From 818ff34bc0841edda10951b7b043076b6e7159ef Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 23 Jan 2010 18:49:30 +0000 Subject: [PATCH] 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 --- lib/Target/README.txt | 20 ++---------- .../InstCombine/InstCombineShifts.cpp | 32 ++++++++++++++++--- test/Transforms/InstCombine/intrinsics.ll | 15 +++++++++ 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/lib/Target/README.txt b/lib/Target/README.txt index 6c6290a70a1..c68ae76a257 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; isize; 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 321c91d57d2..9dd60dd4a25 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(Op1)) + if (IntrinsicInst *II = dyn_cast(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 c63475c2bd7..08dcfa731a9 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) ; [#uses=1] + %shr3 = lshr i32 %tmp1, 5 ; [#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 +