Codegen integer abs more efficiently using the trick from the PPC CWG. This

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
This commit is contained in:
Chris Lattner 2007-04-11 05:11:38 +00:00
parent 603572a771
commit 1982ef20c4

View 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();
}