[llvm] [GlobalISel][ARM] Selection of G_CONSTANT using constant pool (PR #96225)
Serge Pavlov via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 20 11:47:41 PDT 2024
https://github.com/spavloff created https://github.com/llvm/llvm-project/pull/96225
Some constants cannot be represented as immediate operands. They can be loaded from constant pool. This change implement selection of such constants in the same way as the DAG selector uses.
>From ed5db9a1cd7c6f84136123036bf0f3cf08a8f6b8 Mon Sep 17 00:00:00 2001
From: Serge Pavlov <sepavloff at gmail.com>
Date: Fri, 21 Jun 2024 00:04:28 +0700
Subject: [PATCH] [GlobalISel][ARM] Selection of G_CONSTANT using constant pool
Some constants cannot be represented as immediate operands. They can
be loaded from constant pool. This change implement selection of such
constants in the same way as the DAG selector uses.
---
.../lib/Target/ARM/ARMInstructionSelector.cpp | 58 +++++++++++++++++++
.../CodeGen/ARM/GlobalISel/select-const.mir | 19 ++++++
2 files changed, 77 insertions(+)
diff --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
index 3b3c380e1e1b3..ebbf569e499e2 100644
--- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
+++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
@@ -61,6 +61,10 @@ class ARMInstructionSelector : public InstructionSelector {
bool selectSelect(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
bool selectShift(unsigned ShiftOpc, MachineInstrBuilder &MIB) const;
+ bool selectConstantUsingPool(MachineInstrBuilder &MIB) const;
+ void emitLoadFromConstantPool(const Register DefReg, const Constant *CPVal,
+ MachineInstrBuilder &MIB) const;
+
// Check if the types match and both operands have the expected size and
// register bank.
bool validOpRegPair(MachineRegisterInfo &MRI, unsigned LHS, unsigned RHS,
@@ -812,6 +816,57 @@ bool ARMInstructionSelector::selectShift(unsigned ShiftOpc,
return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
}
+bool ARMInstructionSelector::selectConstantUsingPool(
+ MachineInstrBuilder &MIB) const {
+ MachineInstr &MI = *MIB;
+ assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && "Expected G_CONSTANT");
+
+ const Register DefReg = MI.getOperand(0).getReg();
+ MachineOperand &ConstOperand = MI.getOperand(1);
+ if (!ConstOperand.isCImm())
+ return false;
+ const Constant *ConstVal = ConstOperand.getCImm();
+ uint64_t ImmVal = ConstOperand.getCImm()->getZExtValue();
+
+ if (ConstantMaterializationCost(ImmVal, Subtarget) > 2 &&
+ !Subtarget->genExecuteOnly()) {
+ emitLoadFromConstantPool(DefReg, ConstVal, MIB);
+ MI.eraseFromParent();
+ return true;
+ }
+
+ return false;
+}
+
+void ARMInstructionSelector::emitLoadFromConstantPool(
+ const Register DefReg, const Constant *ConstVal,
+ MachineInstrBuilder &MIB) const {
+ MachineBasicBlock &MBB = *MIB->getParent();
+ MachineFunction &MF = *MBB.getParent();
+ const DataLayout &DL = MF.getDataLayout();
+
+ auto InsertBefore = std::next(MIB->getIterator());
+ auto &DbgLoc = MIB->getDebugLoc();
+
+ Type *ConstTy = ConstVal->getType();
+ unsigned Size = DL.getTypeStoreSize(ConstTy);
+ Align Alignment = DL.getPrefTypeAlign(ConstTy);
+
+ MachineConstantPool *Pool = MF.getConstantPool();
+ unsigned ConstIndex = Pool->getConstantPoolIndex(ConstVal, Alignment);
+
+ auto Load = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::LDRcp))
+ .addDef(DefReg)
+ .addConstantPoolIndex(ConstIndex)
+ .addImm(0)
+ .add(predOps(ARMCC::AL));
+ MachinePointerInfo PtrInfo = MachinePointerInfo::getConstantPool(MF);
+ Load->addMemOperand(MF, MF.getMachineMemOperand(PtrInfo,
+ MachineMemOperand::MOLoad,
+ Size, Alignment));
+ constrainSelectedInstRegOperands(*Load, TII, TRI, RBI);
+}
+
void ARMInstructionSelector::renderVFPF32Imm(
MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst,
int OpIdx) const {
@@ -970,6 +1025,9 @@ bool ARMInstructionSelector::select(MachineInstr &I) {
return selectCopy(I, TII, MRI, TRI, RBI);
}
case G_CONSTANT: {
+ if (selectConstantUsingPool(MIB))
+ return true;
+
if (!MRI.getType(I.getOperand(0).getReg()).isPointer()) {
// Non-pointer constants should be handled by TableGen.
LLVM_DEBUG(dbgs() << "Unsupported constant type\n");
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/select-const.mir b/llvm/test/CodeGen/ARM/GlobalISel/select-const.mir
index 5a1ea32a91c9e..5fd83f8937f96 100644
--- a/llvm/test/CodeGen/ARM/GlobalISel/select-const.mir
+++ b/llvm/test/CodeGen/ARM/GlobalISel/select-const.mir
@@ -23,3 +23,22 @@ body: |
MOVPCLR 14 /* CC::al */, $noreg, implicit $r0
...
+---
+name: get_from_constpool
+legalized: true
+regBankSelected: true
+selected: false
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: gprb, preferred-register: '' }
+body: |
+ bb.1.entry:
+ ; CHECK-LABEL: name: get_from_constpool
+ ; 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: BX_RET 14 /* CC::al */, $noreg, implicit $r0
+ %0:gprb(s32) = G_CONSTANT i32 287454020
+ $r0 = COPY %0(s32)
+ BX_RET 14 /* CC::al */, $noreg, implicit $r0
+
+...
More information about the llvm-commits
mailing list