X86: optimization for max-like struct

This patch will optimize the following cases on X86
(a > b) ? (a-b) : 0
(a >= b) ? (a-b) : 0
(b < a) ? (a-b) : 0
(b <= a) ? (a-b) : 0

FROM
movl    %edi, %ecx
subl    %esi, %ecx
cmpl    %edi, %esi
movl    $0, %eax
cmovll  %ecx, %eax
TO
xorl    %eax, %eax
subl    %esi, %edi
cmovll  %eax, %edi
movl    %edi, %eax

rdar: 10734411


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@155919 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Manman Ren 2012-05-01 17:16:15 +00:00
parent d07d06ceef
commit 769ea2f93f
2 changed files with 82 additions and 0 deletions

View File

@ -8573,6 +8573,46 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
Cond = NewCond;
}
// Handle the following cases related to max and min:
// (a > b) ? (a-b) : 0
// (a >= b) ? (a-b) : 0
// (b < a) ? (a-b) : 0
// (b <= a) ? (a-b) : 0
// Comparison is removed to use EFLAGS from SUB.
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op2))
if (Cond.getOpcode() == X86ISD::SETCC &&
Cond.getOperand(1).getOpcode() == X86ISD::CMP &&
(Op1.getOpcode() == ISD::SUB || Op1.getOpcode() == X86ISD::SUB) &&
C->getAPIntValue() == 0) {
SDValue Cmp = Cond.getOperand(1);
unsigned CC = cast<ConstantSDNode>(Cond.getOperand(0))->getZExtValue();
if ((DAG.isEqualTo(Op1.getOperand(0), Cmp.getOperand(0)) &&
DAG.isEqualTo(Op1.getOperand(1), Cmp.getOperand(1)) &&
(CC == X86::COND_G || CC == X86::COND_GE ||
CC == X86::COND_A || CC == X86::COND_AE)) ||
(DAG.isEqualTo(Op1.getOperand(0), Cmp.getOperand(1)) &&
DAG.isEqualTo(Op1.getOperand(1), Cmp.getOperand(0)) &&
(CC == X86::COND_L || CC == X86::COND_LE ||
CC == X86::COND_B || CC == X86::COND_BE))) {
if (Op1.getOpcode() == ISD::SUB) {
SDVTList VTs = DAG.getVTList(Op1.getValueType(), MVT::i32);
SDValue New = DAG.getNode(X86ISD::SUB, DL, VTs,
Op1.getOperand(0), Op1.getOperand(1));
DAG.ReplaceAllUsesWith(Op1, New);
Op1 = New;
}
SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue);
unsigned NewCC = (CC == X86::COND_G || CC == X86::COND_GE ||
CC == X86::COND_L ||
CC == X86::COND_LE) ? X86::COND_GE : X86::COND_AE;
SDValue Ops[] = { Op2, Op1, DAG.getConstant(NewCC, MVT::i8),
SDValue(Op1.getNode(), 1) };
return DAG.getNode(X86ISD::CMOV, DL, VTs, Ops, array_lengthof(Ops));
}
}
// (select (x == 0), -1, y) -> (sign_bit (x - 1)) | y
// (select (x == 0), y, -1) -> ~(sign_bit (x - 1)) | y
// (select (x != 0), y, -1) -> (sign_bit (x - 1)) | y

View File

@ -32,3 +32,45 @@ entry:
%cond = select i1 %cmp, i32 %sub, i32 0
ret i32 %cond
}
; rdar://10734411
define i32 @h(i32 %a, i32 %b) nounwind {
entry:
; CHECK: h:
; CHECK-NOT: cmp
; CHECK: cmov
%cmp = icmp slt i32 %b, %a
%sub = sub nsw i32 %a, %b
%cond = select i1 %cmp, i32 %sub, i32 0
ret i32 %cond
}
define i32 @i(i32 %a, i32 %b) nounwind {
entry:
; CHECK: i:
; CHECK-NOT: cmp
; CHECK: cmov
%cmp = icmp sgt i32 %a, %b
%sub = sub nsw i32 %a, %b
%cond = select i1 %cmp, i32 %sub, i32 0
ret i32 %cond
}
define i32 @j(i32 %a, i32 %b) nounwind {
entry:
; CHECK: j:
; CHECK-NOT: cmp
; CHECK: cmov
%cmp = icmp ugt i32 %a, %b
%sub = sub i32 %a, %b
%cond = select i1 %cmp, i32 %sub, i32 0
ret i32 %cond
}
define i32 @k(i32 %a, i32 %b) nounwind {
entry:
; CHECK: k:
; CHECK-NOT: cmp
; CHECK: cmov
%cmp = icmp ult i32 %b, %a
%sub = sub i32 %a, %b
%cond = select i1 %cmp, i32 %sub, i32 0
ret i32 %cond
}