Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -625,6 +625,8 @@ LLVMContext *Context; + DenseMap ExportedMap; + SelectionDAGBuilder(SelectionDAG &dag, FunctionLoweringInfo &funcinfo, CodeGenOpt::Level ol) : SDNodeOrder(LowestSDNodeOrder), TM(dag.getTarget()), DAG(dag), @@ -1067,7 +1069,7 @@ /// updates them for the output Chain/Flag. If the Flag pointer is nullptr, no /// flag is used. If V is not nullptr, then it is used in printing better /// diagnostic messages on error. - void getCopyToRegs(SDValue Val, SelectionDAG &DAG, const SDLoc &dl, + SDValue getCopyToRegs(SDValue Val, SelectionDAG &DAG, const SDLoc &dl, SDValue &Chain, SDValue *Flag, const Value *V = nullptr, ISD::NodeType PreferredExtendType = ISD::ANY_EXTEND) const; Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -873,7 +873,7 @@ return DAG.getNode(ISD::MERGE_VALUES, dl, DAG.getVTList(ValueVTs), Values); } -void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, +SDValue RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, const SDLoc &dl, SDValue &Chain, SDValue *Flag, const Value *V, ISD::NodeType PreferredExtendType) const { @@ -901,8 +901,8 @@ // Copy the parts into the registers. SmallVector Chains(NumRegs); + SDValue Part; for (unsigned i = 0; i != NumRegs; ++i) { - SDValue Part; if (!Flag) { Part = DAG.getCopyToReg(Chain, dl, Regs[i], Parts[i]); } else { @@ -927,6 +927,8 @@ Chain = Chains[NumRegs-1]; else Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains); + + return Part; } void RegsForValue::AddInlineAsmOperands(unsigned Code, bool HasMatching, @@ -1015,6 +1017,7 @@ HasTailCall = false; SDNodeOrder = LowestSDNodeOrder; StatepointLowering.clear(); + ExportedMap.clear(); } void SelectionDAGBuilder::clearDanglingDebugInfo() { @@ -1255,6 +1258,50 @@ << "\n"); } +// Helper for handleDebugValue to deal with dbg.value intrinsics that refer +// to a virtual register. If the original IR type was not a primitive, the +// variable location may have been split over several machine vregs, meaning +// the dbg.value must decompose into several DBG_VALUE insts and fragment +// expressions. +static void handleVRegDebugValue(const Value *V, DILocalVariable *Var, + DIExpression *Expr, DebugLoc dl, + DebugLoc InstDL, unsigned Order, + unsigned Reg, SDNode *Node, + const TargetLowering &TLI, + SelectionDAG &DAG) { + SDDbgValue *SDV; + // If this is a PHI node, it may be split up into several MI PHI nodes + // (in FunctionLoweringInfo::set). + RegsForValue RFV(V->getContext(), TLI, DAG.getDataLayout(), Reg, + V->getType(), None); + if (!RFV.occupiesMultipleRegs()) { + // Simple case: the value resides in one virtual register. + SDV = DAG.getVRegDbgValue(Var, Expr, Reg, Node, dl, Order); + DAG.AddDbgValue(SDV, Node, false); + } else { + // Hard case: split variable location into multiple vregs and fragments. + unsigned Offset = 0; + unsigned BitsToDescribe = Var->getSizeInBits().getValueOr(0); + for (auto RegAndSize : RFV.getRegsAndSizes()) { + unsigned RegisterSize = RegAndSize.second; + // Bail out if all bits are described already. + if (Offset >= BitsToDescribe) + break; + unsigned FragmentSize = (Offset + RegisterSize > BitsToDescribe) + ? BitsToDescribe - Offset + : RegisterSize; + auto FragmentExpr = DIExpression::createFragmentExpression( + Expr, Offset, FragmentSize); + if (!FragmentExpr) + continue; + SDV = DAG.getVRegDbgValue(Var, *FragmentExpr, RegAndSize.first, + false, dl, Order); + DAG.AddDbgValue(SDV, Node, false); + Offset += RegisterSize; + } + } +} + bool SelectionDAGBuilder::handleDebugValue(const Value *V, DILocalVariable *Var, DIExpression *Expr, DebugLoc dl, DebugLoc InstDL, unsigned Order) { @@ -1290,6 +1337,18 @@ if (N.getNode()) { if (EmitFuncArgumentDbgValue(V, Var, Expr, dl, false, N)) return true; + + // If this Value is exported from the current block, attach our debug + // record to the exporting CopyToReg, to avoid liveness issues. + if (ExportedMap.count(V)) { + SDValue &TheVal = ExportedMap.find(V)->second; + unsigned Reg = FuncInfo.ValueMap[V]; + + handleVRegDebugValue(V, Var, Expr, dl, InstDL, SDNodeOrder, Reg, + TheVal.getNode(), TLI, DAG); + return true; + } + SDV = getDbgValue(N, Var, Expr, dl, SDNodeOrder); DAG.AddDbgValue(SDV, N.getNode(), false); return true; @@ -1308,38 +1367,8 @@ auto VMI = FuncInfo.ValueMap.find(V); if (VMI != FuncInfo.ValueMap.end()) { unsigned Reg = VMI->second; - // If this is a PHI node, it may be split up into several MI PHI nodes - // (in FunctionLoweringInfo::set). - RegsForValue RFV(V->getContext(), TLI, DAG.getDataLayout(), Reg, - V->getType(), None); - if (RFV.occupiesMultipleRegs()) { - unsigned Offset = 0; - unsigned BitsToDescribe = 0; - if (auto VarSize = Var->getSizeInBits()) - BitsToDescribe = *VarSize; - if (auto Fragment = Expr->getFragmentInfo()) - BitsToDescribe = Fragment->SizeInBits; - for (auto RegAndSize : RFV.getRegsAndSizes()) { - unsigned RegisterSize = RegAndSize.second; - // Bail out if all bits are described already. - if (Offset >= BitsToDescribe) - break; - unsigned FragmentSize = (Offset + RegisterSize > BitsToDescribe) - ? BitsToDescribe - Offset - : RegisterSize; - auto FragmentExpr = DIExpression::createFragmentExpression( - Expr, Offset, FragmentSize); - if (!FragmentExpr) - continue; - SDV = DAG.getVRegDbgValue(Var, *FragmentExpr, RegAndSize.first, - false, dl, SDNodeOrder); - DAG.AddDbgValue(SDV, nullptr, false); - Offset += RegisterSize; - } - } else { - SDV = DAG.getVRegDbgValue(Var, Expr, Reg, false, dl, SDNodeOrder); - DAG.AddDbgValue(SDV, nullptr, false); - } + handleVRegDebugValue(V, Var, Expr, dl, InstDL, SDNodeOrder, Reg, nullptr, + TLI, DAG); return true; } } @@ -9228,8 +9257,10 @@ FuncInfo.PreferredExtendType.end()) ? ISD::ANY_EXTEND : FuncInfo.PreferredExtendType[V]; - RFV.getCopyToRegs(Op, DAG, getCurSDLoc(), Chain, nullptr, V, ExtendType); + SDValue CopyNode = + RFV.getCopyToRegs(Op, DAG, getCurSDLoc(), Chain, nullptr, V, ExtendType); PendingExports.push_back(Chain); + ExportedMap.insert(std::make_pair(V, CopyNode)); } #include "llvm/CodeGen/SelectionDAGISel.h"