Skip to content

Commit 5eb9f58

Browse files
committedApr 28, 2018
[globalisel][legalizerinfo] Introduce dedicated extending loads and add lowerings for them
Summary: Previously, a extending load was represented at (G_*EXT (G_LOAD x)). This had a few drawbacks: * G_LOAD had to be legal for all sizes you could extend from, even if registers didn't naturally hold those sizes. * All sizes you could extend from had to be allocatable just in case the extend went missing (e.g. by optimization). * At minimum, G_*EXT and G_TRUNC had to be legal for these sizes. As we improve optimization of extends and truncates, this legality requirement would spread without considerable care w.r.t when certain combines were permitted. * The SelectionDAG importer required some ugly and fragile pattern rewriting to translate patterns into this style. This patch begins changing the representation to: * (G_[SZ]EXTLOAD x) * (G_LOAD x) any-extends when MMO.getSize() * 8 < ResultTy.getSizeInBits() which resolves these issues by allowing targets to work entirely in their native register sizes, and by having a more direct translation from SelectionDAG patterns. This patch introduces the new generic instructions and new variation on G_LOAD and adds lowering for them to convert back to the existing representations. Depends on D45466 Reviewers: ab, aditya_nandakumar, bogner, rtereshin, volkan, rovka, aemerson, javed.absar Reviewed By: aemerson Subscribers: aemerson, kristof.beyls, javed.absar, llvm-commits Differential Revision: https://reviews.llvm.org/D45540 llvm-svn: 331115
1 parent 2d2698c commit 5eb9f58

File tree

9 files changed

+167
-6
lines changed

9 files changed

+167
-6
lines changed
 

Diff for: ‎llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

