}
}
-/// 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
// 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.
}
};
- // 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<unsigned, 4> FwdRegDefs;
+ // Set of worklist registers that are defined by this instruction.
+ SmallSetVector<unsigned, 4> 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.