diff options
author | Evan Cheng <evan.cheng@apple.com> | 2012-01-04 01:41:39 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2012-01-04 01:41:39 +0000 |
commit | 56f582d664c54bf4567ec37d0bd16b6d4ea6a6eb (patch) | |
tree | 885c9db256151200548df5cee4b3dfb938079b5a | |
parent | 091523c6487fea71571a42f5d74eaf439f133f8c (diff) |
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
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 31 | ||||
-rw-r--r-- | test/CodeGen/X86/jump_sign.ll | 16 |
2 files changed, 46 insertions, 1 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index e12343ebcf..d33a7e09a5 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -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(); } diff --git a/test/CodeGen/X86/jump_sign.ll b/test/CodeGen/X86/jump_sign.ll index 5e8e162173..78dddf9568 100644 --- a/test/CodeGen/X86/jump_sign.ll +++ b/test/CodeGen/X86/jump_sign.ll @@ -1,7 +1,9 @@ -; RUN: llc < %s -march=x86 | grep jns +; RUN: llc < %s -march=x86 | FileCheck %s define i32 @f(i32 %X) { entry: +; CHECK: f: +; CHECK: jns %tmp1 = add i32 %X, 1 ; <i32> [#uses=1] %tmp = icmp slt i32 %tmp1, 0 ; <i1> [#uses=1] br i1 %tmp, label %cond_true, label %cond_next @@ -18,3 +20,15 @@ cond_next: ; preds = %cond_true, %entry declare i32 @bar(...) 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 +} |