diff options
-rw-r--r-- | llvm/lib/Target/ARM/ARMInstructionSelector.cpp | 34 | ||||
-rw-r--r-- | llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir | 25 |
2 files changed, 48 insertions, 11 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp index b0fd0b47692..c4b9d6d25e5 100644 --- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp +++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp @@ -670,14 +670,6 @@ bool ARMInstructionSelector::select(MachineInstr &I, } using namespace TargetOpcode; - if (I.getOpcode() == G_CONSTANT) { - // Pointer constants should be treated the same as 32-bit integer constants. - // Change the type and let TableGen handle it. - unsigned ResultReg = I.getOperand(0).getReg(); - LLT Ty = MRI.getType(ResultReg); - if (Ty.isPointer()) - MRI.setType(ResultReg, LLT::scalar(32)); - } if (selectImpl(I, CoverageInfo)) return true; @@ -788,6 +780,32 @@ bool ARMInstructionSelector::select(MachineInstr &I, I.setDesc(TII.get(COPY)); return selectCopy(I, TII, MRI, TRI, RBI); } + case G_CONSTANT: { + if (!MRI.getType(I.getOperand(0).getReg()).isPointer()) { + // Non-pointer constants should be handled by TableGen. + DEBUG(dbgs() << "Unsupported constant type\n"); + return false; + } + + auto &Val = I.getOperand(1); + if (Val.isCImm()) { + if (!Val.getCImm()->isZero()) { + DEBUG(dbgs() << "Unsupported pointer constant value\n"); + return false; + } + Val.ChangeToImmediate(0); + } else { + assert(Val.isImm() && "Unexpected operand for G_CONSTANT"); + if (Val.getImm() != 0) { + DEBUG(dbgs() << "Unsupported pointer constant value\n"); + return false; + } + } + + I.setDesc(TII.get(ARM::MOVi)); + MIB.add(predOps(ARMCC::AL)).add(condCodeOp()); + break; + } case G_INTTOPTR: case G_PTRTOINT: { auto SrcReg = I.getOperand(1).getReg(); diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir index 8b9b83f6d0e..b6db0e0a75f 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir @@ -47,7 +47,8 @@ define void @test_gep() { ret void } define void @test_constant_imm() { ret void } define void @test_constant_cimm() { ret void } - define void @test_pointer_constant() { ret void } + define void @test_pointer_constant_unconstrained() { ret void } + define void @test_pointer_constant_constrained() { ret void } define void @test_inttoptr_s32() { ret void } define void @test_ptrtoint_s32() { ret void } @@ -1110,8 +1111,8 @@ body: | BX_RET 14, %noreg, implicit %r0 ... --- -name: test_pointer_constant -# CHECK-LABEL: name: test_pointer_constant +name: test_pointer_constant_unconstrained +# CHECK-LABEL: name: test_pointer_constant_unconstrained legalized: true regBankSelected: true selected: false @@ -1123,10 +1124,28 @@ body: | %0(p0) = G_CONSTANT i32 0 ; CHECK: %[[C:[0-9]+]]:gpr = MOVi 0, 14, %noreg, %noreg + ; This leaves %0 unconstrained before the G_CONSTANT is selected. %r0 = COPY %0(p0) BX_RET 14, %noreg, implicit %r0 ... --- +name: test_pointer_constant_constrained +# CHECK-LABEL: name: test_pointer_constant_constrained +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +registers: + - { id: 0, class: gprb } +body: | + bb.0: + %0(p0) = G_CONSTANT i32 0 + ; CHECK: %[[C:[0-9]+]]:gpr = MOVi 0, 14, %noreg, %noreg + + ; This constrains %0 before the G_CONSTANT is selected. + G_STORE %0(p0), %0(p0) :: (store 4) +... +--- name: test_inttoptr_s32 # CHECK-LABEL: name: test_inttoptr_s32 legalized: true |