summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/InstCombine/InstCombineCompares.cpp24
-rw-r--r--test/Transforms/InstCombine/intrinsics.ll30
2 files changed, 49 insertions, 5 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 90ab4f43df..abbc89b0a1 100644
--- a/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -1418,11 +1418,33 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
}
} else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(LHSI)) {
// Handle icmp {eq|ne} <intrinsic>, intcst.
- if (II->getIntrinsicID() == Intrinsic::bswap) {
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::bswap:
Worklist.Add(II);
ICI.setOperand(0, II->getOperand(1));
ICI.setOperand(1, ConstantInt::get(II->getContext(), RHSV.byteSwap()));
return &ICI;
+ case Intrinsic::ctlz:
+ case Intrinsic::cttz:
+ // ctz(A) == bitwidth(a) -> A == 0 and likewise for !=
+ if (RHSV == RHS->getType()->getBitWidth()) {
+ Worklist.Add(II);
+ ICI.setOperand(0, II->getOperand(1));
+ ICI.setOperand(1, ConstantInt::get(RHS->getType(), 0));
+ return &ICI;
+ }
+ break;
+ case Intrinsic::ctpop:
+ // popcount(A) == 0 -> A == 0 and likewise for !=
+ if (RHS->isZero()) {
+ Worklist.Add(II);
+ ICI.setOperand(0, II->getOperand(1));
+ ICI.setOperand(1, RHS);
+ return &ICI;
+ }
+ break;
+ default:
+ break;
}
}
}
diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll
index f899fc0ecd..c63475c2bd 100644
--- a/test/Transforms/InstCombine/intrinsics.ll
+++ b/test/Transforms/InstCombine/intrinsics.ll
@@ -6,6 +6,8 @@ declare %overflow.result @llvm.uadd.with.overflow.i8(i8, i8)
declare %overflow.result @llvm.umul.with.overflow.i8(i8, i8)
declare double @llvm.powi.f64(double, i32) nounwind readonly
declare i32 @llvm.cttz.i32(i32) nounwind readnone
+declare i32 @llvm.ctlz.i32(i32) nounwind readnone
+declare i32 @llvm.ctpop.i32(i32) nounwind readnone
declare i8 @llvm.ctlz.i8(i8) nounwind readnone
define i8 @test1(i8 %A, i8 %B) {
@@ -99,8 +101,7 @@ entry:
; CHECK: volatile store double %V
}
-define i32 @cttz(i32 %a)
-{
+define i32 @cttz(i32 %a) {
entry:
%or = or i32 %a, 8
%and = and i32 %or, -8
@@ -111,8 +112,7 @@ entry:
; CHECK-NEXT: ret i32 3
}
-define i8 @ctlz(i8 %a)
-{
+define i8 @ctlz(i8 %a) {
entry:
%or = or i8 %a, 32
%and = and i8 %or, 63
@@ -122,3 +122,25 @@ entry:
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i8 2
}
+
+define void @cmp.simplify(i32 %a, i32 %b, i1* %c) {
+entry:
+ %lz = tail call i32 @llvm.ctlz.i32(i32 %a) nounwind readnone
+ %lz.cmp = icmp eq i32 %lz, 32
+ volatile store i1 %lz.cmp, i1* %c
+ %tz = tail call i32 @llvm.cttz.i32(i32 %a) nounwind readnone
+ %tz.cmp = icmp ne i32 %tz, 32
+ volatile store i1 %tz.cmp, i1* %c
+ %pop = tail call i32 @llvm.ctpop.i32(i32 %b) nounwind readnone
+ %pop.cmp = icmp eq i32 %pop, 0
+ volatile store i1 %pop.cmp, i1* %c
+ ret void
+; CHECK: @cmp.simplify
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %lz.cmp = icmp eq i32 %a, 0
+; CHECK-NEXT: volatile store i1 %lz.cmp, i1* %c
+; CHECK-NEXT: %tz.cmp = icmp ne i32 %a, 0
+; CHECK-NEXT: volatile store i1 %tz.cmp, i1* %c
+; CHECK-NEXT: %pop.cmp = icmp eq i32 %b, 0
+; CHECK-NEXT: volatile store i1 %pop.cmp, i1* %c
+}