Skip to content

Commit b1b86d1

Browse files
author
Jessica Paquette
committed
[AArch64][GlobalISel] Fold shifts into G_ICMP
Since G_ICMP can be selected to a SUBS, we can fold shifts into such compares. E.g. ``` cmp w1, w0, lsl rust-lang#3 cmp w1, w0, lsr rust-lang#3 cmp w1, w0, asr rust-lang#3 ``` This is done the same way as for adds and subtracts, using `selectShiftedRegister`. This gives some minor code size savings on CTMark. https://reviews.llvm.org/D79365
1 parent 17fc651 commit b1b86d1

File tree

2 files changed

+813
-0
lines changed

2 files changed

+813
-0
lines changed

llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ class AArch64InstructionSelector : public InstructionSelector {
309309
MachineOperand &RHS,
310310
MachineOperand &Predicate,
311311
MachineIRBuilder &MIB) const;
312+
MachineInstr *tryOptArithShiftedCompare(MachineOperand &LHS,
313+
MachineOperand &RHS,
314+
MachineIRBuilder &MIB) const;
312315

313316
/// Return true if \p MI is a load or store of \p NumBytes bytes.
314317
bool isLoadStoreOfNumBytes(const MachineInstr &MI, unsigned NumBytes) const;
@@ -3710,6 +3713,12 @@ AArch64InstructionSelector::emitIntegerCompare(
37103713
if (ImmedCmp)
37113714
return {ImmedCmp, (CmpInst::Predicate)Predicate.getPredicate()};
37123715

3716+
// If we don't have an immediate, we may have a shift which can be folded
3717+
// into the compare.
3718+
MachineInstr *ShiftedCmp = tryOptArithShiftedCompare(LHS, RHS, MIRBuilder);
3719+
if (ShiftedCmp)
3720+
return {ShiftedCmp, (CmpInst::Predicate)Predicate.getPredicate()};
3721+
37133722
auto CmpMI =
37143723
MIRBuilder.buildInstr(CmpOpc, {ZReg}, {LHS.getReg(), RHS.getReg()});
37153724
// Make sure that we can constrain the compare that we emitted.
@@ -4142,6 +4151,35 @@ MachineInstr *AArch64InstructionSelector::tryOptArithImmedIntegerCompare(
41424151
return &*CmpMI;
41434152
}
41444153

4154+
MachineInstr *AArch64InstructionSelector::tryOptArithShiftedCompare(
4155+
MachineOperand &LHS, MachineOperand &RHS, MachineIRBuilder &MIB) const {
4156+
// We are looking for the following pattern:
4157+
//
4158+
// shift = G_SHL/ASHR/LHSR y, c
4159+
// ...
4160+
// cmp = G_ICMP pred, something, shift
4161+
//
4162+
// Since we will select the G_ICMP to a SUBS, we can potentially fold the
4163+
// shift into the subtract.
4164+
static const unsigned OpcTable[2] = {AArch64::SUBSWrs, AArch64::SUBSXrs};
4165+
static const Register ZRegTable[2] = {AArch64::WZR, AArch64::XZR};
4166+
auto ImmFns = selectShiftedRegister(RHS);
4167+
if (!ImmFns)
4168+
return nullptr;
4169+
MachineRegisterInfo &MRI = *MIB.getMRI();
4170+
auto Ty = MRI.getType(LHS.getReg());
4171+
assert(!Ty.isVector() && "Expected scalar or pointer only?");
4172+
unsigned Size = Ty.getSizeInBits();
4173+
bool Idx = (Size == 64);
4174+
Register ZReg = ZRegTable[Idx];
4175+
unsigned Opc = OpcTable[Idx];
4176+
auto CmpMI = MIB.buildInstr(Opc, {ZReg}, {LHS.getReg()});
4177+
for (auto &RenderFn : *ImmFns)
4178+
RenderFn(CmpMI);
4179+
constrainSelectedInstRegOperands(*CmpMI, TII, TRI, RBI);
4180+
return &*CmpMI;
4181+
}
4182+
41454183
bool AArch64InstructionSelector::tryOptVectorDup(MachineInstr &I) const {
41464184
// Try to match a vector splat operation into a dup instruction.
41474185
// We're looking for this pattern:

0 commit comments

Comments
 (0)