summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-01-23 18:49:30 +0000
committerChris Lattner <sabre@nondot.org>2010-01-23 18:49:30 +0000
commit818ff34bc0841edda10951b7b043076b6e7159ef (patch)
treec98b6b028a742d8c58e9b2cf66a33ce49ae1b35e
parenta9cf5b3cc9082acee5b6e30e989a667fed286b05 (diff)
downloadllvm-818ff34bc0841edda10951b7b043076b6e7159ef.tar.gz
llvm-818ff34bc0841edda10951b7b043076b6e7159ef.tar.bz2
llvm-818ff34bc0841edda10951b7b043076b6e7159ef.tar.xz
implement a simple instcombine xform that has been in the
readme forever. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94318 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/README.txt20
-rw-r--r--lib/Transforms/InstCombine/InstCombineShifts.cpp32
-rw-r--r--test/Transforms/InstCombine/intrinsics.ll15
3 files changed, 44 insertions, 23 deletions
diff --git a/lib/Target/README.txt b/lib/Target/README.txt
index 6c6290a70a..c68ae76a25 100644
--- a/lib/Target/README.txt
+++ b/lib/Target/README.txt
@@ -237,24 +237,6 @@ define void @test(i32* %P) {
//===---------------------------------------------------------------------===//
-dag/inst combine "clz(x)>>5 -> x==0" for 32-bit x.
-
-Compile:
-
-int bar(int x)
-{
- int t = __builtin_clz(x);
- return -(t>>5);
-}
-
-to:
-
-_bar: addic r3,r3,-1
- subfe r3,r3,r3
- blr
-
-//===---------------------------------------------------------------------===//
-
quantum_sigma_x in 462.libquantum contains the following loop:
for(i=0; i<reg->size; i++)
@@ -294,6 +276,8 @@ unsigned long reverse(unsigned v) {
//===---------------------------------------------------------------------===//
+[LOOP RECOGNITION]
+
These idioms should be recognized as popcount (see PR1488):
unsigned countbits_slow(unsigned v) {
diff --git a/lib/Transforms/InstCombine/InstCombineShifts.cpp b/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 321c91d57d..9dd60dd4a2 100644
--- a/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "InstCombine.h"
+#include "llvm/IntrinsicInst.h"
#include "llvm/Support/PatternMatch.h"
using namespace llvm;
using namespace PatternMatch;
@@ -69,10 +70,9 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
if (Op1->uge(TypeBits)) {
if (I.getOpcode() != Instruction::AShr)
return ReplaceInstUsesWith(I, Constant::getNullValue(Op0->getType()));
- else {
- I.setOperand(1, ConstantInt::get(I.getType(), TypeBits-1));
- return &I;
- }
+ // ashr i32 X, 32 --> ashr i32 X, 31
+ I.setOperand(1, ConstantInt::get(I.getType(), TypeBits-1));
+ return &I;
}
// ((X*C1) << C2) == (X * (C1 << C2))
@@ -387,7 +387,29 @@ Instruction *InstCombiner::visitShl(BinaryOperator &I) {
}
Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
- return commonShiftTransforms(I);
+ if (Instruction *R = commonShiftTransforms(I))
+ return R;
+
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+ if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1))
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Op0)) {
+ // ctlz.i32(x)>>5 --> zext(x == 0)
+ // cttz.i32(x)>>5 --> zext(x == 0)
+ // ctpop.i32(x)>>5 --> zext(x == -1)
+ if ((II->getIntrinsicID() == Intrinsic::ctlz ||
+ II->getIntrinsicID() == Intrinsic::cttz ||
+ II->getIntrinsicID() == Intrinsic::ctpop) &&
+ (1ULL << Op1C->getZExtValue()) ==
+ Op0->getType()->getScalarSizeInBits()) {
+ bool isCtPop = II->getIntrinsicID() == Intrinsic::ctpop;
+ Constant *RHS = ConstantInt::getSigned(Op0->getType(), isCtPop ? -1 : 0);
+ Value *Cmp = Builder->CreateICmpEQ(II->getOperand(1), RHS);
+ return new ZExtInst(Cmp, II->getType());
+ }
+ }
+
+ return 0;
}
Instruction *InstCombiner::visitAShr(BinaryOperator &I) {
diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll
index c63475c2bd..08dcfa731a 100644
--- a/test/Transforms/InstCombine/intrinsics.ll
+++ b/test/Transforms/InstCombine/intrinsics.ll
@@ -144,3 +144,18 @@ entry:
; CHECK-NEXT: %pop.cmp = icmp eq i32 %b, 0
; CHECK-NEXT: volatile store i1 %pop.cmp, i1* %c
}
+
+
+define i32 @cttz_simplify1(i32 %x) nounwind readnone ssp {
+ %tmp1 = tail call i32 @llvm.ctlz.i32(i32 %x) ; <i32> [#uses=1]
+ %shr3 = lshr i32 %tmp1, 5 ; <i32> [#uses=1]
+ ret i32 %shr3
+
+; CHECK: @cttz_simplify1
+; CHECK: icmp eq i32 %x, 0
+; CHECK-NEXT: zext i1
+; CHECK-NEXT: ret i32
+}
+
+declare i32 @llvm.ctlz.i32(i32) nounwind readnone
+