|
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" |
@@ -7069,6 +7071,8 @@ static Expected<Function *> createOutlinedFunction( |
7069 | 7071 | ? make_range(Func->arg_begin() + 1, Func->arg_end()) |
7070 | 7072 | : Func->args(); |
7071 | 7073 |
|
| 7074 | + DenseMap<Value *, std::tuple<Value *, unsigned>> ValueReplacementMap; |
| 7075 | + |
7072 | 7076 | auto ReplaceValue = [](Value *Input, Value *InputCopy, Function *Func) { |
7073 | 7077 | // Things like GEP's can come in the form of Constants. Constants and |
7074 | 7078 | // ConstantExpr's do not have access to the knowledge of what they're |
@@ -7110,6 +7114,7 @@ static Expected<Function *> createOutlinedFunction( |
7110 | 7114 | if (!AfterIP) |
7111 | 7115 | return AfterIP.takeError(); |
7112 | 7116 | Builder.restoreIP(*AfterIP); |
| 7117 | + ValueReplacementMap[Input] = std::make_tuple(InputCopy, Arg.getArgNo()); |
7113 | 7118 |
|
7114 | 7119 | // In certain cases a Global may be set up for replacement, however, this |
7115 | 7120 | // Global may be used in multiple arguments to the kernel, just segmented |
@@ -7141,6 +7146,67 @@ static Expected<Function *> createOutlinedFunction( |
7141 | 7146 | for (auto Deferred : DeferredReplacement) |
7142 | 7147 | ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func); |
7143 | 7148 |
|
| 7149 | + DenseMap<const MDNode *, MDNode *> Cache; |
| 7150 | + SmallDenseMap<DILocalVariable *, DILocalVariable *> RemappedVariables; |
| 7151 | + |
| 7152 | + auto GetUpdatedDIVariable = [&](DILocalVariable *OldVar, unsigned arg) { |
| 7153 | + auto NewSP = Func->getSubprogram(); |
| 7154 | + DILocalVariable *&NewVar = RemappedVariables[OldVar]; |
| 7155 | + if (!NewVar) { |
| 7156 | + DILocalScope *NewScope = DILocalScope::cloneScopeForSubprogram( |
| 7157 | + *OldVar->getScope(), *NewSP, Builder.getContext(), Cache); |
| 7158 | + NewVar = llvm::DILocalVariable::get( |
| 7159 | + Builder.getContext(), NewScope, OldVar->getName(), OldVar->getFile(), |
| 7160 | + OldVar->getLine(), OldVar->getType(), arg, OldVar->getFlags(), |
| 7161 | + OldVar->getAlignInBits(), OldVar->getAnnotations()); |
| 7162 | + } |
| 7163 | + return NewVar; |
| 7164 | + }; |
| 7165 | + |
| 7166 | + DISubprogram *NewSP = Func->getSubprogram(); |
| 7167 | + if (NewSP) { |
| 7168 | + // The location and scope of variable intrinsics and records still point to |
| 7169 | + // the parent function of the target region. Update them. |
| 7170 | + for (Instruction &I : instructions(Func)) { |
| 7171 | + if (auto *DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&I)) { |
| 7172 | + DILocalVariable *OldVar = DDI->getVariable(); |
| 7173 | + unsigned ArgNo = OldVar->getArg(); |
| 7174 | + for (auto Loc : DDI->location_ops()) { |
| 7175 | + auto Iter = ValueReplacementMap.find(Loc); |
| 7176 | + if (Iter != ValueReplacementMap.end()) { |
| 7177 | + DDI->replaceVariableLocationOp(Loc, std::get<0>(Iter->second)); |
| 7178 | + ArgNo = std::get<1>(Iter->second) + 1; |
| 7179 | + } |
| 7180 | + } |
| 7181 | + DDI->setVariable(GetUpdatedDIVariable(OldVar, ArgNo)); |
| 7182 | + } |
| 7183 | + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { |
| 7184 | + DILocalVariable *OldVar = DVR.getVariable(); |
| 7185 | + unsigned ArgNo = OldVar->getArg(); |
| 7186 | + for (auto Loc : DVR.location_ops()) { |
| 7187 | + auto Iter = ValueReplacementMap.find(Loc); |
| 7188 | + if (Iter != ValueReplacementMap.end()) { |
| 7189 | + DVR.replaceVariableLocationOp(Loc, std::get<0>(Iter->second)); |
| 7190 | + ArgNo = std::get<1>(Iter->second) + 1; |
| 7191 | + } |
| 7192 | + } |
| 7193 | + DVR.setVariable(GetUpdatedDIVariable(OldVar, ArgNo)); |
| 7194 | + } |
| 7195 | + } |
| 7196 | + // An extra argument is passed to the device. Create the debug data for it. |
| 7197 | + if (OMPBuilder.Config.isTargetDevice()) { |
| 7198 | + DICompileUnit *CU = NewSP->getUnit(); |
| 7199 | + DIBuilder DB(*M, true, CU); |
| 7200 | + DIType *VoidPtrTy = |
| 7201 | + DB.createQualifiedType(dwarf::DW_TAG_pointer_type, nullptr); |
| 7202 | + DILocalVariable *Var = DB.createParameterVariable( |
| 7203 | + NewSP, "dyn_ptr", /*ArgNo*/ 1, NewSP->getFile(), /*LineNo=*/0, |
| 7204 | + VoidPtrTy, /*AlwaysPreserve=*/false, DINode::DIFlags::FlagArtificial); |
| 7205 | + auto Loc = DILocation::get(Func->getContext(), 0, 0, NewSP, 0); |
| 7206 | + DB.insertDeclare(&(*Func->arg_begin()), Var, DB.createExpression(), Loc, |
| 7207 | + &(*Func->begin())); |
| 7208 | + } |
| 7209 | + } |
7144 | 7210 | return Func; |
7145 | 7211 | } |
7146 | 7212 |
|
|
0 commit comments