diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -4119,7 +4119,8 @@ MachineIRBuilder MIB(I); MachineRegisterInfo &MRI = *MIB.getMRI(); const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo(); - + Register SrcReg1 = I.getOperand(2).getReg(); + Register SrcReg2 = I.getOperand(3).getReg(); // We want to recognize this pattern: // // $z = G_FCMP pred, $x, $y @@ -4208,6 +4209,31 @@ } // Emit the select. + // We may also be able to emit a CSINC if the RHS operand is a 1. + const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg1, MRI, TRI); + auto ValAndVReg = + getConstantVRegValWithLookThrough(SrcReg2, MRI); + + if (SrcRB.getID() == AArch64::GPRRegBankID && ValAndVReg && + ValAndVReg->Value == 1) { + unsigned Size = MRI.getType(SrcReg1).getSizeInBits(); + unsigned Opc = 0; + Register Zero; + if (Size == 64) { + Opc = AArch64::CSINCXr; + Zero = AArch64::XZR; + } else { + Opc = AArch64::CSINCWr; + Zero = AArch64::WZR; + } + auto CSINC = + MIB.buildInstr(Opc, {I.getOperand(0).getReg()}, {SrcReg1, Zero}) + .addImm(CondCode); + constrainSelectedInstRegOperands(*CSINC, TII, TRI, RBI); + I.eraseFromParent(); + return true; + } + unsigned CSelOpc = selectSelectOpc(I, MRI, RBI); auto CSel = MIB.buildInstr(CSelOpc, {I.getOperand(0).getReg()}, diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/fold-select.mir b/llvm/test/CodeGen/AArch64/GlobalISel/fold-select.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/fold-select.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/fold-select.mir @@ -97,3 +97,29 @@ $w0 = COPY %select(s32) RET_ReallyLR implicit $w0 ... +--- +name: csinc +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0: + liveins: $w0, $w1 + + ; CHECK-LABEL: name: csinc + ; CHECK: liveins: $w0, $w1 + ; CHECK: [[COPY:%[0-9]+]]:gpr32common = COPY $w0 + ; CHECK: [[SUBSWri:%[0-9]+]]:gpr32 = SUBSWri [[COPY]], 1, 0, implicit-def $nzcv + ; CHECK: [[CSINCWr:%[0-9]+]]:gpr32 = CSINCWr [[COPY]], $wzr, 0, implicit $nzcv + ; CHECK: $w0 = COPY [[CSINCWr]] + ; CHECK: RET_ReallyLR implicit $w0 + %0:gpr(s32) = COPY $w0 + %1:gpr(s32) = COPY $w1 + %2:gpr(s32) = G_CONSTANT i32 1 + %5:gpr(s32) = G_ICMP intpred(eq), %0(s32), %2 + %3:gpr(s1) = G_TRUNC %5(s32) + %4:gpr(s32) = G_SELECT %3(s1), %0, %2 + $w0 = COPY %4(s32) + RET_ReallyLR implicit $w0 +...