1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[VE] Clean check routines of branch types

Previously, these check routines accepted non-generatble instructions.
This time, I clean them and add assert for those non-generatable
instructions.

Reviewed By: simoll

Differential Revision: https://reviews.llvm.org/D92254
This commit is contained in:
Kazushi (Jam) Marukawa 2020-11-28 11:26:52 +09:00
parent 80cb0524f6
commit 09cebbfd58
2 changed files with 129 additions and 25 deletions

View File

@ -92,38 +92,46 @@ static VECC::CondCode GetOppositeBranchCondition(VECC::CondCode CC) {
llvm_unreachable("Invalid cond code");
}
// Treat br.l [BRCF AT] as unconditional branch
// Treat a branch relative long always instruction as unconditional branch.
// For example, br.l.t and br.l.
static bool isUncondBranchOpcode(int Opc) {
return Opc == VE::BRCFLa || Opc == VE::BRCFWa ||
Opc == VE::BRCFLa_nt || Opc == VE::BRCFWa_nt ||
Opc == VE::BRCFLa_t || Opc == VE::BRCFWa_t ||
Opc == VE::BRCFDa || Opc == VE::BRCFSa ||
Opc == VE::BRCFDa_nt || Opc == VE::BRCFSa_nt ||
Opc == VE::BRCFDa_t || Opc == VE::BRCFSa_t;
using namespace llvm::VE;
#define BRKIND(NAME) (Opc == NAME##a || Opc == NAME##a_nt || Opc == NAME##a_t)
// VE has other branch relative always instructions for word/double/float,
// but we use only long branches in our lower. So, sanity check it here.
assert(!BRKIND(BRCFW) && !BRKIND(BRCFD) && !BRKIND(BRCFS) &&
"Branch relative word/double/float always instructions should not be "
"used!");
return BRKIND(BRCFL);
#undef BRKIND
}
// Treat branch relative conditional as conditional branch instructions.
// For example, brgt.l.t and brle.s.nt.
static bool isCondBranchOpcode(int Opc) {
return Opc == VE::BRCFLrr || Opc == VE::BRCFLir ||
Opc == VE::BRCFLrr_nt || Opc == VE::BRCFLir_nt ||
Opc == VE::BRCFLrr_t || Opc == VE::BRCFLir_t ||
Opc == VE::BRCFWrr || Opc == VE::BRCFWir ||
Opc == VE::BRCFWrr_nt || Opc == VE::BRCFWir_nt ||
Opc == VE::BRCFWrr_t || Opc == VE::BRCFWir_t ||
Opc == VE::BRCFDrr || Opc == VE::BRCFDir ||
Opc == VE::BRCFDrr_nt || Opc == VE::BRCFDir_nt ||
Opc == VE::BRCFDrr_t || Opc == VE::BRCFDir_t ||
Opc == VE::BRCFSrr || Opc == VE::BRCFSir ||
Opc == VE::BRCFSrr_nt || Opc == VE::BRCFSir_nt ||
Opc == VE::BRCFSrr_t || Opc == VE::BRCFSir_t;
using namespace llvm::VE;
#define BRKIND(NAME) \
(Opc == NAME##rr || Opc == NAME##rr_nt || Opc == NAME##rr_t || \
Opc == NAME##ir || Opc == NAME##ir_nt || Opc == NAME##ir_t)
return BRKIND(BRCFL) || BRKIND(BRCFW) || BRKIND(BRCFD) || BRKIND(BRCFS);
#undef BRKIND
}
// Treat branch long always instructions as indirect branch.
// For example, b.l.t and b.l.
static bool isIndirectBranchOpcode(int Opc) {
return Opc == VE::BCFLari || Opc == VE::BCFLari ||
Opc == VE::BCFLari_nt || Opc == VE::BCFLari_nt ||
Opc == VE::BCFLari_t || Opc == VE::BCFLari_t ||
Opc == VE::BCFLari || Opc == VE::BCFLari ||
Opc == VE::BCFLari_nt || Opc == VE::BCFLari_nt ||
Opc == VE::BCFLari_t || Opc == VE::BCFLari_t;
using namespace llvm::VE;
#define BRKIND(NAME) \
(Opc == NAME##ari || Opc == NAME##ari_nt || Opc == NAME##ari_t)
// VE has other branch always instructions for word/double/float, but
// we use only long branches in our lower. So, sanity check it here.
assert(!BRKIND(BCFW) && !BRKIND(BCFD) && !BRKIND(BCFS) &&
"Branch word/double/float always instructions should not be used!");
return BRKIND(BCFL);
#undef BRKIND
}
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target,

View File

@ -0,0 +1,96 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=ve | FileCheck %s
declare void @foo() noreturn
;;; Check a case where a separate branch is needed and where the original
;;; order should be reversed. Copied from SystemZ/branch-08.ll
define i32 @f1(i32 %a, i32 *%bptr) {
; CHECK-LABEL: f1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: st %s9, (, %s11)
; CHECK-NEXT: st %s10, 8(, %s11)
; CHECK-NEXT: or %s9, 0, %s11
; CHECK-NEXT: lea %s11, -240(, %s11)
; CHECK-NEXT: brge.l %s11, %s8, .LBB0_4
; CHECK-NEXT: # %bb.3: # %entry
; CHECK-NEXT: ld %s61, 24(, %s14)
; CHECK-NEXT: or %s62, 0, %s0
; CHECK-NEXT: lea %s63, 315
; CHECK-NEXT: shm.l %s63, (%s61)
; CHECK-NEXT: shm.l %s8, 8(%s61)
; CHECK-NEXT: shm.l %s11, 16(%s61)
; CHECK-NEXT: monc
; CHECK-NEXT: or %s0, 0, %s62
; CHECK-NEXT: .LBB0_4: # %entry
; CHECK-NEXT: ldl.sx %s1, (, %s1)
; CHECK-NEXT: cmpu.w %s0, %s1, %s0
; CHECK-NEXT: brlt.w 0, %s0, .LBB0_2
; CHECK-NEXT: # %bb.1: # %return
; CHECK-NEXT: or %s0, 1, (0)1
; CHECK-NEXT: or %s11, 0, %s9
; CHECK-NEXT: ld %s10, 8(, %s11)
; CHECK-NEXT: ld %s9, (, %s11)
; CHECK-NEXT: b.l.t (, %s10)
; CHECK-NEXT: .LBB0_2: # %callit
; CHECK-NEXT: lea %s0, foo@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s12, foo@hi(, %s0)
; CHECK-NEXT: bsic %s10, (, %s12)
entry:
%b = load i32, i32 *%bptr
%cmp = icmp ult i32 %a, %b
br i1 %cmp, label %callit, label %return
callit:
call void @foo()
unreachable
return:
ret i32 1
}
;;; Same again with a fused compare and branch.
define i32 @f2(i32 %a) {
; CHECK-LABEL: f2:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: st %s9, (, %s11)
; CHECK-NEXT: st %s10, 8(, %s11)
; CHECK-NEXT: or %s9, 0, %s11
; CHECK-NEXT: lea %s11, -240(, %s11)
; CHECK-NEXT: brge.l %s11, %s8, .LBB1_4
; CHECK-NEXT: # %bb.3: # %entry
; CHECK-NEXT: ld %s61, 24(, %s14)
; CHECK-NEXT: or %s62, 0, %s0
; CHECK-NEXT: lea %s63, 315
; CHECK-NEXT: shm.l %s63, (%s61)
; CHECK-NEXT: shm.l %s8, 8(%s61)
; CHECK-NEXT: shm.l %s11, 16(%s61)
; CHECK-NEXT: monc
; CHECK-NEXT: or %s0, 0, %s62
; CHECK-NEXT: .LBB1_4: # %entry
; CHECK-NEXT: breq.w 0, %s0, .LBB1_2
; CHECK-NEXT: # %bb.1: # %return
; CHECK-NEXT: or %s0, 1, (0)1
; CHECK-NEXT: or %s11, 0, %s9
; CHECK-NEXT: ld %s10, 8(, %s11)
; CHECK-NEXT: ld %s9, (, %s11)
; CHECK-NEXT: b.l.t (, %s10)
; CHECK-NEXT: .LBB1_2: # %callit
; CHECK-NEXT: lea %s0, foo@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s12, foo@hi(, %s0)
; CHECK-NEXT: bsic %s10, (, %s12)
entry:
%cmp = icmp eq i32 %a, 0
br i1 %cmp, label %callit, label %return
callit:
call void @foo()
unreachable
return:
ret i32 1
}