if (Name.size() <= 8 || !Name.startswith("llvm."))
return false;
Name = Name.substr(5); // Strip off "llvm."
-
+
switch (Name[0]) {
default: break;
- case 'm':
- if (Name == "memory.barrier")
+ case 'c': {
+ if (Name.startswith("ctlz.") && F->arg_size() == 1) {
+ F->setName(Name + ".old");
+ NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctlz,
+ F->arg_begin()->getType());
+ return true;
+ }
+ if (Name.startswith("cttz.") && F->arg_size() == 1) {
+ F->setName(Name + ".old");
+ NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::cttz,
+ F->arg_begin()->getType());
return true;
+ }
break;
}
+ }
// This may not belong here. This function is effectively being overloaded
// to both detect an intrinsic which needs upgrading, and to provide the
// upgraded intrinsic. All argument and return casting must be provided in
// order to seamlessly integrate with existing context.
void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
- Function *F = CI->getCalledFunction();
+ assert(CI->getCalledFunction() && "Intrinsic call is not direct?");
+ if (!NewFn) return;
+
LLVMContext &C = CI->getContext();
- ImmutableCallSite CS(CI);
-
- assert(F && "CallInst has no function associated with it.");
-
- if (!NewFn) {
- if (F->getName() == "llvm.memory.barrier") {
- IRBuilder<> Builder(C);
- Builder.SetInsertPoint(CI->getParent(), CI);
-
- // Note that this conversion ignores the "device" bit; it was not really
- // well-defined, and got abused because nobody paid enough attention to
- // get it right. In practice, this probably doesn't matter; application
- // code generally doesn't need anything stronger than
- // SequentiallyConsistent (and realistically, SequentiallyConsistent
- // is lowered to a strong enough barrier for almost anything).
-
- if (cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue())
- Builder.CreateFence(SequentiallyConsistent);
- else if (!cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue())
- Builder.CreateFence(Release);
- else if (!cast<ConstantInt>(CI->getArgOperand(3))->getZExtValue())
- Builder.CreateFence(Acquire);
- else
- Builder.CreateFence(AcquireRelease);
-
- // Remove intrinsic.
- CI->eraseFromParent();
- } else {
- llvm_unreachable("Unknown function for CallInst upgrade.");
- }
+ 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;
}
}