1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-20 19:42:54 +02:00

[ARM] GlobalISel: Support G_BRCOND

Insert a TSTri to set the flags and a Bcc to branch based on their
values. This is a bit inefficient in the (common) cases where the
condition for the branch comes from a compare right before the branch,
since we set the flags both as part of the compare lowering and as part
of the branch lowering. We're going to live with that until we settle on
a principled way to handle this kind of situation, which occurs with
other patterns as well (combines might be the way forward here).

llvm-svn: 308009
This commit is contained in:
Diana Picus 2017-07-14 09:46:06 +00:00
parent b597a7a7fd
commit b4ef650c0e
7 changed files with 131 additions and 10 deletions

View File

@ -722,6 +722,29 @@ bool ARMInstructionSelector::select(MachineInstr &I) const {
return false;
break;
}
case G_BRCOND: {
if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");
return false;
}
// Set the flags.
auto Test = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::TSTri))
.addReg(I.getOperand(0).getReg())
.addImm(1)
.add(predOps(ARMCC::AL));
if (!constrainSelectedInstRegOperands(*Test, TII, TRI, RBI))
return false;
// Branch conditionally.
auto Branch = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::Bcc))
.add(I.getOperand(1))
.add(predOps(ARMCC::EQ, ARM::CPSR));
if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
return false;
I.eraseFromParent();
return true;
}
default:
return false;
}

View File

@ -88,6 +88,8 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
setAction({G_SELECT, p0}, Legal);
setAction({G_SELECT, 1, s1}, Legal);
setAction({G_BRCOND, s1}, Legal);
setAction({G_CONSTANT, s32}, Legal);
for (auto Ty : {s1, s8, s16})
setAction({G_CONSTANT, Ty}, WidenScalar);

View File

@ -334,6 +334,10 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
case G_BR:
OperandsMapping = getOperandsMapping({nullptr});
break;
case G_BRCOND:
OperandsMapping =
getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
break;
default:
return getInvalidInstructionMapping();
}

View File

@ -1181,17 +1181,35 @@ legalized: true
regBankSelected: true
selected: false
# CHECK: selected: true
registers:
- { id: 0, class: gprb }
body: |
; CHECK: bb.0
bb.0:
successors: %bb.1(0x80000000)
; CHECK: bb.0
successors: %bb.1(0x40000000), %bb.2(0x40000000)
liveins: %r0
%0(s1) = COPY %r0
; CHECK: [[COND:%[0-9]+]] = COPY %r0
G_BRCOND %0(s1), %bb.1
; CHECK: TSTri [[COND]], 1, 14, _, implicit-def %cpsr
; CHECK: Bcc %bb.1, 0, %cpsr
G_BR %bb.2
; CHECK: B %bb.2
; CHECK: bb.1
bb.1:
successors: %bb.1(0x80000000)
; CHECK: bb.1
successors: %bb.2(0x80000000)
; CHECK: B %bb.1
G_BR %bb.1
G_BR %bb.2
; CHECK: B %bb.2
bb.2:
; CHECK: bb.2
BX_RET 14, _
; CHECK: BX_RET 14, _
...
---
name: test_soft_fp_double

View File

@ -431,3 +431,31 @@ entry:
infinite:
br label %infinite
}
declare arm_aapcscc void @brcond1()
declare arm_aapcscc void @brcond2()
define arm_aapcscc void @test_brcond(i32 %n) {
; CHECK-LABEL: test_brcond
; CHECK: cmp r0
; CHECK-NEXT: movgt [[RCMP:r[0-9]+]], #1
; CHECK: tst [[RCMP]], #1
; CHECK-NEXT: bne [[FALSE:.L[[:alnum:]_]+]]
; CHECK: blx brcond1
; CHECK: [[FALSE]]:
; CHECK: blx brcond2
entry:
%cmp = icmp sgt i32 %n, 0
br i1 %cmp, label %if.true, label %if.false
if.true:
call arm_aapcscc void @brcond1()
br label %if.end
if.false:
call arm_aapcscc void @brcond2()
br label %if.end
if.end:
ret void
}

View File

@ -42,6 +42,8 @@
define void @test_select_s32() { ret void }
define void @test_select_ptr() { ret void }
define void @test_brcond() { ret void }
define void @test_fadd_s32() #0 { ret void }
define void @test_fadd_s64() #0 { ret void }
@ -863,6 +865,40 @@ body: |
BX_RET 14, _, implicit %r0
...
---
name: test_brcond
# CHECK-LABEL: name: test_brcond
legalized: false
# CHECK: legalized: true
regBankSelected: false
selected: false
tracksRegLiveness: true
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
body: |
bb.0:
successors: %bb.1(0x40000000), %bb.2(0x40000000)
liveins: %r0, %r1
%0(s32) = COPY %r0
%1(s32) = COPY %r1
%2(s1) = G_ICMP intpred(sgt), %0(s32), %1
G_BRCOND %2(s1), %bb.1
; G_BRCOND with s1 is legal, so we should find it unchanged in the output
; CHECK: G_BRCOND {{%[0-9]+}}(s1), %bb.1
G_BR %bb.2
bb.1:
%r0 = COPY %1(s32)
BX_RET 14, _, implicit %r0
bb.2:
%r0 = COPY %0(s32)
BX_RET 14, _, implicit %r0
...
---
name: test_fadd_s32
# CHECK-LABEL: name: test_fadd_s32
legalized: false

View File

@ -837,16 +837,26 @@ name: test_br
legalized: true
regBankSelected: false
# CHECK: regBankSelected: true
# There aren't any registers to map, but make sure we don't crash.
selected: false
registers:
- { id: 0, class: _ }
# CHECK: { id: 0, class: gprb, preferred-register: '' }
# Check that we map the condition of the G_BRCOND into the GPR.
# For the G_BR, there are no registers to map, but make sure we don't crash.
body: |
bb.0:
successors: %bb.1(0x80000000)
successors: %bb.1(0x40000000), %bb.2(0x40000000)
liveins: %r0
%0(s1) = COPY %r0
G_BRCOND %0(s1), %bb.1
G_BR %bb.2
bb.1:
successors: %bb.1(0x80000000)
BX_RET 14, _
G_BR %bb.1
bb.2:
BX_RET 14, _
...
---