Codegen integer abs more efficiently using the trick from the PPC CWG. This
authorChris Lattner <sabre@nondot.org>
Wed, 11 Apr 2007 05:11:38 +0000 (05:11 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 11 Apr 2007 05:11:38 +0000 (05:11 +0000)
improves codegen on many architectures.  Tests committed as CodeGen/*/iabs.ll

X86 Old: X86 New:
_test: _test:
   movl 4(%esp), %ecx    movl 4(%esp), %eax
   movl %ecx, %eax    movl %eax, %ecx
   negl %eax    sarl $31, %ecx
   testl %ecx, %ecx    addl %ecx, %eax
   cmovns %ecx, %eax    xorl %ecx, %eax
   ret    ret

PPC Old: PPC New:
_test: _test:
   cmpwi cr0, r3, -1    srawi r2, r3, 31
   neg r2, r3    add r3, r3, r2
   bgt cr0, LBB1_2 ;    xor r3, r3, r2
LBB1_1: ;    blr
   mr r3, r2
LBB1_2: ;
   blr

ARM Old: ARM New:
_test: _test:
   rsb r3, r0, #0    add r3, r0, r0, asr #31
   cmp r0, #0    eor r0, r3, r0, asr #31
   movge r3, r0    bx lr
   mov r0, r3
   bx lr

Thumb Old: Thumb New:
_test: _test:
   neg r2, r0    asr r2, r0, #31
   cmp r0, #0    add r0, r0, r2
   bge LBB1_2    eor r0, r2
LBB1_1: @    bx lr
   cpy r0, r2
LBB1_2: @
   bx lr

Sparc Old: Sparc New:
test: test:
   save -96, %o6, %o6    save -96, %o6, %o6
   sethi 0, %l0    sra %i0, 31, %l0
   sub %l0, %i0, %l0    add %i0, %l0, %l1
   subcc %i0, -1, %l1    xor %l1, %l0, %i0
   bg .BB1_2    restore %g0, %g0, %g0
   nop    retl
.BB1_1:    nop
   or %g0, %l0, %i0
.BB1_2:
   restore %g0, %g0, %g0
   retl
   nop

It also helps alpha/ia64 :)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35881 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/DAGCombiner.cpp

index ed026084aae3d8e09e244449ac2a9f8a7ebce6cd..9ce6a8fa9b90b168c7319c35d94bb2b5952e3785 100644 (file)
@@ -4159,13 +4159,27 @@ SDOperand DAGCombiner::SimplifySelectCC(SDOperand N0, SDOperand N1,
   // Check to see if this is an integer abs. select_cc setl[te] X, 0, -X, X ->
   // Y = sra (X, size(X)-1); xor (add (X, Y), Y)
   if (N1C && N1C->isNullValue() && (CC == ISD::SETLT || CC == ISD::SETLE) &&
-      N0 == N3 && N2.getOpcode() == ISD::SUB && N0 == N2.getOperand(1)) {
-    if (ConstantSDNode *SubC = dyn_cast<ConstantSDNode>(N2.getOperand(0))) {
+      N0 == N3 && N2.getOpcode() == ISD::SUB && N0 == N2.getOperand(1) &&
+      N2.getOperand(0) == N1 && MVT::isInteger(N0.getValueType())) {
+    MVT::ValueType XType = N0.getValueType();
+    SDOperand Shift = DAG.getNode(ISD::SRA, XType, N0,
+                                  DAG.getConstant(MVT::getSizeInBits(XType)-1,
+                                                  TLI.getShiftAmountTy()));
+    SDOperand Add = DAG.getNode(ISD::ADD, XType, N0, Shift);
+    AddToWorkList(Shift.Val);
+    AddToWorkList(Add.Val);
+    return DAG.getNode(ISD::XOR, XType, Add, Shift);
+  }
+  // Check to see if this is an integer abs. select_cc setgt X, -1, X, -X ->
+  // Y = sra (X, size(X)-1); xor (add (X, Y), Y)
+  if (N1C && N1C->isAllOnesValue() && CC == ISD::SETGT &&
+      N0 == N2 && N3.getOpcode() == ISD::SUB && N0 == N3.getOperand(1)) {
+    if (ConstantSDNode *SubC = dyn_cast<ConstantSDNode>(N3.getOperand(0))) {
       MVT::ValueType XType = N0.getValueType();
       if (SubC->isNullValue() && MVT::isInteger(XType)) {
         SDOperand Shift = DAG.getNode(ISD::SRA, XType, N0,
                                     DAG.getConstant(MVT::getSizeInBits(XType)-1,
-                                                    TLI.getShiftAmountTy()));
+                                                      TLI.getShiftAmountTy()));
         SDOperand Add = DAG.getNode(ISD::ADD, XType, N0, Shift);
         AddToWorkList(Shift.Val);
         AddToWorkList(Add.Val);
@@ -4173,7 +4187,7 @@ SDOperand DAGCombiner::SimplifySelectCC(SDOperand N0, SDOperand N1,
       }
     }
   }
-
+  
   return SDOperand();
 }