@@ -309,6 +309,9 @@ class AArch64InstructionSelector : public InstructionSelector {
309
309
MachineOperand &RHS,
310
310
MachineOperand &Predicate,
311
311
MachineIRBuilder &MIB) const ;
312
+ MachineInstr *tryOptArithShiftedCompare (MachineOperand &LHS,
313
+ MachineOperand &RHS,
314
+ MachineIRBuilder &MIB) const ;
312
315
313
316
// / Return true if \p MI is a load or store of \p NumBytes bytes.
314
317
bool isLoadStoreOfNumBytes (const MachineInstr &MI, unsigned NumBytes) const ;
@@ -3710,6 +3713,12 @@ AArch64InstructionSelector::emitIntegerCompare(
3710
3713
if (ImmedCmp)
3711
3714
return {ImmedCmp, (CmpInst::Predicate)Predicate.getPredicate ()};
3712
3715
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
+
3713
3722
auto CmpMI =
3714
3723
MIRBuilder.buildInstr (CmpOpc, {ZReg}, {LHS.getReg (), RHS.getReg ()});
3715
3724
// Make sure that we can constrain the compare that we emitted.
@@ -4142,6 +4151,35 @@ MachineInstr *AArch64InstructionSelector::tryOptArithImmedIntegerCompare(
4142
4151
return &*CmpMI;
4143
4152
}
4144
4153
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
+
4145
4183
bool AArch64InstructionSelector::tryOptVectorDup (MachineInstr &I) const {
4146
4184
// Try to match a vector splat operation into a dup instruction.
4147
4185
// We're looking for this pattern:
0 commit comments