diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index 84a39ad0c87..7ceeb9c7d5d 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -284,8 +284,8 @@ def int_expect : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, let Properties = [IntrNoMem] in { def int_bswap: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; def int_ctpop: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; - def int_ctlz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; - def int_cttz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; + def int_ctlz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; + def int_cttz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; } //===------------------------ Debugger Intrinsics -------------------------===// diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index 7e98b218884..8e2f263cd4c 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -1290,10 +1290,6 @@ llvm::ConstantFoldCall(Function *F, ArrayRef Operands, return ConstantInt::get(F->getContext(), Op->getValue().byteSwap()); case Intrinsic::ctpop: return ConstantInt::get(Ty, Op->getValue().countPopulation()); - case Intrinsic::cttz: - return ConstantInt::get(Ty, Op->getValue().countTrailingZeros()); - case Intrinsic::ctlz: - return ConstantInt::get(Ty, Op->getValue().countLeadingZeros()); case Intrinsic::convert_from_fp16: { APFloat Val(Op->getValue()); @@ -1418,6 +1414,14 @@ llvm::ConstantFoldCall(Function *F, ArrayRef Operands, }; return ConstantStruct::get(cast(F->getReturnType()), Ops); } + case Intrinsic::cttz: + // FIXME: This should check for Op2 == 1, and become unreachable if + // Op1 == 0. + return ConstantInt::get(Ty, Op1->getValue().countTrailingZeros()); + case Intrinsic::ctlz: + // FIXME: This should check for Op2 == 1, and become unreachable if + // Op1 == 0. + return ConstantInt::get(Ty, Op1->getValue().countLeadingZeros()); } } diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 6e169de8291..075adc01873 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -999,7 +999,7 @@ struct FFSOpt : public LibCallOptimization { Type *ArgType = Op->getType(); Value *F = Intrinsic::getDeclaration(Callee->getParent(), Intrinsic::cttz, ArgType); - Value *V = B.CreateCall(F, Op, "cttz"); + Value *V = B.CreateCall2(F, Op, B.getFalse(), "cttz"); V = B.CreateAdd(V, ConstantInt::get(V->getType(), 1)); V = B.CreateIntCast(V, B.getInt32Ty(), false); diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp index 373524cdf38..6bdb115a9aa 100644 --- a/lib/VMCore/AutoUpgrade.cpp +++ b/lib/VMCore/AutoUpgrade.cpp @@ -40,7 +40,20 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { switch (Name[0]) { default: break; - // SOMEDAY: Add some. + case 'c': { + Type *Tys[] = { F->arg_begin()->getType() }; + if (Name.startswith("ctlz.") && F->arg_size() == 1) { + F->setName(Name + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctlz, Tys); + return true; + } + if (Name.startswith("cttz.") && F->arg_size() == 1) { + F->setName(Name + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::cttz, Tys); + return true; + } + break; + } } // This may not belong here. This function is effectively being overloaded @@ -72,15 +85,29 @@ bool llvm::UpgradeGlobalVariable(GlobalVariable *GV) { // order to seamlessly integrate with existing context. void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Function *F = CI->getCalledFunction(); + LLVMContext &C = CI->getContext(); assert(F && "CallInst has no function associated with it."); - if (NewFn) return; - - if (F->getName() == "llvm.something eventually") { - // UPGRADE HERE. - } else { + if (!NewFn) return; + + IRBuilder<> Builder(C); + Builder.SetInsertPoint(CI->getParent(), CI); + + switch (NewFn->getIntrinsicID()) { + default: llvm_unreachable("Unknown function for CallInst upgrade."); + + case Intrinsic::ctlz: + case Intrinsic::cttz: + assert(CI->getNumArgOperands() == 1 && + "Mismatch between function args and call args"); + StringRef Name = CI->getName(); + CI->setName(Name + ".old"); + CI->replaceAllUsesWith(Builder.CreateCall2(NewFn, CI->getArgOperand(0), + Builder.getFalse(), Name)); + CI->eraseFromParent(); + return; } }