mirror of
https://github.com/RPCS3/llvm.git
synced 2025-04-12 02:47:10 +00:00
For x86, canonicalize max
(x > y) ? x : y => (x >= y) ? x : y So for something like (x - y) > 0 : (x - y) ? 0 It will be (x - y) >= 0 : (x - y) ? 0 This makes is possible to test sign-bit and eliminate a comparison against zero. e.g. subl %esi, %edi testl %edi, %edi movl $0, %eax cmovgl %edi, %eax => xorl %eax, %eax subl %esi, $edi cmovsl %eax, %edi rdar://10633221 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147512 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
091523c648
commit
56f582d664
@ -13139,6 +13139,37 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Canonicalize max and min:
|
||||||
|
// (x > y) ? x : y -> (x >= y) ? x : y
|
||||||
|
// (x < y) ? x : y -> (x <= y) ? x : y
|
||||||
|
// This allows use of COND_S / COND_NS (see TranslateX86CC) which eliminates
|
||||||
|
// the need for an extra compare
|
||||||
|
// against zero. e.g.
|
||||||
|
// (x - y) > 0 : (x - y) ? 0 -> (x - y) >= 0 : (x - y) ? 0
|
||||||
|
// subl %esi, %edi
|
||||||
|
// testl %edi, %edi
|
||||||
|
// movl $0, %eax
|
||||||
|
// cmovgl %edi, %eax
|
||||||
|
// =>
|
||||||
|
// xorl %eax, %eax
|
||||||
|
// subl %esi, $edi
|
||||||
|
// cmovsl %eax, %edi
|
||||||
|
if (N->getOpcode() == ISD::SELECT && Cond.getOpcode() == ISD::SETCC &&
|
||||||
|
DAG.isEqualTo(LHS, Cond.getOperand(0)) &&
|
||||||
|
DAG.isEqualTo(RHS, Cond.getOperand(1))) {
|
||||||
|
ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
|
||||||
|
switch (CC) {
|
||||||
|
default: break;
|
||||||
|
case ISD::SETLT:
|
||||||
|
case ISD::SETGT: {
|
||||||
|
ISD::CondCode NewCC = (CC == ISD::SETLT) ? ISD::SETLE : ISD::SETGE;
|
||||||
|
Cond = DAG.getSetCC(Cond.getDebugLoc(), Cond.getValueType(),
|
||||||
|
Cond.getOperand(0), Cond.getOperand(1), NewCC);
|
||||||
|
return DAG.getNode(ISD::SELECT, DL, VT, Cond, LHS, RHS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
; RUN: llc < %s -march=x86 | grep jns
|
; RUN: llc < %s -march=x86 | FileCheck %s
|
||||||
|
|
||||||
define i32 @f(i32 %X) {
|
define i32 @f(i32 %X) {
|
||||||
entry:
|
entry:
|
||||||
|
; CHECK: f:
|
||||||
|
; CHECK: jns
|
||||||
%tmp1 = add i32 %X, 1 ; <i32> [#uses=1]
|
%tmp1 = add i32 %X, 1 ; <i32> [#uses=1]
|
||||||
%tmp = icmp slt i32 %tmp1, 0 ; <i1> [#uses=1]
|
%tmp = icmp slt i32 %tmp1, 0 ; <i1> [#uses=1]
|
||||||
br i1 %tmp, label %cond_true, label %cond_next
|
br i1 %tmp, label %cond_true, label %cond_next
|
||||||
@ -18,3 +20,15 @@ cond_next: ; preds = %cond_true, %entry
|
|||||||
declare i32 @bar(...)
|
declare i32 @bar(...)
|
||||||
|
|
||||||
declare i32 @baz(...)
|
declare i32 @baz(...)
|
||||||
|
|
||||||
|
; rdar://10633221
|
||||||
|
define i32 @g(i32 %a, i32 %b) nounwind {
|
||||||
|
entry:
|
||||||
|
; CHECK: g:
|
||||||
|
; CHECK-NOT: test
|
||||||
|
; CHECK: cmovs
|
||||||
|
%sub = sub nsw i32 %a, %b
|
||||||
|
%cmp = icmp sgt i32 %sub, 0
|
||||||
|
%cond = select i1 %cmp, i32 %sub, i32 0
|
||||||
|
ret i32 %cond
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user