diff options
Diffstat (limited to 'lib/IR/AutoUpgrade.cpp')
-rw-r--r-- | lib/IR/AutoUpgrade.cpp | 229 |
1 files changed, 152 insertions, 77 deletions
diff --git a/lib/IR/AutoUpgrade.cpp b/lib/IR/AutoUpgrade.cpp index 459bd880ccb0..e3544dfa9e08 100644 --- a/lib/IR/AutoUpgrade.cpp +++ b/lib/IR/AutoUpgrade.cpp @@ -15,6 +15,7 @@ #include "llvm/IR/CFG.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Function.h" @@ -43,6 +44,22 @@ static bool UpgradeSSE41Function(Function* F, Intrinsic::ID IID, return true; } +// Upgrade the declarations of intrinsic functions whose 8-bit immediate mask +// arguments have changed their type from i32 to i8. +static bool UpgradeX86IntrinsicsWith8BitMask(Function *F, Intrinsic::ID IID, + Function *&NewFn) { + // Check that the last argument is an i32. + Type *LastArgType = F->getFunctionType()->getParamType( + F->getFunctionType()->getNumParams() - 1); + if (!LastArgType->isIntegerTy(32)) + return false; + + // Move this function aside and map down. + F->setName(F->getName() + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), IID); + return true; +} + static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { assert(F && "Illegal to upgrade a non-existent Function."); @@ -90,6 +107,20 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { } break; } + case 'd': { + if (Name.startswith("dbg.declare") && F->arg_size() == 2) { + F->setName(Name + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_declare); + return true; + } + if (Name.startswith("dbg.value") && F->arg_size() == 3) { + F->setName(Name + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_value); + return true; + } + break; + } + case 'o': // We only need to change the name to match the mangling including the // address space. @@ -130,6 +161,51 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { if (Name == "x86.sse41.ptestnzc") return UpgradeSSE41Function(F, Intrinsic::x86_sse41_ptestnzc, NewFn); } + // Several blend and other instructions with maskes used the wrong number of + // bits. + if (Name == "x86.sse41.pblendw") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_pblendw, + NewFn); + if (Name == "x86.sse41.blendpd") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_blendpd, + NewFn); + if (Name == "x86.sse41.blendps") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_blendps, + NewFn); + if (Name == "x86.sse41.insertps") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_insertps, + NewFn); + if (Name == "x86.sse41.dppd") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_dppd, + NewFn); + if (Name == "x86.sse41.dpps") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_dpps, + NewFn); + if (Name == "x86.sse41.mpsadbw") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_mpsadbw, + NewFn); + if (Name == "x86.avx.blend.pd.256") + return UpgradeX86IntrinsicsWith8BitMask( + F, Intrinsic::x86_avx_blend_pd_256, NewFn); + if (Name == "x86.avx.blend.ps.256") + return UpgradeX86IntrinsicsWith8BitMask( + F, Intrinsic::x86_avx_blend_ps_256, NewFn); + if (Name == "x86.avx.dp.ps.256") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx_dp_ps_256, + NewFn); + if (Name == "x86.avx2.pblendw") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx2_pblendw, + NewFn); + if (Name == "x86.avx2.pblendd.128") + return UpgradeX86IntrinsicsWith8BitMask( + F, Intrinsic::x86_avx2_pblendd_128, NewFn); + if (Name == "x86.avx2.pblendd.256") + return UpgradeX86IntrinsicsWith8BitMask( + F, Intrinsic::x86_avx2_pblendd_256, NewFn); + if (Name == "x86.avx2.mpsadbw") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx2_mpsadbw, + NewFn); + // frcz.ss/sd may need to have an argument dropped if (Name.startswith("x86.xop.vfrcz.ss") && F->arg_size() == 2) { F->setName(Name + ".old"); @@ -173,66 +249,28 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) { return Upgraded; } -static bool UpgradeGlobalStructors(GlobalVariable *GV) { - ArrayType *ATy = dyn_cast<ArrayType>(GV->getType()->getElementType()); - StructType *OldTy = - ATy ? dyn_cast<StructType>(ATy->getElementType()) : nullptr; - - // Only upgrade an array of a two field struct with the appropriate field - // types. - if (!OldTy || OldTy->getNumElements() != 2) - return false; - - // Get the upgraded 3 element type. - PointerType *VoidPtrTy = Type::getInt8Ty(GV->getContext())->getPointerTo(); - Type *Tys[3] = { - OldTy->getElementType(0), - OldTy->getElementType(1), - VoidPtrTy - }; - StructType *NewTy = - StructType::get(GV->getContext(), Tys, /*isPacked=*/false); - - // Build new constants with a null third field filled in. - Constant *OldInitC = GV->getInitializer(); - ConstantArray *OldInit = dyn_cast<ConstantArray>(OldInitC); - if (!OldInit && !isa<ConstantAggregateZero>(OldInitC)) - return false; - std::vector<Constant *> Initializers; - if (OldInit) { - for (Use &U : OldInit->operands()) { - ConstantStruct *Init = cast<ConstantStruct>(&U); - Constant *NewInit = - ConstantStruct::get(NewTy, Init->getOperand(0), Init->getOperand(1), - Constant::getNullValue(VoidPtrTy), nullptr); - Initializers.push_back(NewInit); - } - } - assert(Initializers.size() == ATy->getNumElements()); - - // Replace the old GV with a new one. - ATy = ArrayType::get(NewTy, Initializers.size()); - Constant *NewInit = ConstantArray::get(ATy, Initializers); - GlobalVariable *NewGV = new GlobalVariable( - *GV->getParent(), ATy, GV->isConstant(), GV->getLinkage(), NewInit, "", - GV, GV->getThreadLocalMode(), GV->getType()->getAddressSpace(), - GV->isExternallyInitialized()); - NewGV->copyAttributesFrom(GV); - NewGV->takeName(GV); - assert(GV->use_empty() && "program cannot use initializer list"); - GV->eraseFromParent(); - return true; -} - bool llvm::UpgradeGlobalVariable(GlobalVariable *GV) { - if (GV->getName() == "llvm.global_ctors" || - GV->getName() == "llvm.global_dtors") - return UpgradeGlobalStructors(GV); - // Nothing to do yet. return false; } +static MDNode *getNodeField(const MDNode *DbgNode, unsigned Elt) { + if (!DbgNode || Elt >= DbgNode->getNumOperands()) + return nullptr; + return dyn_cast_or_null<MDNode>(DbgNode->getOperand(Elt)); +} + +static MetadataAsValue *getExpression(Value *VarOperand, Function *F) { + // Old-style DIVariables have an optional expression as the 8th element. + DIExpression Expr(getNodeField( + cast<MDNode>(cast<MetadataAsValue>(VarOperand)->getMetadata()), 8)); + if (!Expr) { + DIBuilder DIB(*F->getParent(), /*AllowUnresolved*/ false); + Expr = DIB.createExpression(); + } + return MetadataAsValue::get(F->getContext(), Expr); +} + // 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. @@ -269,8 +307,9 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Builder.SetInsertPoint(CI->getParent(), CI); Module *M = F->getParent(); - SmallVector<Value *, 1> Elts; - Elts.push_back(ConstantInt::get(Type::getInt32Ty(C), 1)); + SmallVector<Metadata *, 1> Elts; + Elts.push_back( + ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1))); MDNode *Node = MDNode::get(C, Elts); Value *Arg0 = CI->getArgOperand(0); @@ -396,12 +435,32 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { } std::string Name = CI->getName().str(); - CI->setName(Name + ".old"); + if (!Name.empty()) + CI->setName(Name + ".old"); switch (NewFn->getIntrinsicID()) { default: llvm_unreachable("Unknown function for CallInst upgrade."); + // Upgrade debug intrinsics to use an additional DIExpression argument. + case Intrinsic::dbg_declare: { + auto NewCI = + Builder.CreateCall3(NewFn, CI->getArgOperand(0), CI->getArgOperand(1), + getExpression(CI->getArgOperand(1), F), Name); + NewCI->setDebugLoc(CI->getDebugLoc()); + CI->replaceAllUsesWith(NewCI); + CI->eraseFromParent(); + return; + } + case Intrinsic::dbg_value: { + auto NewCI = Builder.CreateCall4( + NewFn, CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), + getExpression(CI->getArgOperand(2), F), Name); + NewCI->setDebugLoc(CI->getDebugLoc()); + CI->replaceAllUsesWith(NewCI); + CI->eraseFromParent(); + return; + } case Intrinsic::ctlz: case Intrinsic::cttz: assert(CI->getNumArgOperands() == 1 && @@ -419,14 +478,6 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { CI->eraseFromParent(); return; - case Intrinsic::arm_neon_vclz: { - // Change name from llvm.arm.neon.vclz.* to llvm.ctlz.* - CI->replaceAllUsesWith(Builder.CreateCall2(NewFn, CI->getArgOperand(0), - Builder.getFalse(), - "llvm.ctlz." + Name.substr(14))); - CI->eraseFromParent(); - return; - } case Intrinsic::ctpop: { CI->replaceAllUsesWith(Builder.CreateCall(NewFn, CI->getArgOperand(0))); CI->eraseFromParent(); @@ -468,6 +519,34 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { CI->eraseFromParent(); return; } + + case Intrinsic::x86_sse41_pblendw: + case Intrinsic::x86_sse41_blendpd: + case Intrinsic::x86_sse41_blendps: + case Intrinsic::x86_sse41_insertps: + case Intrinsic::x86_sse41_dppd: + case Intrinsic::x86_sse41_dpps: + case Intrinsic::x86_sse41_mpsadbw: + case Intrinsic::x86_avx_blend_pd_256: + case Intrinsic::x86_avx_blend_ps_256: + case Intrinsic::x86_avx_dp_ps_256: + case Intrinsic::x86_avx2_pblendw: + case Intrinsic::x86_avx2_pblendd_128: + case Intrinsic::x86_avx2_pblendd_256: + case Intrinsic::x86_avx2_mpsadbw: { + // Need to truncate the last argument from i32 to i8 -- this argument models + // an inherently 8-bit immediate operand to these x86 instructions. + SmallVector<Value *, 4> Args(CI->arg_operands().begin(), + CI->arg_operands().end()); + + // Replace the last argument with a trunc. + Args.back() = Builder.CreateTrunc(Args.back(), Type::getInt8Ty(C), "trunc"); + + CallInst *NewCall = Builder.CreateCall(NewFn, Args); + CI->replaceAllUsesWith(NewCall); + CI->eraseFromParent(); + return; + } } } @@ -501,22 +580,18 @@ void llvm::UpgradeInstWithTBAATag(Instruction *I) { return; if (MD->getNumOperands() == 3) { - Value *Elts[] = { - MD->getOperand(0), - MD->getOperand(1) - }; + Metadata *Elts[] = {MD->getOperand(0), MD->getOperand(1)}; MDNode *ScalarType = MDNode::get(I->getContext(), Elts); // Create a MDNode <ScalarType, ScalarType, offset 0, const> - Value *Elts2[] = { - ScalarType, ScalarType, - Constant::getNullValue(Type::getInt64Ty(I->getContext())), - MD->getOperand(2) - }; + Metadata *Elts2[] = {ScalarType, ScalarType, + ConstantAsMetadata::get(Constant::getNullValue( + Type::getInt64Ty(I->getContext()))), + MD->getOperand(2)}; I->setMetadata(LLVMContext::MD_tbaa, MDNode::get(I->getContext(), Elts2)); } else { // Create a MDNode <MD, MD, offset 0> - Value *Elts[] = {MD, MD, - Constant::getNullValue(Type::getInt64Ty(I->getContext()))}; + Metadata *Elts[] = {MD, MD, ConstantAsMetadata::get(Constant::getNullValue( + Type::getInt64Ty(I->getContext())))}; I->setMetadata(LLVMContext::MD_tbaa, MDNode::get(I->getContext(), Elts)); } } |