Index: llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -639,6 +639,97 @@ } } +/// Interpret the value loaded into register by \p curMI. +static bool interpretValue(const MachineInstr *CurMI, + FwdRegWorklist &ForwardedRegWorklist, + const DIExpression *EmptyExpr, ParamSet &Params, + bool ShouldTryEmitEntryVals, + FwdRegWorklist &NewWorklistItems) { + + auto *MF = CurMI->getMF(); + const auto &TRI = MF->getSubtarget().getRegisterInfo(); + const auto &TII = MF->getSubtarget().getInstrInfo(); + const auto &TLI = MF->getSubtarget().getTargetLowering(); + + // If the MI is an instruction defining one or more parameters' forwarding + // registers, add those defines. + auto getForwardingRegsDefinedByMI = [&](const MachineInstr &MI, + SmallSetVector &Defs) { + if (MI.isDebugInstr()) + return; + + for (const MachineOperand &MO : MI.operands()) { + if (MO.isReg() && MO.isDef() && + Register::isPhysicalRegister(MO.getReg())) { + for (auto FwdReg : ForwardedRegWorklist) + if (TRI->regsOverlap(FwdReg.first, MO.getReg())) + Defs.insert(FwdReg.first); + } + } + }; + + // Skip bundle headers. + if (CurMI->isBundle()) + return false; + + // 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 true; + + if (ForwardedRegWorklist.empty()) + return true; + + // Set of worklist registers that are defined by this instruction. + SmallSetVector FwdRegDefs; + + getForwardingRegsDefinedByMI(*CurMI, FwdRegDefs); + if (FwdRegDefs.empty()) + return false; + + 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 { + // 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]); + } + } + } + } + + // 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 : NewWorklistItems) + addToFwdRegWorklist(ForwardedRegWorklist, New.first, EmptyExpr, + New.second); + NewWorklistItems.clear(); + + return false; +} + /// 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, @@ -652,9 +743,6 @@ return; auto *MBB = CallMI->getParent(); - 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()); @@ -704,83 +792,11 @@ // as the entry value within basic blocks other than the first one. bool ShouldTryEmitEntryVals = MBB->getIterator() == MF->begin(); - // If the MI is an instruction defining one or more parameters' forwarding - // registers, add those defines. - auto getForwardingRegsDefinedByMI = [&](const MachineInstr &MI, - SmallSetVector &Defs) { - if (MI.isDebugInstr()) - return; - - for (const MachineOperand &MO : MI.operands()) { - if (MO.isReg() && MO.isDef() && - Register::isPhysicalRegister(MO.getReg())) { - for (auto FwdReg : ForwardedRegWorklist) - if (TRI->regsOverlap(FwdReg.first, MO.getReg())) - Defs.insert(FwdReg.first); - } - } - }; - // 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()) + if (interpretValue(&(*I), ForwardedRegWorklist, EmptyExpr, Params, + ShouldTryEmitEntryVals, NewWorklistItems)) return; - - if (ForwardedRegWorklist.empty()) - return; - - // Set of worklist registers that are defined by this instruction. - SmallSetVector FwdRegDefs; - - getForwardingRegsDefinedByMI(*I, FwdRegDefs); - if (FwdRegDefs.empty()) - continue; - - 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, - 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]); - } - } - } - } - - // 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 : NewWorklistItems) - addToFwdRegWorklist(ForwardedRegWorklist, New.first, EmptyExpr, - New.second); - NewWorklistItems.clear(); } // Emit the call site parameter's value as an entry value.