[llvm] [GlobalISel][ARM] Legalization of G_CONSTANT using constant pool (PR #98308)
Serge Pavlov via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 10 05:17:50 PDT 2024
https://github.com/spavloff created https://github.com/llvm/llvm-project/pull/98308
ARM uses complex encoding of immediate values using small number of bits. As a result, some values cannot be represented as immediate operands, they need to be synthesized in a register. This change implements ilegalization of such constants with loading values from constant pool.
>From eebd42fce658177202184851dd869412e85439cc Mon Sep 17 00:00:00 2001
From: Serge Pavlov <sepavloff at gmail.com>
Date: Wed, 10 Jul 2024 13:28:53 +0700
Subject: [PATCH] [GlobalISel][ARM] Legalization of G_CONSTANT using constant
pool
ARM uses complex encoding of immediate values using small number of
bits. As a result, some values cannot be represented as immediate
operands, they need to be synthesized in a register. This change
implements ilegalization of such constants with loading values from
constant pool.
---
.../lib/Target/ARM/ARMInstructionSelector.cpp | 20 ++++++++++++
llvm/lib/Target/ARM/ARMLegalizerInfo.cpp | 14 +++++++--
llvm/lib/Target/ARM/ARMLegalizerInfo.h | 2 ++
llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp | 1 +
.../ARM/GlobalISel/arm-legalize-const.mir | 26 ++++++++++++++++
.../ARM/GlobalISel/arm-legalize-fp.mir | 22 +++++++++----
.../ARM/GlobalISel/select-constpool.mir | 31 +++++++++++++++++++
7 files changed, 108 insertions(+), 8 deletions(-)
create mode 100644 llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-const.mir
create mode 100644 llvm/test/CodeGen/ARM/GlobalISel/select-constpool.mir
diff --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
index 3b3c380e1e1b3..713f8da9b05c5 100644
--- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
+++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
@@ -1103,6 +1103,26 @@ bool ARMInstructionSelector::select(MachineInstr &I) {
assert((ValSize != 64 || STI.hasVFP2Base()) &&
"Don't know how to load/store 64-bit value without VFP");
+ MachineInstr *Ptr = MRI.getVRegDef(I.getOperand(1).getReg());
+ if (Ptr->getOpcode() == TargetOpcode::G_CONSTANT_POOL) {
+ unsigned Opcode;
+ if (Subtarget->isThumb())
+ Opcode = ARM::tLDRpci;
+ else
+ Opcode = ARM::LDRcp;
+
+ auto Instr = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
+ .addDef(Reg)
+ .add(Ptr->getOperand(1))
+ .addImm(0)
+ .add(predOps(ARMCC::AL))
+ .addMemOperand(I.memoperands().front());
+ 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 660f351bae64b..b41c6183f2b88 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,14 @@ 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 d6ce4eb1055b4..333e24ba2da62 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 9234881c9407e..2d0619c598987 100644
--- a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp
@@ -367,6 +367,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 0000000000000..6d19c650c6e1c
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-const.mir
@@ -0,0 +1,26 @@
+# 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
+
+--- |
+ define i32 @get_const() {
+ entry:
+ ret i32 287454020
+ }
+...
+---
+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 96461e044813d..a35f82722adaf 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 0000000000000..35d1e932f8d76
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/GlobalISel/select-constpool.mir
@@ -0,0 +1,31 @@
+# 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
+
+--- |
+ define i32 @get_const() {
+ entry:
+ ret i32 287454020
+ }
+...
+---
+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
+...
More information about the llvm-commits
mailing list