|
38 | 38 | #include "llvm/IR/Function.h" |
39 | 39 | #include "llvm/IR/GlobalVariable.h" |
40 | 40 | #include "llvm/IR/IRBuilder.h" |
| 41 | +#include "llvm/IR/InstIterator.h" |
| 42 | +#include "llvm/IR/IntrinsicInst.h" |
41 | 43 | #include "llvm/IR/LLVMContext.h" |
42 | 44 | #include "llvm/IR/MDBuilder.h" |
43 | 45 | #include "llvm/IR/Metadata.h" |
@@ -7027,6 +7029,8 @@ static Expected<Function *> createOutlinedFunction( |
7027 | 7029 | ? make_range(Func->arg_begin() + 1, Func->arg_end()) |
7028 | 7030 | : Func->args(); |
7029 | 7031 |
|
| 7032 | + DenseMap<Value *, std::tuple<Value *, unsigned>> ValueReplacementMap; |
| 7033 | + |
7030 | 7034 | auto ReplaceValue = [](Value *Input, Value *InputCopy, Function *Func) { |
7031 | 7035 | // Things like GEP's can come in the form of Constants. Constants and |
7032 | 7036 | // ConstantExpr's do not have access to the knowledge of what they're |
@@ -7068,6 +7072,7 @@ static Expected<Function *> createOutlinedFunction( |
7068 | 7072 | if (!AfterIP) |
7069 | 7073 | return AfterIP.takeError(); |
7070 | 7074 | Builder.restoreIP(*AfterIP); |
| 7075 | + ValueReplacementMap[Input] = std::make_tuple(InputCopy, Arg.getArgNo()); |
7071 | 7076 |
|
7072 | 7077 | // In certain cases a Global may be set up for replacement, however, this |
7073 | 7078 | // Global may be used in multiple arguments to the kernel, just segmented |
@@ -7099,6 +7104,67 @@ static Expected<Function *> createOutlinedFunction( |
7099 | 7104 | for (auto Deferred : DeferredReplacement) |
7100 | 7105 | ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func); |
7101 | 7106 |
|
| 7107 | + DenseMap<const MDNode *, MDNode *> Cache; |
| 7108 | + SmallDenseMap<DILocalVariable *, DILocalVariable *> RemappedVariables; |
| 7109 | + |
| 7110 | + auto GetUpdatedDIVariable = [&](DILocalVariable *OldVar, unsigned arg) { |
| 7111 | + auto NewSP = Func->getSubprogram(); |
| 7112 | + DILocalVariable *&NewVar = RemappedVariables[OldVar]; |
| 7113 | + if (!NewVar) { |
| 7114 | + DILocalScope *NewScope = DILocalScope::cloneScopeForSubprogram( |
| 7115 | + *OldVar->getScope(), *NewSP, Builder.getContext(), Cache); |
| 7116 | + NewVar = llvm::DILocalVariable::get( |
| 7117 | + Builder.getContext(), NewScope, OldVar->getName(), OldVar->getFile(), |
| 7118 | + OldVar->getLine(), OldVar->getType(), arg, OldVar->getFlags(), |
| 7119 | + OldVar->getAlignInBits(), OldVar->getAnnotations()); |
| 7120 | + } |
| 7121 | + return NewVar; |
| 7122 | + }; |
| 7123 | + |
| 7124 | + DISubprogram *NewSP = Func->getSubprogram(); |
| 7125 | + if (NewSP) { |
| 7126 | + // The location and scope of variable intrinsics and records still point to |
| 7127 | + // the parent function of the target region. Update them. |
| 7128 | + for (Instruction &I : instructions(Func)) { |
| 7129 | + if (auto *DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&I)) { |
| 7130 | + DILocalVariable *OldVar = DDI->getVariable(); |
| 7131 | + unsigned ArgNo = OldVar->getArg(); |
| 7132 | + for (auto Loc : DDI->location_ops()) { |
| 7133 | + auto Iter = ValueReplacementMap.find(Loc); |
| 7134 | + if (Iter != ValueReplacementMap.end()) { |
| 7135 | + DDI->replaceVariableLocationOp(Loc, std::get<0>(Iter->second)); |
| 7136 | + ArgNo = std::get<1>(Iter->second) + 1; |
| 7137 | + } |
| 7138 | + } |
| 7139 | + DDI->setVariable(GetUpdatedDIVariable(OldVar, ArgNo)); |
| 7140 | + } |
| 7141 | + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { |
| 7142 | + DILocalVariable *OldVar = DVR.getVariable(); |
| 7143 | + unsigned ArgNo = OldVar->getArg(); |
| 7144 | + for (auto Loc : DVR.location_ops()) { |
| 7145 | + auto Iter = ValueReplacementMap.find(Loc); |
| 7146 | + if (Iter != ValueReplacementMap.end()) { |
| 7147 | + DVR.replaceVariableLocationOp(Loc, std::get<0>(Iter->second)); |
| 7148 | + ArgNo = std::get<1>(Iter->second) + 1; |
| 7149 | + } |
| 7150 | + } |
| 7151 | + DVR.setVariable(GetUpdatedDIVariable(OldVar, ArgNo)); |
| 7152 | + } |
| 7153 | + } |
| 7154 | + // An extra argument is passed to the device. Create the debug data for it. |
| 7155 | + if (OMPBuilder.Config.isTargetDevice()) { |
| 7156 | + DICompileUnit *CU = NewSP->getUnit(); |
| 7157 | + DIBuilder DB(*M, true, CU); |
| 7158 | + DIType *VoidPtrTy = |
| 7159 | + DB.createQualifiedType(dwarf::DW_TAG_pointer_type, nullptr); |
| 7160 | + DILocalVariable *Var = DB.createParameterVariable( |
| 7161 | + NewSP, "dyn_ptr", /*ArgNo*/ 1, NewSP->getFile(), /*LineNo=*/0, |
| 7162 | + VoidPtrTy, /*AlwaysPreserve=*/false, DINode::DIFlags::FlagArtificial); |
| 7163 | + auto Loc = DILocation::get(Func->getContext(), 0, 0, NewSP, 0); |
| 7164 | + DB.insertDeclare(&(*Func->arg_begin()), Var, DB.createExpression(), Loc, |
| 7165 | + &(*Func->begin())); |
| 7166 | + } |
| 7167 | + } |
7102 | 7168 | return Func; |
7103 | 7169 | } |
7104 | 7170 |
|
|
0 commit comments