]> granicus.if.org Git - llvm/commitdiff
[ARM] GlobalISel: Support G_BRCOND
authorDiana Picus <diana.picus@linaro.org>
Fri, 14 Jul 2017 09:46:06 +0000 (09:46 +0000)
committerDiana Picus <diana.picus@linaro.org>
Fri, 14 Jul 2017 09:46:06 +0000 (09:46 +0000)
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).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@308009 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMInstructionSelector.cpp
lib/Target/ARM/ARMLegalizerInfo.cpp
lib/Target/ARM/ARMRegisterBankInfo.cpp
test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir
test/CodeGen/ARM/GlobalISel/arm-isel.ll
test/CodeGen/ARM/GlobalISel/arm-legalizer.mir
test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir

index 29ef69ad0010fdbd4c89d22cb152a2de0b9038e6..faed6b867e2bc7d40d916d7e126238555dad70fd 100644 (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;
   }
index f23e62595d2e9f9a247d4d6e2f53261a3129e4fb..4863499e2146bbfa59d4121ac7d613fd4cfc27a8 100644 (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);
index 6e93aafc2ade704548b54e28f45ec93284bb8448..84493023589489a7aad17f8da3cce85e966ea073 100644 (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();
   }
index 3870b58a7a0e3131ed6ed09eacb1b6690747a277..0e3ef479bc3c8bb4408a92fe00aa1c2a24547f4d 100644 (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)
+
+    G_BR %bb.2
+    ; CHECK: B %bb.2
 
-    ; CHECK: B %bb.1
-    G_BR %bb.1
+  bb.2:
+  ; CHECK: bb.2
+
+    BX_RET 14, _
+    ; CHECK: BX_RET 14, _
 ...
 ---
 name:            test_soft_fp_double
index b763b48c47496c06b20ded9b0ff839d4ddfe876f..419bcf71c106574d97f087ef8254cf4023ab14eb 100644 (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
+}
index 4575341dfc290dd5f89488f4ab5634e0c5c3bd28..616f29d3b0689c3ff8966b41fc867eabb0ac3485 100644 (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
index 28053ed459602124b1a6d32a5219dd1bf515f8ed..638c6e6209266daa6b33dd32bdae3dd19c2616f5 100644 (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, _
 
 ...
 ---