+12
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,18 @@ class MachineIRBuilderBase {
521521
MachineInstrBuilder buildLoad(unsigned Res, unsigned Addr,
522522
MachineMemOperand &MMO);
523523

524+
/// Build and insert `Res = <opcode> Addr, MMO`.
525+
///
526+
/// Loads the value stored at \p Addr. Puts the result in \p Res.
527+
///
528+
/// \pre setBasicBlock or setMI must have been called.
529+
/// \pre \p Res must be a generic virtual register.
530+
/// \pre \p Addr must be a generic virtual register with pointer type.
531+
///
532+
/// \return a MachineInstrBuilder for the newly created instruction.
533+
MachineInstrBuilder buildLoadInstr(unsigned Opcode, unsigned Res,
534+
unsigned Addr, MachineMemOperand &MMO);
535+
524536
/// Build and insert `G_STORE Val, Addr, MMO`.
525537
///
526538
/// Stores the value \p Val to \p Addr.

Diff for: ‎llvm/include/llvm/Support/TargetOpcodes.def

+7-1
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,15 @@ HANDLE_TARGET_OPCODE(G_INTTOPTR)
265265
/// COPY is the relevant instruction.
266266
HANDLE_TARGET_OPCODE(G_BITCAST)
267267

268-
/// Generic load.
268+
/// Generic load (including anyext load)
269269
HANDLE_TARGET_OPCODE(G_LOAD)
270270

271+
/// Generic signext load
272+
HANDLE_TARGET_OPCODE(G_SEXTLOAD)
273+
274+
/// Generic zeroext load
275+
HANDLE_TARGET_OPCODE(G_ZEXTLOAD)
276+
271277
/// Generic store.
272278
HANDLE_TARGET_OPCODE(G_STORE)
273279

Diff for: ‎llvm/include/llvm/Target/GenericOpcodes.td

+16
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,22 @@ def G_LOAD : GenericInstruction {
482482
let mayLoad = 1;
483483
}
484484

485+
// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.
486+
def G_SEXTLOAD : GenericInstruction {
487+
let OutOperandList = (outs type0:$dst);
488+
let InOperandList = (ins ptype1:$addr);
489+
let hasSideEffects = 0;
490+
let mayLoad = 1;
491+
}
492+
493+
// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.
494+
def G_ZEXTLOAD : GenericInstruction {
495+
let OutOperandList = (outs type0:$dst);
496+
let InOperandList = (ins ptype1:$addr);
497+
let hasSideEffects = 0;
498+
let mayLoad = 1;
499+
}
500+
485501
// Generic store. Expects a MachineMemOperand in addition to explicit operands.
486502
def G_STORE : GenericInstruction {
487503
let OutOperandList = (outs);

Diff for: ‎llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

+44-4
Original file line numberDiff line numberDiff line change
@@ -732,17 +732,19 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
732732
MI.eraseFromParent();
733733
return Legalized;
734734
}
735-
case TargetOpcode::G_LOAD: {
735+
case TargetOpcode::G_LOAD:
736736
// For some types like i24, we might try to widen to i32. To properly handle
737737
// this we should be using a dedicated extending load, until then avoid
738738
// trying to legalize.
739739
if (alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) !=
740740
WideTy.getSizeInBits())
741741
return UnableToLegalize;
742-
742+
LLVM_FALLTHROUGH;
743+
case TargetOpcode::G_SEXTLOAD:
744+
case TargetOpcode::G_ZEXTLOAD: {
743745
unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
744-
MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
745-
**MI.memoperands_begin());
746+
MIRBuilder.buildLoadInstr(MI.getOpcode(), DstExt, MI.getOperand(1).getReg(),
747+
**MI.memoperands_begin());
746748
MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
747749
MI.eraseFromParent();
748750
return Legalized;
@@ -1030,6 +1032,44 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
10301032
MI.eraseFromParent();
10311033
return Legalized;
10321034
}
1035+
case TargetOpcode::G_LOAD:
1036+
case TargetOpcode::G_SEXTLOAD:
1037+
case TargetOpcode::G_ZEXTLOAD: {
1038+
// Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
1039+
unsigned DstReg = MI.getOperand(0).getReg();
1040+
unsigned PtrReg = MI.getOperand(1).getReg();
1041+
LLT DstTy = MRI.getType(DstReg);
1042+
auto &MMO = **MI.memoperands_begin();
1043+
1044+
if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) {
1045+
MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1046+
MI.eraseFromParent();
1047+
return Legalized;
1048+
}
1049+
1050+
if (DstTy.isScalar()) {
1051+
unsigned TmpReg = MRI.createGenericVirtualRegister(
1052+
LLT::scalar(MMO.getSize() /* in bytes */ * 8));
1053+
MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1054+
switch (MI.getOpcode()) {
1055+
default:
1056+
llvm_unreachable("Unexpected opcode");
1057+
case TargetOpcode::G_LOAD:
1058+
MIRBuilder.buildAnyExt(DstReg, TmpReg);
1059+
break;
1060+
case TargetOpcode::G_SEXTLOAD:
1061+
MIRBuilder.buildSExt(DstReg, TmpReg);
1062+
break;
1063+
case TargetOpcode::G_ZEXTLOAD:
1064+
MIRBuilder.buildZExt(DstReg, TmpReg);
1065+
break;
1066+
}
1067+
MI.eraseFromParent();
1068+
return Legalized;
1069+
}
1070+
1071+
return UnableToLegalize;
1072+
}
10331073
}
10341074
}
10351075

