Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -423,6 +423,8 @@ LLVMContext *Context; + DenseMap ExportedMap; + SelectionDAGBuilder(SelectionDAG &dag, FunctionLoweringInfo &funcinfo, SwiftErrorValueTracking &swifterror, CodeGenOpt::Level ol) : SDNodeOrder(LowestSDNodeOrder), TM(dag.getTarget()), DAG(dag), @@ -867,7 +869,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 @@ -883,7 +883,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 { @@ -911,8 +911,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 { @@ -937,6 +937,8 @@ Chain = Chains[NumRegs-1]; else Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains); + + return Part; } void RegsForValue::AddInlineAsmOperands(unsigned Code, bool HasMatching, @@ -1026,6 +1028,7 @@ HasTailCall = false; SDNodeOrder = LowestSDNodeOrder; StatepointLowering.clear(); + ExportedMap.clear(); } void SelectionDAGBuilder::clearDanglingDebugInfo() { @@ -1266,6 +1269,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, false, dl, Order); + DAG.AddDbgValue(SDV, Node, false); + return; + } + + // 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) { @@ -1301,6 +1348,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; @@ -1319,38 +1378,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; } } @@ -9266,8 +9295,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"