// UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call 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(); LLVMContext &C = CI->getContext(); ImmutableCallSite CS(CI); assert(F && "CallInst has no function associated with it."); if (!NewFn) { if (F->getName() == "llvm.x86.sse.loadu.ps" || F->getName() == "llvm.x86.sse2.loadu.dq" || F->getName() == "llvm.x86.sse2.loadu.pd") { // Convert to a native, unaligned load. const Type *VecTy = CI->getType(); const Type *IntTy = IntegerType::get(C, 128); IRBuilder<> Builder(C); Builder.SetInsertPoint(CI->getParent(), CI); Value *BC = Builder.CreateBitCast(CI->getArgOperand(0), PointerType::getUnqual(IntTy), "cast"); LoadInst *LI = Builder.CreateLoad(BC, CI->getName()); LI->setAlignment(1); // Unaligned load. BC = Builder.CreateBitCast(LI, VecTy, "new.cast"); // Fix up all the uses with our new load. if (!CI->use_empty()) CI->replaceAllUsesWith(BC); // Remove intrinsic. CI->eraseFromParent(); } else if (F->getName() == "llvm.x86.sse.movnt.ps" || F->getName() == "llvm.x86.sse2.movnt.dq" || F->getName() == "llvm.x86.sse2.movnt.pd" || F->getName() == "llvm.x86.sse2.movnt.i") { IRBuilder<> Builder(C); Builder.SetInsertPoint(CI->getParent(), CI); Module *M = F->getParent(); SmallVector<Value *, 1> Elts; Elts.push_back(ConstantInt::get(Type::getInt32Ty(C), 1)); MDNode *Node = MDNode::get(C, Elts); Value *Arg0 = CI->getArgOperand(0); Value *Arg1 = CI->getArgOperand(1); // Convert the type of the pointer to a pointer to the stored type. Value *BC = Builder.CreateBitCast(Arg0, PointerType::getUnqual(Arg1->getType()), "cast"); StoreInst *SI = Builder.CreateStore(Arg1, BC); SI->setMetadata(M->getMDKindID("nontemporal"), Node); SI->setAlignment(16); // Remove intrinsic. CI->eraseFromParent(); } else { llvm_unreachable("Unknown function for CallInst upgrade."); } return; } switch (NewFn->getIntrinsicID()) { case Intrinsic::prefetch: { IRBuilder<> Builder(C); Builder.SetInsertPoint(CI->getParent(), CI); const llvm::Type *I32Ty = llvm::Type::getInt32Ty(CI->getContext()); // Add the extra "data cache" argument Value *Operands[4] = { CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), llvm::ConstantInt::get(I32Ty, 1) }; CallInst *NewCI = CallInst::Create(NewFn, Operands, CI->getName(), CI); NewCI->setTailCall(CI->isTailCall()); NewCI->setCallingConv(CI->getCallingConv()); // Handle any uses of the old CallInst. if (!CI->use_empty()) // Replace all uses of the old call with the new cast which has the // correct type. CI->replaceAllUsesWith(NewCI); // Clean up the old call now that it has been completely upgraded. CI->eraseFromParent(); break; } } }