]> granicus.if.org Git - llvm/commitdiff
[ARM] GlobalISel: Select G_CONSTANT with CImm operands
authorDiana Picus <diana.picus@linaro.org>
Mon, 24 Apr 2017 06:30:56 +0000 (06:30 +0000)
committerDiana Picus <diana.picus@linaro.org>
Mon, 24 Apr 2017 06:30:56 +0000 (06:30 +0000)
When selecting a G_CONSTANT to a MOVi, we need the value to be an Imm
operand. We used to just leave the G_CONSTANT operand unchanged, which
works in some cases (such as the GEP offsets that we create when
referring to stack slots). However, in many other places the G_CONSTANTs
are created with CImm operands. This patch makes sure to handle those as
well, and to error out gracefully if in the end we don't end up with an
Imm operand.

Thanks to Oliver Stannard for reporting this issue.

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

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

index 3b62c3878c34d81598bb363a1299a504879faf73..a99dc159d1139d5d0247f6941b49d7b374bb78bc 100644 (file)
@@ -351,6 +351,18 @@ bool ARMInstructionSelector::select(MachineInstr &I) const {
            "Expected constant to live in a GPR");
     I.setDesc(TII.get(ARM::MOVi));
     MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
+
+    auto &Val = I.getOperand(1);
+    if (Val.isCImm()) {
+      if (Val.getCImm()->getBitWidth() > 32)
+        return false;
+      Val.ChangeToImmediate(Val.getCImm()->getZExtValue());
+    }
+
+    if (!Val.isImm()) {
+      return false;
+    }
+
     break;
   }
   case G_STORE:
index e3af57990c1f57b7b04615e3744192bcf2733d40..5fd6e93263a1bf691af709d689d98d4368cba8a1 100644 (file)
@@ -30,7 +30,8 @@
   define void @test_stores() #0 { ret void }
 
   define void @test_gep() { ret void }
-  define void @test_constants() { ret void }
+  define void @test_constant_imm() { ret void }
+  define void @test_constant_cimm() { ret void }
 
   define void @test_soft_fp_double() #0 { ret void }
 
@@ -744,8 +745,8 @@ body:             |
     BX_RET 14, _, implicit %r0
 ...
 ---
-name:            test_constants
-# CHECK-LABEL: name: test_constants
+name:            test_constant_imm
+# CHECK-LABEL: name: test_constant_imm
 legalized:       true
 regBankSelected: true
 selected:        false
@@ -762,6 +763,26 @@ body:             |
     BX_RET 14, _, implicit %r0
 ...
 ---
+name:            test_constant_cimm
+# CHECK-LABEL: name: test_constant_cimm
+legalized:       true
+regBankSelected: true
+selected:        false
+# CHECK: selected: true
+registers:
+  - { id: 0, class: gprb }
+# CHECK: id: [[C:[0-9]+]], class: gpr
+body:             |
+  bb.0:
+    ; Adding a type on G_CONSTANT changes its operand from an Imm into a CImm.
+    ; We still want to see the same thing in the output though.
+    %0(s32) = G_CONSTANT i32 42
+    ; CHECK: %[[C]] = MOVi 42, 14, _, _
+
+    %r0 = COPY %0(s32)
+    BX_RET 14, _, implicit %r0
+...
+---
 name:            test_soft_fp_double
 # CHECK-LABEL: name: test_soft_fp_double
 legalized:       true
index 3aae94f9a1095b9488ce22df70c0081911b4112a..da02bfe68519d59d47bc9063d9bf2ba71d2ea9b0 100644 (file)
@@ -7,6 +7,14 @@ entry:
   ret void
 }
 
+define i32 @test_constant_return_i32() {
+; CHECK-LABEL: test_constant_return_i32:
+; CHECK: mov r0, #42
+; CHECK: bx lr
+entry:
+  ret i32 42
+}
+
 define zeroext i1 @test_zext_i1(i1 %x) {
 ; CHECK-LABEL: test_zext_i1
 ; CHECK: and r0, r0, #1