@@ -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+
41454183bool 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