diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -639,28 +639,18 @@ } } -/// Try to interpret values loaded into registers that forward parameters -/// for \p CallMI. Store parameters with interpreted value into \p Params. -static void collectCallSiteParameters(const MachineInstr *CallMI, - ParamSet &Params) { - auto *MF = CallMI->getMF(); - auto CalleesMap = MF->getCallSitesInfo(); - auto CallFwdRegsInfo = CalleesMap.find(CallMI); - - // There is no information for the call instruction. - if (CallFwdRegsInfo == CalleesMap.end()) - return; +/// Interpret values loaded into registers by \p CurMI. +static void interpretValues(const MachineInstr *CurMI, + FwdRegWorklist &ForwardedRegWorklist, + ParamSet &Params) { - auto *MBB = CallMI->getParent(); + const MachineFunction *MF = CurMI->getMF(); + const DIExpression *EmptyExpr = + DIExpression::get(MF->getFunction().getContext(), {}); const auto &TRI = *MF->getSubtarget().getRegisterInfo(); const auto &TII = *MF->getSubtarget().getInstrInfo(); const auto &TLI = *MF->getSubtarget().getTargetLowering(); - // Skip the call instruction. - auto I = std::next(CallMI->getReverseIterator()); - - FwdRegWorklist ForwardedRegWorklist; - // If an instruction defines more than one item in the worklist, we may run // into situations where a worklist register's value is (potentially) // described by the previous value of another register that is also defined @@ -680,29 +670,7 @@ // entry values, we simply postpone adding new parameter registers to the // worklist, by first keeping them in this temporary container until the // instruction has been handled. - FwdRegWorklist NewWorklistItems; - - const DIExpression *EmptyExpr = - DIExpression::get(MF->getFunction().getContext(), {}); - - // Add all the forwarding registers into the ForwardedRegWorklist. - for (auto ArgReg : CallFwdRegsInfo->second) { - bool InsertedReg = - ForwardedRegWorklist.insert({ArgReg.Reg, {{ArgReg.Reg, EmptyExpr}}}) - .second; - assert(InsertedReg && "Single register used to forward two arguments?"); - (void)InsertedReg; - } - - // We erase, from the ForwardedRegWorklist, those forwarding registers for - // which we successfully describe a loaded value (by using - // the describeLoadedValue()). For those remaining arguments in the working - // list, for which we do not describe a loaded value by - // the describeLoadedValue(), we try to generate an entry value expression - // for their call site value description, if the call is within the entry MBB. - // TODO: Handle situations when call site parameter value can be described - // as the entry value within basic blocks other than the first one. - bool ShouldTryEmitEntryVals = MBB->getIterator() == MF->begin(); + FwdRegWorklist TmpWorklistItems; // If the MI is an instruction defining one or more parameters' forwarding // registers, add those defines. @@ -721,66 +689,120 @@ } }; - // Search for a loading value in forwarding registers. - for (; I != MBB->rend(); ++I) { - // Skip bundle headers. - if (I->isBundle()) - continue; - - // If the next instruction is a call we can not interpret parameter's - // forwarding registers or we finished the interpretation of all parameters. - if (I->isCall()) - return; - - if (ForwardedRegWorklist.empty()) - return; - - // Set of worklist registers that are defined by this instruction. - SmallSetVector FwdRegDefs; + // Set of worklist registers that are defined by this instruction. + SmallSetVector FwdRegDefs; - getForwardingRegsDefinedByMI(*I, FwdRegDefs); - if (FwdRegDefs.empty()) - continue; + getForwardingRegsDefinedByMI(*CurMI, FwdRegDefs); + if (FwdRegDefs.empty()) + return; - for (auto ParamFwdReg : FwdRegDefs) { - if (auto ParamValue = TII.describeLoadedValue(*I, ParamFwdReg)) { - if (ParamValue->first.isImm()) { - int64_t Val = ParamValue->first.getImm(); - finishCallSiteParams(Val, ParamValue->second, + for (auto ParamFwdReg : FwdRegDefs) { + if (auto ParamValue = TII.describeLoadedValue(*CurMI, ParamFwdReg)) { + if (ParamValue->first.isImm()) { + int64_t Val = ParamValue->first.getImm(); + finishCallSiteParams(Val, ParamValue->second, + ForwardedRegWorklist[ParamFwdReg], Params); + } else if (ParamValue->first.isReg()) { + Register RegLoc = ParamValue->first.getReg(); + unsigned SP = TLI.getStackPointerRegisterToSaveRestore(); + Register FP = TRI.getFrameRegister(*MF); + bool IsSPorFP = (RegLoc == SP) || (RegLoc == FP); + if (TRI.isCalleeSavedPhysReg(RegLoc, *MF) || IsSPorFP) { + MachineLocation MLoc(RegLoc, /*IsIndirect=*/IsSPorFP); + finishCallSiteParams(MLoc, ParamValue->second, ForwardedRegWorklist[ParamFwdReg], Params); - } else if (ParamValue->first.isReg()) { - Register RegLoc = ParamValue->first.getReg(); - unsigned SP = TLI.getStackPointerRegisterToSaveRestore(); - Register FP = TRI.getFrameRegister(*MF); - bool IsSPorFP = (RegLoc == SP) || (RegLoc == FP); - if (TRI.isCalleeSavedPhysReg(RegLoc, *MF) || IsSPorFP) { - MachineLocation MLoc(RegLoc, /*IsIndirect=*/IsSPorFP); - finishCallSiteParams(MLoc, ParamValue->second, - ForwardedRegWorklist[ParamFwdReg], Params); - } else { - // ParamFwdReg was described by the non-callee saved register - // RegLoc. Mark that the call site values for the parameters are - // dependent on that register instead of ParamFwdReg. Since RegLoc - // may be a register that will be handled in this iteration, we - // postpone adding the items to the worklist, and instead keep them - // in a temporary container. - addToFwdRegWorklist(NewWorklistItems, RegLoc, ParamValue->second, - ForwardedRegWorklist[ParamFwdReg]); - } + } else { + // ParamFwdReg was described by the non-callee saved register + // RegLoc. Mark that the call site values for the parameters are + // dependent on that register instead of ParamFwdReg. Since RegLoc + // may be a register that will be handled in this iteration, we + // postpone adding the items to the worklist, and instead keep them + // in a temporary container. + addToFwdRegWorklist(TmpWorklistItems, RegLoc, ParamValue->second, + ForwardedRegWorklist[ParamFwdReg]); } } } + } + + // Remove all registers that this instruction defines from the worklist. + for (auto ParamFwdReg : FwdRegDefs) + ForwardedRegWorklist.erase(ParamFwdReg); - // Remove all registers that this instruction defines from the worklist. - for (auto ParamFwdReg : FwdRegDefs) - ForwardedRegWorklist.erase(ParamFwdReg); + // Now that we are done handling this instruction, add items from the + // temporary worklist to the real one. + for (auto New : TmpWorklistItems) + addToFwdRegWorklist(ForwardedRegWorklist, New.first, EmptyExpr, New.second); + TmpWorklistItems.clear(); +} - // Now that we are done handling this instruction, add items from the - // temporary worklist to the real one. - for (auto New : NewWorklistItems) - addToFwdRegWorklist(ForwardedRegWorklist, New.first, EmptyExpr, - New.second); - NewWorklistItems.clear(); +static bool interpretNextInstr(const MachineInstr *CurMI, + FwdRegWorklist &ForwardedRegWorklist, + ParamSet &Params) { + // Skip bundle headers. + if (CurMI->isBundle()) + return true; + + // If the next instruction is a call we can not interpret parameter's + // forwarding registers or we finished the interpretation of all + // parameters. + if (CurMI->isCall()) + return false; + + if (ForwardedRegWorklist.empty()) + return false; + + interpretValues(CurMI, ForwardedRegWorklist, Params); + + return true; +} + +/// Try to interpret values loaded into registers that forward parameters +/// for \p CallMI. Store parameters with interpreted value into \p Params. +static void collectCallSiteParameters(const MachineInstr *CallMI, + ParamSet &Params) { + const MachineFunction *MF = CallMI->getMF(); + auto CalleesMap = MF->getCallSitesInfo(); + auto CallFwdRegsInfo = CalleesMap.find(CallMI); + + // There is no information for the call instruction. + if (CallFwdRegsInfo == CalleesMap.end()) + return; + + const MachineBasicBlock *MBB = CallMI->getParent(); + + // Skip the call instruction. + auto I = std::next(CallMI->getReverseIterator()); + + FwdRegWorklist ForwardedRegWorklist; + + const DIExpression *EmptyExpr = + DIExpression::get(MF->getFunction().getContext(), {}); + + // Add all the forwarding registers into the ForwardedRegWorklist. + for (auto ArgReg : CallFwdRegsInfo->second) { + bool InsertedReg = + ForwardedRegWorklist.insert({ArgReg.Reg, {{ArgReg.Reg, EmptyExpr}}}) + .second; + assert(InsertedReg && "Single register used to forward two arguments?"); + (void)InsertedReg; + } + + // We erase, from the ForwardedRegWorklist, those forwarding registers for + // which we successfully describe a loaded value (by using + // the describeLoadedValue()). For those remaining arguments in the working + // list, for which we do not describe a loaded value by + // the describeLoadedValue(), we try to generate an entry value expression + // for their call site value description, if the call is within the entry MBB. + // TODO: Handle situations when call site parameter value can be described + // as the entry value within basic blocks other than the first one. + bool ShouldTryEmitEntryVals = MBB->getIterator() == MF->begin(); + + // Search for a loading value in forwarding registers. + for (; I != MBB->rend(); ++I) { + // Try to interpret values loaded by instruction. + if (!interpretNextInstr(&*I, ForwardedRegWorklist, Params)) + return; } // Emit the call site parameter's value as an entry value.