diff --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp index 3b3c380e1e1b32..ea18e6652c656f 100644 --- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp +++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp @@ -14,6 +14,7 @@ #include "ARMSubtarget.h" #include "ARMTargetMachine.h" #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" +#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineRegisterInfo.h" @@ -1088,7 +1089,7 @@ bool ARMInstructionSelector::select(MachineInstr &I) { return selectGlobal(MIB, MRI); case G_STORE: case G_LOAD: { - const auto &MemOp = **I.memoperands_begin(); + auto &MemOp = **I.memoperands_begin(); if (MemOp.isAtomic()) { LLVM_DEBUG(dbgs() << "Atomic load/store not supported yet\n"); return false; @@ -1103,6 +1104,26 @@ bool ARMInstructionSelector::select(MachineInstr &I) { assert((ValSize != 64 || STI.hasVFP2Base()) && "Don't know how to load/store 64-bit value without VFP"); + if (auto *LoadMI = dyn_cast(&I)) { + Register PtrReg = LoadMI->getPointerReg(); + MachineInstr *Ptr = MRI.getVRegDef(PtrReg); + if (Ptr->getOpcode() == TargetOpcode::G_CONSTANT_POOL) { + const MachineOperand &Index = Ptr->getOperand(1); + unsigned Opcode = Subtarget->isThumb() ? ARM::tLDRpci : ARM::LDRcp; + + auto Instr = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode)) + .addDef(Reg) + .add(Index) + .addImm(0) + .add(predOps(ARMCC::AL)) + .addMemOperand(&MemOp); + if (!constrainSelectedInstRegOperands(*Instr, TII, TRI, RBI)) + return false; + I.eraseFromParent(); + return true; + } + } + const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize); if (NewOpc == G_LOAD || NewOpc == G_STORE) return false; diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp index 660f351bae64b7..452e908fdad98f 100644 --- a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp +++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp @@ -29,7 +29,7 @@ static bool AEABI(const ARMSubtarget &ST) { return ST.isTargetAEABI() || ST.isTargetGNUAEABI() || ST.isTargetMuslAEABI(); } -ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) { +ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) : ST(ST) { using namespace TargetOpcode; const LLT p0 = LLT::pointer(0, 32); @@ -99,9 +99,11 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) { .minScalar(0, s32); getActionDefinitionsBuilder(G_CONSTANT) - .legalFor({s32, p0}) + .customFor({s32, p0}) .clampScalar(0, s32, s32); + getActionDefinitionsBuilder(G_CONSTANT_POOL).legalFor({p0}); + getActionDefinitionsBuilder(G_ICMP) .legalForCartesianProduct({s1}, {s32, p0}) .minScalar(1, s32); @@ -435,6 +437,13 @@ bool ARMLegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, } break; } + case G_CONSTANT: { + const ConstantInt *ConstVal = MI.getOperand(1).getCImm(); + uint64_t ImmVal = ConstVal->getZExtValue(); + if (ConstantMaterializationCost(ImmVal, &ST) > 2 && !ST.genExecuteOnly()) + return Helper.lowerConstant(MI) == LegalizerHelper::Legalized; + return true; + } case G_FCONSTANT: { // Convert to integer constants, while preserving the binary representation. auto AsInteger = diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.h b/llvm/lib/Target/ARM/ARMLegalizerInfo.h index 9e10638233e6d1..f7edf0b1612c53 100644 --- a/llvm/lib/Target/ARM/ARMLegalizerInfo.h +++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.h @@ -59,6 +59,8 @@ class ARMLegalizerInfo : public LegalizerInfo { // Get the libcall(s) corresponding to \p Predicate for operands of \p Size // bits. FCmpLibcallsList getFCmpLibcalls(CmpInst::Predicate, unsigned Size) const; + + const ARMSubtarget &ST; }; } // End llvm namespace. #endif diff --git a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp index 447db18b8defa1..0493fd9e317d5c 100644 --- a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp +++ b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp @@ -329,6 +329,7 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { case G_CONSTANT: case G_FRAME_INDEX: case G_GLOBAL_VALUE: + case G_CONSTANT_POOL: OperandsMapping = getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); break; diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-const.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-const.mir new file mode 100644 index 00000000000000..70d4a527493c3a --- /dev/null +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-const.mir @@ -0,0 +1,20 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +# RUN: llc -mtriple arm-- -run-pass=legalizer %s -o - | FileCheck %s + +--- +name: get_const +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +body: | + bb.1.entry: + ; CHECK-LABEL: name: get_const + ; CHECK: [[CONSTANT_POOL:%[0-9]+]]:_(p0) = G_CONSTANT_POOL %const.0 + ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[CONSTANT_POOL]](p0) :: (load (s32) from constant-pool) + ; CHECK-NEXT: $r0 = COPY [[LOAD]](s32) + ; CHECK-NEXT: MOVPCLR 14 /* CC::al */, $noreg, implicit $r0 + %0:_(s32) = G_CONSTANT i32 287454020 + $r0 = COPY %0(s32) + MOVPCLR 14 /* CC::al */, $noreg, implicit $r0 +... diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir index 96461e044813d4..a35f82722adaf4 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir @@ -1,9 +1,9 @@ # RUN: llc -O0 -mtriple arm-linux-gnueabihf -mattr=+vfp2 -float-abi=hard -run-pass=legalizer %s -o - | FileCheck %s -check-prefix CHECK -check-prefix HARD -# RUN: llc -O0 -mtriple arm-linux-gnueabi -mattr=+vfp2,+soft-float -float-abi=soft -run-pass=legalizer %s -o - | FileCheck %s -check-prefix CHECK -check-prefix SOFT -check-prefix SOFT-AEABI -# RUN: llc -O0 -mtriple arm-linux-gnu -mattr=+soft-float -float-abi=soft -run-pass=legalizer %s -o - | FileCheck %s -check-prefix CHECK -check-prefix SOFT -check-prefix SOFT-DEFAULT +# RUN: llc -O0 -mtriple arm-linux-gnueabi -mattr=+vfp2,+soft-float -float-abi=soft -run-pass=legalizer %s -o - | FileCheck %s -check-prefix CHECK -check-prefix SOFT -check-prefix SOFT-AEABI -check-prefix SOFT_POOL +# RUN: llc -O0 -mtriple arm-linux-gnu -mattr=+soft-float -float-abi=soft -run-pass=legalizer %s -o - | FileCheck %s -check-prefix CHECK -check-prefix SOFT -check-prefix SOFT-DEFAULT -check-prefix SOFT_POOL # RUN: llc -O0 -mtriple thumb-linux-gnueabihf -mattr=+v6t2,+vfp2 -float-abi=hard -run-pass=legalizer %s -o - | FileCheck %s -check-prefix CHECK -check-prefix HARD -# RUN: llc -O0 -mtriple thumb-linux-gnueabi -mattr=+v6t2,+vfp2,+soft-float -float-abi=soft -run-pass=legalizer %s -o - | FileCheck %s -check-prefix CHECK -check-prefix SOFT -check-prefix SOFT-AEABI -# RUN: llc -O0 -mtriple thumb-linux-gnu -mattr=+v6t2,+soft-float -float-abi=soft -run-pass=legalizer %s -o - | FileCheck %s -check-prefix CHECK -check-prefix SOFT -check-prefix SOFT-DEFAULT +# RUN: llc -O0 -mtriple thumb-linux-gnueabi -mattr=+v6t2,+vfp2,+soft-float -float-abi=soft -run-pass=legalizer %s -o - | FileCheck %s -check-prefix CHECK -check-prefix SOFT -check-prefix=SOFT-AEABI -check-prefix SOFT_CONST +# RUN: llc -O0 -mtriple thumb-linux-gnu -mattr=+v6t2,+soft-float -float-abi=soft -run-pass=legalizer %s -o - | FileCheck %s -check-prefix CHECK -check-prefix SOFT -check-prefix SOFT-DEFAULT -check-prefix SOFT_CONST --- | define void @test_frem_float() { ret void } define void @test_frem_double() { ret void } @@ -657,10 +657,20 @@ body: | bb.0: liveins: + ; SOFT_POOL: constants: + ; SOFT_POOL: id: 0 + ; SOFT_POOL: value: i32 -1073532109 + ; SOFT_POOL: id: 1 + ; SOFT_POOL: value: i32 858993459 + ; HARD: [[R:%[0-9]+]]:_(s64) = G_FCONSTANT double -2.4 ; SOFT-NOT: G_FCONSTANT - ; SOFT-DAG: [[HI:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1073532109 - ; SOFT-DAG: [[LO:%[0-9]+]]:_(s32) = G_CONSTANT i32 858993459 + ; SOFT_CONST-DAG: [[HI:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1073532109 + ; SOFT_CONST-DAG: [[LO:%[0-9]+]]:_(s32) = G_CONSTANT i32 858993459 + ; SOFT_POOL-DAG: [[HIPTR:%[0-9]+]]:_(p0) = G_CONSTANT_POOL %const.0 + ; SOFT_POOL-DAG: [[HI:%[0-9]+]]:_(s32) = G_LOAD [[HIPTR]] + ; SOFT_POOL-DAG: [[LOPTR:%[0-9]+]]:_(p0) = G_CONSTANT_POOL %const.1 + ; SOFT_POOL-DAG: [[LO:%[0-9]+]]:_(s32) = G_LOAD [[LOPTR]] ; SOFT-NOT: G_FCONSTANT %0(s64) = G_FCONSTANT double -2.4 ; HARD-DAG: G_UNMERGE_VALUES [[R]](s64) diff --git a/llvm/test/CodeGen/ARM/GlobalISel/select-constpool.mir b/llvm/test/CodeGen/ARM/GlobalISel/select-constpool.mir new file mode 100644 index 00000000000000..1c16c37e8b5cd5 --- /dev/null +++ b/llvm/test/CodeGen/ARM/GlobalISel/select-constpool.mir @@ -0,0 +1,25 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +# RUN: llc -mtriple arm-- -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s + +--- +name: get_const +legalized: true +regBankSelected: true +selected: false +tracksRegLiveness: true +constants: + - id: 0 + value: i32 287454020 + alignment: 4 + isTargetSpecific: false +body: | + bb.1.entry: + ; CHECK-LABEL: name: get_const + ; CHECK: [[LDRcp:%[0-9]+]]:gpr = LDRcp %const.0, 0, 14 /* CC::al */, $noreg :: (load (s32) from constant-pool) + ; CHECK-NEXT: $r0 = COPY [[LDRcp]] + ; CHECK-NEXT: MOVPCLR 14 /* CC::al */, $noreg, implicit $r0 + %1:gprb(p0) = G_CONSTANT_POOL %const.0 + %0:gprb(s32) = G_LOAD %1(p0) :: (load (s32) from constant-pool) + $r0 = COPY %0(s32) + MOVPCLR 14 /* CC::al */, $noreg, implicit $r0 +...