Skip to content

Commit 52e5683

Browse files
spavloffarsenm
andauthored
[GlobalISel][ARM] Legalization of G_CONSTANT using constant pool (llvm#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 legalization of such constants with loading values from constant pool. --------- Co-authored-by: Matt Arsenault <[email protected]>
1 parent fe1e1e3 commit 52e5683

File tree

7 files changed

+97
-9
lines changed

7 files changed

+97
-9
lines changed

llvm/lib/Target/ARM/ARMInstructionSelector.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "ARMSubtarget.h"
1515
#include "ARMTargetMachine.h"
1616
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
17+
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
1718
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
1819
#include "llvm/CodeGen/MachineConstantPool.h"
1920
#include "llvm/CodeGen/MachineRegisterInfo.h"
@@ -1088,7 +1089,7 @@ bool ARMInstructionSelector::select(MachineInstr &I) {
10881089
return selectGlobal(MIB, MRI);
10891090
case G_STORE:
10901091
case G_LOAD: {
1091-
const auto &MemOp = **I.memoperands_begin();
1092+
auto &MemOp = **I.memoperands_begin();
10921093
if (MemOp.isAtomic()) {
10931094
LLVM_DEBUG(dbgs() << "Atomic load/store not supported yet\n");
10941095
return false;
@@ -1103,6 +1104,26 @@ bool ARMInstructionSelector::select(MachineInstr &I) {
11031104
assert((ValSize != 64 || STI.hasVFP2Base()) &&
11041105
"Don't know how to load/store 64-bit value without VFP");
11051106

1107+
if (auto *LoadMI = dyn_cast<GLoad>(&I)) {
1108+
Register PtrReg = LoadMI->getPointerReg();
1109+
MachineInstr *Ptr = MRI.getVRegDef(PtrReg);
1110+
if (Ptr->getOpcode() == TargetOpcode::G_CONSTANT_POOL) {
1111+
const MachineOperand &Index = Ptr->getOperand(1);
1112+
unsigned Opcode = Subtarget->isThumb() ? ARM::tLDRpci : ARM::LDRcp;
1113+
1114+
auto Instr = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
1115+
.addDef(Reg)
1116+
.add(Index)
1117+
.addImm(0)
1118+
.add(predOps(ARMCC::AL))
1119+
.addMemOperand(&MemOp);
1120+
if (!constrainSelectedInstRegOperands(*Instr, TII, TRI, RBI))
1121+
return false;
1122+
I.eraseFromParent();
1123+
return true;
1124+
}
1125+
}
1126+
11061127
const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
11071128
if (NewOpc == G_LOAD || NewOpc == G_STORE)
11081129
return false;

llvm/lib/Target/ARM/ARMLegalizerInfo.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static bool AEABI(const ARMSubtarget &ST) {
2929
return ST.isTargetAEABI() || ST.isTargetGNUAEABI() || ST.isTargetMuslAEABI();
3030
}
3131

32-
ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
32+
ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) : ST(ST) {
3333
using namespace TargetOpcode;
3434

3535
const LLT p0 = LLT::pointer(0, 32);
@@ -99,9 +99,11 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
9999
.minScalar(0, s32);
100100

101101
getActionDefinitionsBuilder(G_CONSTANT)
102-
.legalFor({s32, p0})
102+
.customFor({s32, p0})
103103
.clampScalar(0, s32, s32);
104104

105+
getActionDefinitionsBuilder(G_CONSTANT_POOL).legalFor({p0});
106+
105107
getActionDefinitionsBuilder(G_ICMP)
106108
.legalForCartesianProduct({s1}, {s32, p0})
107109
.minScalar(1, s32);
@@ -435,6 +437,13 @@ bool ARMLegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
435437
}
436438
break;
437439
}
440+
case G_CONSTANT: {
441+
const ConstantInt *ConstVal = MI.getOperand(1).getCImm();
442+
uint64_t ImmVal = ConstVal->getZExtValue();
443+
if (ConstantMaterializationCost(ImmVal, &ST) > 2 && !ST.genExecuteOnly())
444+
return Helper.lowerConstant(MI) == LegalizerHelper::Legalized;
445+
return true;
446+
}
438447
case G_FCONSTANT: {
439448
// Convert to integer constants, while preserving the binary representation.
440449
auto AsInteger =

llvm/lib/Target/ARM/ARMLegalizerInfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ class ARMLegalizerInfo : public LegalizerInfo {
5959
// Get the libcall(s) corresponding to \p Predicate for operands of \p Size
6060
// bits.
6161
FCmpLibcallsList getFCmpLibcalls(CmpInst::Predicate, unsigned Size) const;
62+
63+
const ARMSubtarget &ST;
6264
};
6365
} // End llvm namespace.
6466
#endif

llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
329329
case G_CONSTANT:
330330
case G_FRAME_INDEX:
331331
case G_GLOBAL_VALUE:
332+
case G_CONSTANT_POOL:
332333
OperandsMapping =
333334
getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
334335
break;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
2+
# RUN: llc -mtriple arm-- -run-pass=legalizer %s -o - | FileCheck %s
3+
4+
---
5+
name: get_const
6+
legalized: false
7+
regBankSelected: false
8+
selected: false
9+
tracksRegLiveness: true
10+
body: |
11+
bb.1.entry:
12+
; CHECK-LABEL: name: get_const
13+
; CHECK: [[CONSTANT_POOL:%[0-9]+]]:_(p0) = G_CONSTANT_POOL %const.0
14+
; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[CONSTANT_POOL]](p0) :: (load (s32) from constant-pool)
15+
; CHECK-NEXT: $r0 = COPY [[LOAD]](s32)
16+
; CHECK-NEXT: MOVPCLR 14 /* CC::al */, $noreg, implicit $r0
17+
%0:_(s32) = G_CONSTANT i32 287454020
18+
$r0 = COPY %0(s32)
19+
MOVPCLR 14 /* CC::al */, $noreg, implicit $r0
20+
...

llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# 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
2-
# 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
3-
# 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
2+
# 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
3+
# 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
44
# 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
5-
# 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
6-
# 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
5+
# 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
6+
# 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
77
--- |
88
define void @test_frem_float() { ret void }
99
define void @test_frem_double() { ret void }
@@ -657,10 +657,20 @@ body: |
657657
bb.0:
658658
liveins:
659659
660+
; SOFT_POOL: constants:
661+
; SOFT_POOL: id: 0
662+
; SOFT_POOL: value: i32 -1073532109
663+
; SOFT_POOL: id: 1
664+
; SOFT_POOL: value: i32 858993459
665+
660666
; HARD: [[R:%[0-9]+]]:_(s64) = G_FCONSTANT double -2.4
661667
; SOFT-NOT: G_FCONSTANT
662-
; SOFT-DAG: [[HI:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1073532109
663-
; SOFT-DAG: [[LO:%[0-9]+]]:_(s32) = G_CONSTANT i32 858993459
668+
; SOFT_CONST-DAG: [[HI:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1073532109
669+
; SOFT_CONST-DAG: [[LO:%[0-9]+]]:_(s32) = G_CONSTANT i32 858993459
670+
; SOFT_POOL-DAG: [[HIPTR:%[0-9]+]]:_(p0) = G_CONSTANT_POOL %const.0
671+
; SOFT_POOL-DAG: [[HI:%[0-9]+]]:_(s32) = G_LOAD [[HIPTR]]
672+
; SOFT_POOL-DAG: [[LOPTR:%[0-9]+]]:_(p0) = G_CONSTANT_POOL %const.1
673+
; SOFT_POOL-DAG: [[LO:%[0-9]+]]:_(s32) = G_LOAD [[LOPTR]]
664674
; SOFT-NOT: G_FCONSTANT
665675
%0(s64) = G_FCONSTANT double -2.4
666676
; HARD-DAG: G_UNMERGE_VALUES [[R]](s64)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
2+
# RUN: llc -mtriple arm-- -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
3+
4+
---
5+
name: get_const
6+
legalized: true
7+
regBankSelected: true
8+
selected: false
9+
tracksRegLiveness: true
10+
constants:
11+
- id: 0
12+
value: i32 287454020
13+
alignment: 4
14+
isTargetSpecific: false
15+
body: |
16+
bb.1.entry:
17+
; CHECK-LABEL: name: get_const
18+
; CHECK: [[LDRcp:%[0-9]+]]:gpr = LDRcp %const.0, 0, 14 /* CC::al */, $noreg :: (load (s32) from constant-pool)
19+
; CHECK-NEXT: $r0 = COPY [[LDRcp]]
20+
; CHECK-NEXT: MOVPCLR 14 /* CC::al */, $noreg, implicit $r0
21+
%1:gprb(p0) = G_CONSTANT_POOL %const.0
22+
%0:gprb(s32) = G_LOAD %1(p0) :: (load (s32) from constant-pool)
23+
$r0 = COPY %0(s32)
24+
MOVPCLR 14 /* CC::al */, $noreg, implicit $r0
25+
...

0 commit comments

Comments
 (0)