mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-28 03:25:23 +00:00
InstCombine: fold (A << C) == (B << C) --> ((A^B) & (~0U >> C)) == 0
Anding and comparing with zero can be done in a single instruction on most archs so this is a bit cheaper. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233291 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1844,44 +1844,6 @@ we remove checking in code like
|
|||||||
|
|
||||||
//===---------------------------------------------------------------------===//
|
//===---------------------------------------------------------------------===//
|
||||||
|
|
||||||
This code (from Benchmarks/Dhrystone/dry.c):
|
|
||||||
|
|
||||||
define i32 @Func1(i32, i32) nounwind readnone optsize ssp {
|
|
||||||
entry:
|
|
||||||
%sext = shl i32 %0, 24
|
|
||||||
%conv = ashr i32 %sext, 24
|
|
||||||
%sext6 = shl i32 %1, 24
|
|
||||||
%conv4 = ashr i32 %sext6, 24
|
|
||||||
%cmp = icmp eq i32 %conv, %conv4
|
|
||||||
%. = select i1 %cmp, i32 10000, i32 0
|
|
||||||
ret i32 %.
|
|
||||||
}
|
|
||||||
|
|
||||||
Should be simplified into something like:
|
|
||||||
|
|
||||||
define i32 @Func1(i32, i32) nounwind readnone optsize ssp {
|
|
||||||
entry:
|
|
||||||
%sext = shl i32 %0, 24
|
|
||||||
%conv = and i32 %sext, 0xFF000000
|
|
||||||
%sext6 = shl i32 %1, 24
|
|
||||||
%conv4 = and i32 %sext6, 0xFF000000
|
|
||||||
%cmp = icmp eq i32 %conv, %conv4
|
|
||||||
%. = select i1 %cmp, i32 10000, i32 0
|
|
||||||
ret i32 %.
|
|
||||||
}
|
|
||||||
|
|
||||||
and then to:
|
|
||||||
|
|
||||||
define i32 @Func1(i32, i32) nounwind readnone optsize ssp {
|
|
||||||
entry:
|
|
||||||
%conv = and i32 %0, 0xFF
|
|
||||||
%conv4 = and i32 %1, 0xFF
|
|
||||||
%cmp = icmp eq i32 %conv, %conv4
|
|
||||||
%. = select i1 %cmp, i32 10000, i32 0
|
|
||||||
ret i32 %.
|
|
||||||
}
|
|
||||||
//===---------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
clang -O3 currently compiles this code
|
clang -O3 currently compiles this code
|
||||||
|
|
||||||
int g(unsigned int a) {
|
int g(unsigned int a) {
|
||||||
|
@@ -3553,6 +3553,21 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (A << C) == (B << C) --> ((A^B) & (~0U >> C)) == 0
|
||||||
|
if (match(Op0, m_OneUse(m_Shl(m_Value(A), m_ConstantInt(Cst1)))) &&
|
||||||
|
match(Op1, m_OneUse(m_Shl(m_Value(B), m_Specific(Cst1))))) {
|
||||||
|
unsigned TypeBits = Cst1->getBitWidth();
|
||||||
|
unsigned ShAmt = (unsigned)Cst1->getLimitedValue(TypeBits);
|
||||||
|
if (ShAmt < TypeBits && ShAmt != 0) {
|
||||||
|
Value *Xor = Builder->CreateXor(A, B, I.getName() + ".unshifted");
|
||||||
|
APInt AndVal = APInt::getLowBitsSet(TypeBits, TypeBits - ShAmt);
|
||||||
|
Value *And = Builder->CreateAnd(Xor, Builder->getInt(AndVal),
|
||||||
|
I.getName() + ".mask");
|
||||||
|
return new ICmpInst(I.getPredicate(), And,
|
||||||
|
Constant::getNullValue(Cst1->getType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Transform "icmp eq (trunc (lshr(X, cst1)), cst" to
|
// Transform "icmp eq (trunc (lshr(X, cst1)), cst" to
|
||||||
// "icmp (and X, mask), cst"
|
// "icmp (and X, mask), cst"
|
||||||
uint64_t ShAmt = 0;
|
uint64_t ShAmt = 0;
|
||||||
|
@@ -1573,3 +1573,33 @@ define i32 @f5(i8 %a, i8 %b) {
|
|||||||
%sub7.sub = select i1 %cmp4, i32 %sub7, i32 %sub
|
%sub7.sub = select i1 %cmp4, i32 %sub7, i32 %sub
|
||||||
ret i32 %sub7.sub
|
ret i32 %sub7.sub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @f6
|
||||||
|
; CHECK: %cmp.unshifted = xor i32 %a, %b
|
||||||
|
; CHECK-NEXT: %cmp.mask = and i32 %cmp.unshifted, 255
|
||||||
|
; CHECK-NEXT: %cmp = icmp eq i32 %cmp.mask, 0
|
||||||
|
; CHECK-NEXT: %s = select i1 %cmp, i32 10000, i32 0
|
||||||
|
; CHECK-NEXT: ret i32 %s
|
||||||
|
define i32 @f6(i32 %a, i32 %b) {
|
||||||
|
%sext = shl i32 %a, 24
|
||||||
|
%conv = ashr i32 %sext, 24
|
||||||
|
%sext6 = shl i32 %b, 24
|
||||||
|
%conv4 = ashr i32 %sext6, 24
|
||||||
|
%cmp = icmp eq i32 %conv, %conv4
|
||||||
|
%s = select i1 %cmp, i32 10000, i32 0
|
||||||
|
ret i32 %s
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @f7
|
||||||
|
; CHECK: %cmp.unshifted = xor i32 %a, %b
|
||||||
|
; CHECK-NEXT: %cmp.mask = and i32 %cmp.unshifted, 511
|
||||||
|
; CHECK-NEXT: %cmp = icmp ne i32 %cmp.mask, 0
|
||||||
|
; CHECK-NEXT: %s = select i1 %cmp, i32 10000, i32 0
|
||||||
|
; CHECK-NEXT: ret i32 %s
|
||||||
|
define i32 @f7(i32 %a, i32 %b) {
|
||||||
|
%sext = shl i32 %a, 23
|
||||||
|
%sext6 = shl i32 %b, 23
|
||||||
|
%cmp = icmp ne i32 %sext, %sext6
|
||||||
|
%s = select i1 %cmp, i32 10000, i32 0
|
||||||
|
ret i32 %s
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user