[AArch64] Avoid materializing constant 1 when generating cneg instructions.
authorChad Rosier <mcrosier@codeaurora.org>
Wed, 26 Oct 2016 18:15:32 +0000 (18:15 +0000)
committerChad Rosier <mcrosier@codeaurora.org>
Wed, 26 Oct 2016 18:15:32 +0000 (18:15 +0000)
Instead of

 cmp w0, #1
 orr w8, wzr, #0x1
 cneg w0, w8, ne

we now generate

 cmp w0, #1
 csinv w0, w0, wzr, eq

PR28965

llvm-svn: 285217

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/test/CodeGen/AArch64/cond-sel-value-prop.ll

index d9e61aa..076145c 100644 (file)
@@ -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<ConstantSDNode>(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;
index cc0aad1..0c8b5e5 100644 (file)
@@ -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
+}