Diff for: ‎llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -278,10 +278,16 @@ MachineInstrBuilder MachineIRBuilderBase::buildBrCond(unsigned Tst,
278278

279279
MachineInstrBuilder MachineIRBuilderBase::buildLoad(unsigned Res, unsigned Addr,
280280
MachineMemOperand &MMO) {
281+
return buildLoadInstr(TargetOpcode::G_LOAD, Res, Addr, MMO);
282+
}
283+
284+
MachineInstrBuilder
285+
MachineIRBuilderBase::buildLoadInstr(unsigned Opcode, unsigned Res,
286+
unsigned Addr, MachineMemOperand &MMO) {
281287
assert(getMRI()->getType(Res).isValid() && "invalid operand type");
282288
assert(getMRI()->getType(Addr).isPointer() && "invalid operand type");
283289

284-
return buildInstr(TargetOpcode::G_LOAD)
290+
return buildInstr(Opcode)
285291
.addDef(Res)
286292
.addUse(Addr)
287293
.addMemOperand(&MMO);

Diff for: ‎llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) {
135135
.maxScalarIf(typeInSet(1, {s64}), 0, s32)
136136
.widenScalarToNextPow2(0);
137137

138+
getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
139+
.lower();
140+
138141
getActionDefinitionsBuilder({G_LOAD, G_STORE})
139142
.legalForTypesWithMemSize({{s8, p0, 8},
140143
{s16, p0, 16},
@@ -147,6 +150,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) {
147150
.unsupportedIfMemSizeNotPow2()
148151
.clampScalar(0, s8, s64)
149152
.widenScalarToNextPow2(0)
153+
.lowerIf([=](const LegalityQuery &Query) {
154+
return Query.Types[0].getSizeInBits() != Query.MMODescrs[0].Size * 8;
155+
})
150156
.clampNumElements(0, v2s32, v2s32);
151157

152158
// Constants
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - -verify-machineinstrs | FileCheck %s
2+
3+
--- |
4+
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
5+
target triple = "aarch64--"
6+
define void @test_extload(i8* %addr) {
7+
entry:
8+
ret void
9+
}
10+
...
11+
12+
---
13+
name: test_extload
14+
body: |
15+
bb.0.entry:
16+
liveins: $x0
17+
; CHECK-LABEL: name: test_extload
18+
; CHECK: [[T0:%[0-9]+]]:_(p0) = COPY $x0
19+
; CHECK: [[T1:%[0-9]+]]:_(s8) = G_LOAD [[T0]](p0) :: (load 1 from %ir.addr)
20+
; CHECK: [[T2:%[0-9]+]]:_(s32) = G_ANYEXT [[T1]](s8)
21+
; CHECK: $w0 = COPY [[T2]](s32)
22+
%0:_(p0) = COPY $x0
23+
%1:_(s32) = G_LOAD %0 :: (load 1 from %ir.addr)
24+
$w0 = COPY %1
25+
...
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - -verify-machineinstrs | FileCheck %s
2+
3+
--- |
4+
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
5+
target triple = "aarch64--"
6+
define void @test_zextload(i8* %addr) {
7+
entry:
8+
ret void
9+
}
10+
...
11+
12+
---
13+
name: test_zextload
14+
body: |
15+
bb.0.entry:
16+
liveins: $x0
17+
; CHECK-LABEL: name: test_zextload
18+
; CHECK: [[T0:%[0-9]+]]:_(p0) = COPY $x0
19+
; CHECK: [[T1:%[0-9]+]]:_(s8) = G_LOAD [[T0]](p0) :: (load 1 from %ir.addr)
20+
; CHECK: [[T2:%[0-9]+]]:_(s32) = G_SEXT [[T1]](s8)
21+
; CHECK: $w0 = COPY [[T2]](s32)
22+
%0:_(p0) = COPY $x0
23+
%1:_(s32) = G_SEXTLOAD %0 :: (load 1 from %ir.addr)
24+
$w0 = COPY %1
25+
...
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - -verify-machineinstrs | FileCheck %s
2+
3+
--- |
4+
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
5+
target triple = "aarch64--"
6+
define void @test_sextload(i8* %addr) {
7+
entry:
8+
ret void
9+
}
10+
...
11+
12+
---
13+
name: test_sextload
14+
body: |
15+
bb.0.entry:
16+
liveins: $x0
17+
; CHECK-LABEL: name: test_sextload
18+
; CHECK: [[T0:%[0-9]+]]:_(p0) = COPY $x0
19+
; CHECK: [[T1:%[0-9]+]]:_(s8) = G_LOAD [[T0]](p0) :: (load 1 from %ir.addr)
20+
; CHECK: [[T2:%[0-9]+]]:_(s32) = G_ZEXT [[T1]](s8)
21+
; CHECK: $w0 = COPY [[T2]](s32)
22+
%0:_(p0) = COPY $x0
23+
%1:_(s32) = G_ZEXTLOAD %0 :: (load 1 from %ir.addr)
24+
$w0 = COPY %1
25+
...

0 commit comments

Comments
 (0)
Please sign in to comment.