mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-10-30 16:17:05 +00:00
optimize:
void a(int x) { if (((1<<x)&8)==0) b(); }
into "x != 3", which occurs over 100 times in 403.gcc but in no
other program in llvm-test.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119922 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1699,14 +1699,6 @@ This should be optimized to a single compare. Testcase derived from gcc.
|
|||||||
|
|
||||||
//===---------------------------------------------------------------------===//
|
//===---------------------------------------------------------------------===//
|
||||||
|
|
||||||
Missed instcombine transformation:
|
|
||||||
void b();
|
|
||||||
void a(int x) { if (((1<<x)&8)==0) b(); }
|
|
||||||
|
|
||||||
The shift should be optimized out. Testcase derived from gcc.
|
|
||||||
|
|
||||||
//===---------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
Missed instcombine or reassociate transformation:
|
Missed instcombine or reassociate transformation:
|
||||||
int a(int a, int b) { return (a==12)&(b>47)&(b<58); }
|
int a(int a, int b) { return (a==12)&(b>47)&(b<58); }
|
||||||
|
|
||||||
|
|||||||
@@ -1744,14 +1744,84 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
|||||||
// simplify this comparison. For example, (x&4) < 8 is always true.
|
// simplify this comparison. For example, (x&4) < 8 is always true.
|
||||||
switch (I.getPredicate()) {
|
switch (I.getPredicate()) {
|
||||||
default: llvm_unreachable("Unknown icmp opcode!");
|
default: llvm_unreachable("Unknown icmp opcode!");
|
||||||
case ICmpInst::ICMP_EQ:
|
case ICmpInst::ICMP_EQ: {
|
||||||
if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max))
|
if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max))
|
||||||
return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
|
return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
|
||||||
|
|
||||||
|
// If all bits are known zero except for one, then we know at most one
|
||||||
|
// bit is set. If the comparison is against zero, then this is a check
|
||||||
|
// to see if *that* bit is set.
|
||||||
|
APInt Op0KnownZeroInverted = ~Op0KnownZero;
|
||||||
|
if (~Op1KnownZero == 0 && Op0KnownZeroInverted.isPowerOf2()) {
|
||||||
|
// If the LHS is an AND with the same constant, look through it.
|
||||||
|
Value *LHS = 0;
|
||||||
|
ConstantInt *LHSC = 0;
|
||||||
|
if (!match(Op0, m_And(m_Value(LHS), m_ConstantInt(LHSC))) ||
|
||||||
|
LHSC->getValue() != Op0KnownZeroInverted)
|
||||||
|
LHS = Op0;
|
||||||
|
|
||||||
|
// If the LHS is 1 << x, and we know the result is a power of 2 like 8,
|
||||||
|
// then turn "((1 << x)&8) == 0" into "x == 3".
|
||||||
|
Value *X = 0;
|
||||||
|
if (match(LHS, m_Shl(m_One(), m_Value(X)))) {
|
||||||
|
unsigned CmpVal = Op0KnownZeroInverted.countTrailingZeros();
|
||||||
|
return new ICmpInst(ICmpInst::ICMP_EQ, X,
|
||||||
|
ConstantInt::get(X->getType(), CmpVal));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the LHS is 8 >>u x, and we know the result is a power of 2 like 1,
|
||||||
|
// then turn "((8 >>u x)&1) == 0" into "x == 3".
|
||||||
|
ConstantInt *CI = 0;
|
||||||
|
if (Op0KnownZeroInverted == 1 &&
|
||||||
|
match(LHS, m_LShr(m_ConstantInt(CI), m_Value(X))) &&
|
||||||
|
CI->getValue().isPowerOf2()) {
|
||||||
|
unsigned CmpVal = CI->getValue().countTrailingZeros();
|
||||||
|
return new ICmpInst(ICmpInst::ICMP_EQ, X,
|
||||||
|
ConstantInt::get(X->getType(), CmpVal));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ICmpInst::ICMP_NE:
|
}
|
||||||
|
case ICmpInst::ICMP_NE: {
|
||||||
if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max))
|
if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max))
|
||||||
return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
|
return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
|
||||||
|
|
||||||
|
// If all bits are known zero except for one, then we know at most one
|
||||||
|
// bit is set. If the comparison is against zero, then this is a check
|
||||||
|
// to see if *that* bit is set.
|
||||||
|
APInt Op0KnownZeroInverted = ~Op0KnownZero;
|
||||||
|
if (~Op1KnownZero == 0 && Op0KnownZeroInverted.isPowerOf2()) {
|
||||||
|
// If the LHS is an AND with the same constant, look through it.
|
||||||
|
Value *LHS = 0;
|
||||||
|
ConstantInt *LHSC = 0;
|
||||||
|
if (!match(Op0, m_And(m_Value(LHS), m_ConstantInt(LHSC))) ||
|
||||||
|
LHSC->getValue() != Op0KnownZeroInverted)
|
||||||
|
LHS = Op0;
|
||||||
|
|
||||||
|
// If the LHS is 1 << x, and we know the result is a power of 2 like 8,
|
||||||
|
// then turn "((1 << x)&8) != 0" into "x != 3".
|
||||||
|
Value *X = 0;
|
||||||
|
if (match(LHS, m_Shl(m_One(), m_Value(X)))) {
|
||||||
|
unsigned CmpVal = Op0KnownZeroInverted.countTrailingZeros();
|
||||||
|
return new ICmpInst(ICmpInst::ICMP_NE, X,
|
||||||
|
ConstantInt::get(X->getType(), CmpVal));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the LHS is 8 >>u x, and we know the result is a power of 2 like 1,
|
||||||
|
// then turn "((8 >>u x)&1) != 0" into "x != 3".
|
||||||
|
ConstantInt *CI = 0;
|
||||||
|
if (Op0KnownZeroInverted == 1 &&
|
||||||
|
match(LHS, m_LShr(m_ConstantInt(CI), m_Value(X))) &&
|
||||||
|
CI->getValue().isPowerOf2()) {
|
||||||
|
unsigned CmpVal = CI->getValue().countTrailingZeros();
|
||||||
|
return new ICmpInst(ICmpInst::ICMP_NE, X,
|
||||||
|
ConstantInt::get(X->getType(), CmpVal));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case ICmpInst::ICMP_ULT:
|
case ICmpInst::ICMP_ULT:
|
||||||
if (Op0Max.ult(Op1Min)) // A <u B -> true if max(A) < min(B)
|
if (Op0Max.ult(Op1Min)) // A <u B -> true if max(A) < min(B)
|
||||||
return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
|
return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext()));
|
||||||
|
|||||||
@@ -154,3 +154,41 @@ entry:
|
|||||||
; CHECK: @test16
|
; CHECK: @test16
|
||||||
; CHECK: ret i1 undef
|
; CHECK: ret i1 undef
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define i1 @test17(i32 %x) nounwind {
|
||||||
|
%shl = shl i32 1, %x
|
||||||
|
%and = and i32 %shl, 8
|
||||||
|
%cmp = icmp eq i32 %and, 0
|
||||||
|
ret i1 %cmp
|
||||||
|
; CHECK: @test17
|
||||||
|
; CHECK-NEXT: %cmp = icmp eq i32 %x, 3
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
define i1 @test18(i32 %x) nounwind {
|
||||||
|
%sh = lshr i32 8, %x
|
||||||
|
%and = and i32 %sh, 1
|
||||||
|
%cmp = icmp eq i32 %and, 0
|
||||||
|
ret i1 %cmp
|
||||||
|
; CHECK: @test18
|
||||||
|
; CHECK-NEXT: %cmp = icmp eq i32 %x, 3
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @test19(i32 %x) nounwind {
|
||||||
|
%shl = shl i32 1, %x
|
||||||
|
%and = and i32 %shl, 8
|
||||||
|
%cmp = icmp eq i32 %and, 8
|
||||||
|
ret i1 %cmp
|
||||||
|
; CHECK: @test19
|
||||||
|
; CHECK-NEXT: %cmp = icmp ne i32 %x, 3
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @test20(i32 %x) nounwind {
|
||||||
|
%shl = shl i32 1, %x
|
||||||
|
%and = and i32 %shl, 8
|
||||||
|
%cmp = icmp ne i32 %and, 0
|
||||||
|
ret i1 %cmp
|
||||||
|
; CHECK: @test20
|
||||||
|
; CHECK-NEXT: %cmp = icmp ne i32 %x, 3
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user