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 @@ -1066,6 +1066,21 @@ return true; } + // Attempt to fold: + // + // %add = G_ADD %x, 1 + // %select = G_SELECT cc, %reg, %add + // + // Into: + // %select = CSINC %reg, %x, cc + if (mi_match(Reg, MRI, m_GAdd(m_Reg(MatchReg), m_SpecificICst(1)))) { + Opc = Is32Bit ? AArch64::CSINCWr : AArch64::CSINCXr; + Reg = MatchReg; + if (Invert) + CC = AArch64CC::getInvertedCondCode(CC); + return true; + } + return false; }; diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-select.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-select.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-select.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-select.mir @@ -592,3 +592,61 @@ %select:gpr(s64) = G_SELECT %cond(s1), %t, %xor $x0 = COPY %select(s64) RET_ReallyLR implicit $x0 + +... +--- +name: csinc_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0: + liveins: $w0, $w1, $w2 + ; G_SELECT cc, %true, (G_ADD %x, 1) -> CSINC %true, %x, cc + ; CHECK-LABEL: name: csinc_s32 + ; CHECK: liveins: $w0, $w1, $w2 + ; CHECK: %reg0:gpr32 = COPY $w0 + ; CHECK: %reg1:gpr32 = COPY $w1 + ; CHECK: %t:gpr32 = COPY $w2 + ; CHECK: [[ANDSWri:%[0-9]+]]:gpr32 = ANDSWri %reg0, 0, implicit-def $nzcv + ; CHECK: %select:gpr32 = CSINCWr %t, %reg1, 1, implicit $nzcv + ; CHECK: $w0 = COPY %select + ; CHECK: RET_ReallyLR implicit $w0 + %reg0:gpr(s32) = COPY $w0 + %reg1:gpr(s32) = COPY $w1 + %cond:gpr(s1) = G_TRUNC %reg0(s32) + %t:gpr(s32) = COPY $w2 + %one:gpr(s32) = G_CONSTANT i32 1 + %add:gpr(s32) = G_ADD %reg1(s32), %one + %select:gpr(s32) = G_SELECT %cond(s1), %t, %add + $w0 = COPY %select(s32) + RET_ReallyLR implicit $w0 + +... +--- +name: csinc_s32_inverted_cc +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0: + liveins: $w0, $w1, $w2 + ; G_SELECT cc, (G_ADD %x, 1), %false -> CSINC %x, %false, inv_cc + ; CHECK-LABEL: name: csinc_s32_inverted_cc + ; CHECK: liveins: $w0, $w1, $w2 + ; CHECK: %reg0:gpr32 = COPY $w0 + ; CHECK: %reg1:gpr32 = COPY $w1 + ; CHECK: %f:gpr32 = COPY $w2 + ; CHECK: [[ANDSWri:%[0-9]+]]:gpr32 = ANDSWri %reg0, 0, implicit-def $nzcv + ; CHECK: %select:gpr32 = CSINCWr %reg1, %f, 0, implicit $nzcv + ; CHECK: $w0 = COPY %select + ; CHECK: RET_ReallyLR implicit $w0 + %reg0:gpr(s32) = COPY $w0 + %reg1:gpr(s32) = COPY $w1 + %cond:gpr(s1) = G_TRUNC %reg0(s32) + %f:gpr(s32) = COPY $w2 + %one:gpr(s32) = G_CONSTANT i32 1 + %add:gpr(s32) = G_ADD %reg1(s32), %one + %select:gpr(s32) = G_SELECT %cond(s1), %add, %f + $w0 = COPY %select(s32) + RET_ReallyLR implicit $w0