Index: lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.cpp +++ lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3988,13 +3988,25 @@ } else if (CTVal && CFVal) { const int64_t TrueVal = CTVal->getSExtValue(); const int64_t FalseVal = CFVal->getSExtValue(); + ConstantSDNode *RHSVal = dyn_cast(RHS); bool Swap = false; + bool KeepFVal = false; // If both TVal and FVal are constants, see if FVal is the // inverse/negation/increment of TVal and generate a CSINV/CSNEG/CSINC // instead of a CSEL in that case. if (TrueVal == ~FalseVal) { Opcode = AArch64ISD::CSINV; + } else if (CFVal->isAllOnesValue() && RHSVal == CTVal && + changeIntCCToAArch64CC(CC) == AArch64CC::EQ) { + // If FVal is -1, we can use a CSINV to invert wzr/xzr to avoid + // materializing the -1. We can also avoid materializing TVal, if TVal + // matches RHS and we're doing an equality comparison as we know LHS + // will contain TVal if the equality is true. + Opcode = AArch64ISD::CSINV; + TVal = LHS; + FVal = DAG.getConstant(0, dl, FVal.getValueType()); + KeepFVal = true; } else if (TrueVal == -FalseVal) { Opcode = AArch64ISD::CSNEG; } else if (TVal.getValueType() == MVT::i32) { @@ -4029,7 +4041,7 @@ CC = ISD::getSetCCInverse(CC, true); } - if (Opcode != AArch64ISD::CSEL) { + if (Opcode != AArch64ISD::CSEL && !KeepFVal) { // Drop FVal since we can get its value by simply inverting/negating // TVal. FVal = TVal; Index: test/CodeGen/AArch64/arm64-csel.ll =================================================================== --- test/CodeGen/AArch64/arm64-csel.ll +++ test/CodeGen/AArch64/arm64-csel.ll @@ -228,3 +228,37 @@ %inc.c = add i64 %inc, %c ret i64 %inc.c } + +; PR28965 +define i32 @foo20(i32 %x) { +entry: +; CHECK-LABEL: foo20: +; CHECK: cmp w[[REG:[0-9]+]], #1 +; CHECK-NOT: orr w{{[0-9]+}}, wzr, #0x1 +; CHECK: csinv w0, w[[REG]], wzr, eq + %cmp = icmp eq i32 %x, 1 + %res = select i1 %cmp, i32 1, i32 -1 + ret i32 %res +} + +define i64 @foo21(i64 %x) { +entry: +; CHECK-LABEL: foo21: +; CHECK: cmp x[[REG:[0-9]+]], #1 +; CHECK-NOT: orr w{{[0-9]+}}, wzr, #0x1 +; CHECK: csinv x0, x[[REG]], xzr, eq + %cmp = icmp eq i64 %x, 1 + %res = select i1 %cmp, i64 1, i64 -1 + ret i64 %res +} + +define i64 @foo22(i64 %x) { +entry: +; CHECK-LABEL: foo22: +; CHECK: cmp x[[REG:[0-9]+]], #3 +; CHECK-NOT: orr w{{[0-9]+}}, wzr, #0x3 +; CHECK: csinv x0, x[[REG]], xzr, eq + %cmp = icmp eq i64 %x, 3 + %res = select i1 %cmp, i64 3, i64 -1 + ret i64 %res +}