diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp index d9e61aa936b..076145c36b2 100644 --- a/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -4054,8 +4054,9 @@ SDValue AArch64TargetLowering::LowerSELECT_CC(ISD::CondCode CC, SDValue LHS, // Avoid materializing a constant when possible by reusing a known value in // a register. However, don't perform this optimization if the known value - // is one, zero or negative one. We can always materialize these values - // using CSINC, CSEL and CSINV with wzr/xzr as the FVal, respectively. + // is one, zero or negative one in the case of a CSEL. We can always + // materialize these values using CSINC, CSEL and CSINV with wzr/xzr as the + // FVal, respectively. ConstantSDNode *RHSVal = dyn_cast(RHS); if (Opcode == AArch64ISD::CSEL && RHSVal && !RHSVal->isOne() && !RHSVal->isNullValue() && !RHSVal->isAllOnesValue()) { @@ -4066,6 +4067,16 @@ SDValue AArch64TargetLowering::LowerSELECT_CC(ISD::CondCode CC, SDValue LHS, TVal = LHS; else if (CFVal && CFVal == RHSVal && AArch64CC == AArch64CC::NE) FVal = LHS; + } else if (Opcode == AArch64ISD::CSNEG && RHSVal && RHSVal->isOne()) { + assert (CTVal && CFVal && "Expected constant operands for CSNEG."); + // Use a CSINV to transform "a == C ? 1 : -1" to "a == C ? a : -1" to + // avoid materializing C. + AArch64CC::CondCode AArch64CC = changeIntCCToAArch64CC(CC); + if (CTVal == RHSVal && AArch64CC == AArch64CC::EQ) { + Opcode = AArch64ISD::CSINV; + TVal = LHS; + FVal = DAG.getConstant(0, dl, FVal.getValueType()); + } } SDValue CCVal; diff --git a/test/CodeGen/AArch64/cond-sel-value-prop.ll b/test/CodeGen/AArch64/cond-sel-value-prop.ll index cc0aad1a0bf..0c8b5e559a3 100644 --- a/test/CodeGen/AArch64/cond-sel-value-prop.ll +++ b/test/CodeGen/AArch64/cond-sel-value-prop.ll @@ -97,3 +97,14 @@ define i64 @test9(i64 %x) { %res = select i1 %cmp, i64 7, i64 -1 ret i64 %res } + +; Rather than use a CNEG, use a CSINV to transform "a == 1 ? 1 : -1" to +; "a == 1 ? a : -1" to avoid materializing a constant. +; CHECK-LABEL: test10: +; CHECK: cmp w[[REG:[0-9]]], #1 +; CHECK: cneg w0, w[[REG]], ne +define i32 @test10(i32 %x) { + %cmp = icmp eq i32 %x, 1 + %res = select i1 %cmp, i32 1, i32 -1 + ret i32 %res +}