Skip to content

Commit 280e47e

Browse files
Jessica Paquettetstellar
authored andcommitted
[AArch64][GlobalISel] Narrow 128-bit regs to 64-bit regs in emitTestBit
When we have a 128-bit register, emitTestBit would incorrectly narrow to 32 bits always. If the bit number was > 32, then we would need a TB(N)ZX. This would cause a crash, as we'd have the wrong register class. (PR48379) This generalizes `narrowExtReg` into `moveScalarRegClass`. This also allows us to remove `widenGPRBankRegIfNeeded` entirely, since `selectCopy` correctly handles SUBREG_TO_REG etc. This does create some codegen changes (since `selectCopy` uses the `all` regclass variants). However, I think that these will likely be optimized away, and we can always improve the `selectCopy` code. It looks like we should revisit `selectCopy` at this point, and possibly refactor it into at least one `emit` function. Differential Revision: https://reviews.llvm.org/D92707 (cherry picked from commit 195a7af)
1 parent 9e16c5b commit 280e47e

File tree

4 files changed

+67
-77
lines changed

4 files changed

+67
-77
lines changed

llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp

Lines changed: 26 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -289,14 +289,15 @@ class AArch64InstructionSelector : public InstructionSelector {
289289
getExtendTypeForInst(MachineInstr &MI, MachineRegisterInfo &MRI,
290290
bool IsLoadStore = false) const;
291291

292-
/// Instructions that accept extend modifiers like UXTW expect the register
293-
/// being extended to be a GPR32. Narrow ExtReg to a 32-bit register using a
294-
/// subregister copy if necessary. Return either ExtReg, or the result of the
295-
/// new copy.
296-
Register narrowExtendRegIfNeeded(Register ExtReg,
297-
MachineIRBuilder &MIB) const;
298-
Register widenGPRBankRegIfNeeded(Register Reg, unsigned Size,
299-
MachineIRBuilder &MIB) const;
292+
/// Move \p Reg to \p RC if \p Reg is not already on \p RC.
293+
///
294+
/// \returns Either \p Reg if no change was necessary, or the new register
295+
/// created by moving \p Reg.
296+
///
297+
/// Note: This uses emitCopy right now.
298+
Register moveScalarRegClass(Register Reg, const TargetRegisterClass &RC,
299+
MachineIRBuilder &MIB) const;
300+
300301
ComplexRendererFns selectArithExtendedRegister(MachineOperand &Root) const;
301302

302303
void renderTruncImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
@@ -1195,10 +1196,10 @@ MachineInstr *AArch64InstructionSelector::emitTestBit(
11951196
// TBNZW work.
11961197
bool UseWReg = Bit < 32;
11971198
unsigned NecessarySize = UseWReg ? 32 : 64;
1198-
if (Size < NecessarySize)
1199-
TestReg = widenGPRBankRegIfNeeded(TestReg, NecessarySize, MIB);
1200-
else if (Size > NecessarySize)
1201-
TestReg = narrowExtendRegIfNeeded(TestReg, MIB);
1199+
if (Size != NecessarySize)
1200+
TestReg = moveScalarRegClass(
1201+
TestReg, UseWReg ? AArch64::GPR32RegClass : AArch64::GPR64RegClass,
1202+
MIB);
12021203

12031204
static const unsigned OpcTable[2][2] = {{AArch64::TBZX, AArch64::TBNZX},
12041205
{AArch64::TBZW, AArch64::TBNZW}};
@@ -4984,7 +4985,7 @@ AArch64InstructionSelector::selectExtendedSHL(
49844985

49854986
// Need a 32-bit wide register here.
49864987
MachineIRBuilder MIB(*MRI.getVRegDef(Root.getReg()));
4987-
OffsetReg = narrowExtendRegIfNeeded(OffsetReg, MIB);
4988+
OffsetReg = moveScalarRegClass(OffsetReg, AArch64::GPR32RegClass, MIB);
49884989
}
49894990

49904991
// We can use the LHS of the GEP as the base, and the LHS of the shift as an
@@ -5156,8 +5157,8 @@ AArch64InstructionSelector::selectAddrModeWRO(MachineOperand &Root,
51565157

51575158
// Need a 32-bit wide register.
51585159
MachineIRBuilder MIB(*PtrAdd);
5159-
Register ExtReg =
5160-
narrowExtendRegIfNeeded(OffsetInst->getOperand(1).getReg(), MIB);
5160+
Register ExtReg = moveScalarRegClass(OffsetInst->getOperand(1).getReg(),
5161+
AArch64::GPR32RegClass, MIB);
51615162
unsigned SignExtend = Ext == AArch64_AM::SXTW;
51625163

51635164
// Base is LHS, offset is ExtReg.
@@ -5431,67 +5432,21 @@ AArch64_AM::ShiftExtendType AArch64InstructionSelector::getExtendTypeForInst(
54315432
}
54325433
}
54335434

5434-
Register AArch64InstructionSelector::narrowExtendRegIfNeeded(
5435-
Register ExtReg, MachineIRBuilder &MIB) const {
5435+
Register AArch64InstructionSelector::moveScalarRegClass(
5436+
Register Reg, const TargetRegisterClass &RC, MachineIRBuilder &MIB) const {
54365437
MachineRegisterInfo &MRI = *MIB.getMRI();
5437-
if (MRI.getType(ExtReg).getSizeInBits() == 32)
5438-
return ExtReg;
5439-
5440-
// Insert a copy to move ExtReg to GPR32.
5441-
Register NarrowReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
5442-
auto Copy = MIB.buildCopy({NarrowReg}, {ExtReg});
5438+
auto Ty = MRI.getType(Reg);
5439+
assert(!Ty.isVector() && "Expected scalars only!");
5440+
if (Ty.getSizeInBits() == TRI.getRegSizeInBits(RC))
5441+
return Reg;
54435442

5444-
// Select the copy into a subregister copy.
5443+
// Create a copy and immediately select it.
5444+
// FIXME: We should have an emitCopy function?
5445+
auto Copy = MIB.buildCopy({&RC}, {Reg});
54455446
selectCopy(*Copy, TII, MRI, TRI, RBI);
54465447
return Copy.getReg(0);
54475448
}
54485449

5449-
Register AArch64InstructionSelector::widenGPRBankRegIfNeeded(
5450-
Register Reg, unsigned WideSize, MachineIRBuilder &MIB) const {
5451-
assert(WideSize >= 8 && "WideSize is smaller than all possible registers?");
5452-
MachineRegisterInfo &MRI = *MIB.getMRI();
5453-
unsigned NarrowSize = MRI.getType(Reg).getSizeInBits();
5454-
assert(WideSize >= NarrowSize &&
5455-
"WideSize cannot be smaller than NarrowSize!");
5456-
5457-
// If the sizes match, just return the register.
5458-
//
5459-
// If NarrowSize is an s1, then we can select it to any size, so we'll treat
5460-
// it as a don't care.
5461-
if (NarrowSize == WideSize || NarrowSize == 1)
5462-
return Reg;
5463-
5464-
// Now check the register classes.
5465-
const RegisterBank *RB = RBI.getRegBank(Reg, MRI, TRI);
5466-
const TargetRegisterClass *OrigRC = getMinClassForRegBank(*RB, NarrowSize);
5467-
const TargetRegisterClass *WideRC = getMinClassForRegBank(*RB, WideSize);
5468-
assert(OrigRC && "Could not determine narrow RC?");
5469-
assert(WideRC && "Could not determine wide RC?");
5470-
5471-
// If the sizes differ, but the register classes are the same, there is no
5472-
// need to insert a SUBREG_TO_REG.
5473-
//
5474-
// For example, an s8 that's supposed to be a GPR will be selected to either
5475-
// a GPR32 or a GPR64 register. Note that this assumes that the s8 will
5476-
// always end up on a GPR32.
5477-
if (OrigRC == WideRC)
5478-
return Reg;
5479-
5480-
// We have two different register classes. Insert a SUBREG_TO_REG.
5481-
unsigned SubReg = 0;
5482-
getSubRegForClass(OrigRC, TRI, SubReg);
5483-
assert(SubReg && "Couldn't determine subregister?");
5484-
5485-
// Build the SUBREG_TO_REG and return the new, widened register.
5486-
auto SubRegToReg =
5487-
MIB.buildInstr(AArch64::SUBREG_TO_REG, {WideRC}, {})
5488-
.addImm(0)
5489-
.addUse(Reg)
5490-
.addImm(SubReg);
5491-
constrainSelectedInstRegOperands(*SubRegToReg, TII, TRI, RBI);
5492-
return SubRegToReg.getReg(0);
5493-
}
5494-
54955450
/// Select an "extended register" operand. This operand folds in an extend
54965451
/// followed by an optional left shift.
54975452
InstructionSelector::ComplexRendererFns
@@ -5552,7 +5507,7 @@ AArch64InstructionSelector::selectArithExtendedRegister(
55525507
// We require a GPR32 here. Narrow the ExtReg if needed using a subregister
55535508
// copy.
55545509
MachineIRBuilder MIB(*RootDef);
5555-
ExtReg = narrowExtendRegIfNeeded(ExtReg, MIB);
5510+
ExtReg = moveScalarRegClass(ExtReg, AArch64::GPR32RegClass, MIB);
55565511

55575512
return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(ExtReg); },
55585513
[=](MachineInstrBuilder &MIB) {

llvm/test/CodeGen/AArch64/GlobalISel/opt-fold-ext-tbz-tbnz.mir

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ body: |
7878
; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000)
7979
; CHECK: liveins: $h0
8080
; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:fpr32 = SUBREG_TO_REG 0, $h0, %subreg.hsub
81-
; CHECK: %copy:gpr32 = COPY [[SUBREG_TO_REG]]
82-
; CHECK: TBNZW %copy, 3, %bb.1
81+
; CHECK: %copy:gpr32all = COPY [[SUBREG_TO_REG]]
82+
; CHECK: [[COPY:%[0-9]+]]:gpr32 = COPY %copy
83+
; CHECK: TBNZW [[COPY]], 3, %bb.1
8384
; CHECK: B %bb.0
8485
; CHECK: bb.1:
8586
; CHECK: RET_ReallyLR

llvm/test/CodeGen/AArch64/GlobalISel/subreg-copy.mir

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,35 @@ body: |
3434
bb.1:
3535
RET_ReallyLR
3636
...
37+
---
38+
name: no_trunc
39+
alignment: 4
40+
legalized: true
41+
regBankSelected: true
42+
tracksRegLiveness: true
43+
body: |
44+
; CHECK-LABEL: name: no_trunc
45+
; CHECK: bb.0:
46+
; CHECK: successors: %bb.1(0x80000000)
47+
; CHECK: liveins: $x0
48+
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
49+
; CHECK: [[LDRQui:%[0-9]+]]:fpr128 = LDRQui [[COPY]], 0 :: (load 16)
50+
; CHECK: [[COPY1:%[0-9]+]]:gpr64all = COPY [[LDRQui]].dsub
51+
; CHECK: [[COPY2:%[0-9]+]]:gpr64 = COPY [[COPY1]]
52+
; CHECK: TBNZX [[COPY2]], 33, %bb.1
53+
; CHECK: bb.1:
54+
; CHECK: RET_ReallyLR
55+
bb.0:
56+
liveins: $x0
57+
%1:gpr(p0) = COPY $x0
58+
%3:gpr(s64) = G_CONSTANT i64 8589934592
59+
%5:gpr(s64) = G_CONSTANT i64 0
60+
%0:fpr(s128) = G_LOAD %1:gpr(p0) :: (load 16)
61+
%2:fpr(s64) = G_TRUNC %0:fpr(s128)
62+
%8:gpr(s64) = COPY %2:fpr(s64)
63+
%4:gpr(s64) = G_AND %8:gpr, %3:gpr
64+
%7:gpr(s32) = G_ICMP intpred(ne), %4:gpr(s64), %5:gpr
65+
%6:gpr(s1) = G_TRUNC %7:gpr(s32)
66+
G_BRCOND %6:gpr(s1), %bb.1
67+
bb.1:
68+
RET_ReallyLR

llvm/test/CodeGen/AArch64/GlobalISel/widen-narrow-tbz-tbnz.mir

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,9 @@ body: |
106106
; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000)
107107
; CHECK: liveins: $w0
108108
; CHECK: %reg:gpr32all = COPY $w0
109-
; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:gpr64 = SUBREG_TO_REG 0, %reg, %subreg.sub_32
110-
; CHECK: TBZX [[SUBREG_TO_REG]], 33, %bb.1
109+
; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:gpr64all = SUBREG_TO_REG 0, %reg, %subreg.sub_32
110+
; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY [[SUBREG_TO_REG]]
111+
; CHECK: TBZX [[COPY]], 33, %bb.1
111112
; CHECK: B %bb.0
112113
; CHECK: bb.1:
113114
; CHECK: RET_ReallyLR
@@ -140,8 +141,9 @@ body: |
140141
; CHECK: bb.0:
141142
; CHECK: successors: %bb.0(0x40000000), %bb.1(0x40000000)
142143
; CHECK: %reg:gpr32 = IMPLICIT_DEF
143-
; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:gpr64 = SUBREG_TO_REG 0, %reg, %subreg.sub_32
144-
; CHECK: TBZX [[SUBREG_TO_REG]], 33, %bb.1
144+
; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:gpr64all = SUBREG_TO_REG 0, %reg, %subreg.sub_32
145+
; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY [[SUBREG_TO_REG]]
146+
; CHECK: TBZX [[COPY]], 33, %bb.1
145147
; CHECK: B %bb.0
146148
; CHECK: bb.1:
147149
; CHECK: RET_ReallyLR

0 commit comments

Comments
 (0)