forked from OSchip/llvm-project
Teach instcombine to transform
(X >s -1) ? C1 : C2 and (X <s 0) ? C2 : C1 into ((X >>s 31) & (C2 - C1)) + C1, avoiding the conditional. This optimization could be extended to take non-const C1 and C2 but we better stay conservative to avoid code size bloat for now. for int sel(int n) { return n >= 0 ? 60 : 100; } we now generate sarl $31, %edi andl $40, %edi leal 60(%rdi), %eax instead of testl %edi, %edi movl $60, %ecx movl $100, %eax cmovnsl %ecx, %eax llvm-svn: 107866
This commit is contained in:
parent
e51a119fc6
commit
2321e6a4d4
|
@ -906,17 +906,6 @@ The expression should optimize to something like
|
|||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
From GCC Bug 3756:
|
||||
int
|
||||
pn (int n)
|
||||
{
|
||||
return (n >= 0 ? 1 : -1);
|
||||
}
|
||||
Should combine to (n >> 31) | 1. Currently not optimized with "clang
|
||||
-emit-llvm-bc | opt -std-compile-opts | llc".
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
void a(int variable)
|
||||
{
|
||||
if (variable == 4 || variable == 6)
|
||||
|
|
|
@ -329,6 +329,37 @@ Instruction *InstCombiner::visitSelectInstWithICmp(SelectInst &SI,
|
|||
}
|
||||
}
|
||||
|
||||
// Transform (X >s -1) ? C1 : C2 --> ((X >>s 31) & (C2 - C1)) + C1
|
||||
// and (X <s 0) ? C2 : C1 --> ((X >>s 31) & (C2 - C1)) + C1
|
||||
// FIXME: Type and constness constraints could be lifted, but we have to
|
||||
// watch code size carefully. We should consider xor instead of
|
||||
// sub/add when we decide to do that.
|
||||
if (const IntegerType *Ty = dyn_cast<IntegerType>(CmpLHS->getType())) {
|
||||
if (TrueVal->getType() == Ty) {
|
||||
if (ConstantInt *Cmp = dyn_cast<ConstantInt>(CmpRHS)) {
|
||||
ConstantInt *C1 = NULL, *C2 = NULL;
|
||||
if (Pred == ICmpInst::ICMP_SGT && Cmp->isAllOnesValue()) {
|
||||
C1 = dyn_cast<ConstantInt>(TrueVal);
|
||||
C2 = dyn_cast<ConstantInt>(FalseVal);
|
||||
} else if (Pred == ICmpInst::ICMP_SLT && Cmp->isNullValue()) {
|
||||
C1 = dyn_cast<ConstantInt>(FalseVal);
|
||||
C2 = dyn_cast<ConstantInt>(TrueVal);
|
||||
}
|
||||
if (C1 && C2) {
|
||||
// This shift results in either -1 or 0.
|
||||
Value *AShr = Builder->CreateAShr(CmpLHS, Ty->getBitWidth()-1);
|
||||
|
||||
// Check if we can express the operation with a single or.
|
||||
if (C2->isAllOnesValue())
|
||||
return ReplaceInstUsesWith(SI, Builder->CreateOr(AShr, C1));
|
||||
|
||||
Value *And = Builder->CreateAnd(AShr, C2->getValue()-C1->getValue());
|
||||
return ReplaceInstUsesWith(SI, Builder->CreateAdd(And, C1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CmpLHS == TrueVal && CmpRHS == FalseVal) {
|
||||
// Transform (X == Y) ? X : Y -> Y
|
||||
if (Pred == ICmpInst::ICMP_EQ)
|
||||
|
|
|
@ -438,3 +438,35 @@ define i32 @test34(i32 %x, i32 %y) {
|
|||
; CHECK: @test34
|
||||
; CHECK: ret i32 %x
|
||||
}
|
||||
|
||||
define i32 @test35(i32 %x) {
|
||||
%cmp = icmp sge i32 %x, 0
|
||||
%cond = select i1 %cmp, i32 60, i32 100
|
||||
ret i32 %cond
|
||||
; CHECK: @test35
|
||||
; CHECK: ashr i32 %x, 31
|
||||
; CHECK: and i32 {{.*}}, 40
|
||||
; CHECK: add i32 {{.*}}, 60
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
define i32 @test36(i32 %x) {
|
||||
%cmp = icmp slt i32 %x, 0
|
||||
%cond = select i1 %cmp, i32 60, i32 100
|
||||
ret i32 %cond
|
||||
; CHECK: @test36
|
||||
; CHECK: ashr i32 %x, 31
|
||||
; CHECK: and i32 {{.*}}, -40
|
||||
; CHECK: add i32 {{.*}}, 100
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
define i32 @test37(i32 %x) {
|
||||
%cmp = icmp sgt i32 %x, -1
|
||||
%cond = select i1 %cmp, i32 1, i32 -1
|
||||
ret i32 %cond
|
||||
; CHECK: @test37
|
||||
; CHECK: ashr i32 %x, 31
|
||||
; CHECK: or i32 {{.*}}, 1
|
||||
; CHECK: ret
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue