diff options
author | Chris Lattner <sabre@nondot.org> | 2005-05-11 20:24:12 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2005-05-11 20:24:12 +0000 |
commit | 991ce367980b4d9980c13a387c0d3a39290f3ba4 (patch) | |
tree | c518b60eed9627486ca4366209348307d9992178 /llvm/lib/CodeGen/IntrinsicLowering.cpp | |
parent | fe5759b0220d40637ece3df293a38039758febab (diff) | |
download | bcm5719-llvm-991ce367980b4d9980c13a387c0d3a39290f3ba4.tar.gz bcm5719-llvm-991ce367980b4d9980c13a387c0d3a39290f3ba4.zip |
Fix lowering of ctlz, so now UnitTests/2005-05-11-Popcount-ffs-fls passes
with the CBE
llvm-svn: 21875
Diffstat (limited to 'llvm/lib/CodeGen/IntrinsicLowering.cpp')
-rw-r--r-- | llvm/lib/CodeGen/IntrinsicLowering.cpp | 66 |
1 files changed, 26 insertions, 40 deletions
diff --git a/llvm/lib/CodeGen/IntrinsicLowering.cpp b/llvm/lib/CodeGen/IntrinsicLowering.cpp index 634f959f3c4..98d00f67f1b 100644 --- a/llvm/lib/CodeGen/IntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/IntrinsicLowering.cpp @@ -131,7 +131,6 @@ void DefaultIntrinsicLowering::AddPrototypes(Module &M) { /// instruction. static Value *LowerCTPOP(Value *V, Instruction *IP) { assert(V->getType()->isInteger() && "Can't ctpop a non-integer type!"); - unsigned BitSize = V->getType()->getPrimitiveSizeInBits(); static const uint64_t MaskValues[6] = { 0x5555555555555555ULL, 0x3333333333333333ULL, @@ -145,6 +144,7 @@ static Value *LowerCTPOP(Value *V, Instruction *IP) { if (DestTy->isSigned()) V = new CastInst(V, DestTy->getUnsignedVersion(), V->getName(), IP); + unsigned BitSize = V->getType()->getPrimitiveSizeInBits(); for (unsigned i = 1, ct = 0; i != BitSize; i <<= 1, ++ct) { Value *MaskCst = ConstantExpr::getCast(ConstantUInt::get(Type::ULongTy, @@ -161,6 +161,29 @@ static Value *LowerCTPOP(Value *V, Instruction *IP) { return V; } +/// LowerCTLZ - Emit the code to lower ctlz of V before the specified +/// instruction. +static Value *LowerCTLZ(Value *V, Instruction *IP) { + const Type *DestTy = V->getType(); + + // Force to unsigned so that the shift rights are logical. + if (DestTy->isSigned()) + V = new CastInst(V, DestTy->getUnsignedVersion(), V->getName(), IP); + + unsigned BitSize = V->getType()->getPrimitiveSizeInBits(); + for (unsigned i = 1; i != BitSize; i <<= 1) { + Value *ShVal = ConstantInt::get(Type::UByteTy, i); + ShVal = new ShiftInst(Instruction::Shr, V, ShVal, "ctlz.sh", IP); + V = BinaryOperator::createOr(V, ShVal, "ctlz.step", IP); + } + + if (V->getType() != DestTy) + V = new CastInst(V, DestTy, V->getName(), IP); + + V = BinaryOperator::createNot(V, "", IP); + return LowerCTPOP(V, IP); +} + void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { Function *Callee = CI->getCalledFunction(); assert(Callee && "Cannot lower an indirect call!"); @@ -210,46 +233,9 @@ void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { CI->replaceAllUsesWith(LowerCTPOP(CI->getOperand(1), CI)); break; - case Intrinsic::ctlz: { - Value *Src = CI->getOperand(1); - Value* SA; - switch (CI->getOperand(0)->getType()->getTypeID()) - { - case Type::LongTyID: - case Type::ULongTyID: - SA = ConstantUInt::get(Type::UByteTy, 32); - Src = BinaryOperator::createOr(Src, new ShiftInst(Instruction::Shr, Src, - SA, "", CI), "", CI); - case Type::IntTyID: - case Type::UIntTyID: - SA = ConstantUInt::get(Type::UByteTy, 16); - Src = BinaryOperator::createOr(Src, new ShiftInst(Instruction::Shr, - Src, SA, "", CI), - "", CI); - case Type::ShortTyID: - case Type::UShortTyID: - SA = ConstantUInt::get(Type::UByteTy, 8); - Src = BinaryOperator::createOr(Src, new ShiftInst(Instruction::Shr, - Src, SA, "", CI), - "", CI); - default: - SA = ConstantUInt::get(Type::UByteTy, 1); - Src = BinaryOperator::createOr(Src, new ShiftInst(Instruction::Shr, Src, - SA, "", CI), "", CI); - SA = ConstantUInt::get(Type::UByteTy, 2); - Src = BinaryOperator::createOr(Src, new ShiftInst(Instruction::Shr, Src, - SA, "", CI), "", CI); - SA = ConstantUInt::get(Type::UByteTy, 4); - Src = BinaryOperator::createOr(Src, new ShiftInst(Instruction::Shr, Src, - SA, "", CI), "", CI); - }; - Src = BinaryOperator::createNot(Src, "", CI); - - - Src = LowerCTPOP(Src, CI); - CI->replaceAllUsesWith(Src); + case Intrinsic::ctlz: + CI->replaceAllUsesWith(LowerCTLZ(CI->getOperand(1), CI)); break; - } case Intrinsic::cttz: { // cttz(x) -> ctpop(~X & (X-1)) Value *Src = CI->getOperand(1); |