[CSInfo][NFC] Interpret loaded parameter value separately
authorDjordje Todorovic <djordje.todorovic@syrmia.com>
Tue, 2 Jun 2020 09:44:32 +0000 (11:44 +0200)
committerDjordje Todorovic <djordje.todorovic@syrmia.com>
Tue, 2 Jun 2020 11:05:04 +0000 (13:05 +0200)
The collectCallSiteParameters() method searches for instructions
which load values into registers used for parameters passing.
Previously, interpretation of those values, loaded by one such
instruction, was implemented inside collectCallSiteParameters() method.

This patch moves the interpretation code from collectCallSiteParameters()
method into a separate static method named interpretValue. New method is
called from collectCallSiteParameters() to process each instruction from
targeted instruction scope.

The collectCallSiteParameters() searches for loaded parameter value
among instructions which precede the call instruction, inside the same
basic block. When needed, new method (interpretValue) could be used for
searching any instruction scope.

This is preparation for search of parameter value, loaded inside call
delay slot.

Patch by Nikola Tesic

Differential revision: https://reviews.llvm.org/D78106

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

index 9988301..a1ac00d 100644 (file)
@@ -639,28 +639,18 @@ static void addToFwdRegWorklist(FwdRegWorklist &Worklist, unsigned Reg,
   }
 }
 
-/// 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 @@ static void collectCallSiteParameters(const MachineInstr *CallMI,
   // 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 @@ static void collectCallSiteParameters(const MachineInstr *CallMI,
     }
   };
 
-  // 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.