[PATCH] D50638: [AsmPrinter] Look inside bundles and rely on FrameDestroy in calculateDbgValueHistory

Bjorn Pettersson via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 13 08:21:00 PDT 2018


bjope created this revision.

When DbgValueHistoryCalculator is determining which registers
that are clobbered within the function body it now got the
alternative to rely on FrameDestroy attributes when finding
out if an instruction is part of the epilogue or not.
In the past it treated all instructions with the same DebugLoc
as the return instruction as epilogue. So if for example the
whole function was written on a single line everything ended up
being treated as the epilogue.
For the above to work properly a target has to mark epilogue
instructions as FrameDestroy (I do not think all targets are
doing that, so therefore this isn't enabled by default).

Another difference between the old collectChangingRegs and
the new collectChangingRegsInBody is that the new method
examines individual instructions within bundles (to support
the case where a bundle contain a mix of prolog/epilog
instructions and function body instructions. That might be
an odd case, but there is nothing today that prohibits such
bundling.


Repository:
  rL LLVM

https://reviews.llvm.org/D50638

Files:
  include/llvm/CodeGen/TargetFrameLowering.h
  lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp


Index: lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
===================================================================
--- lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
+++ lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
@@ -15,6 +15,7 @@
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/TargetFrameLowering.h"
 #include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
@@ -187,11 +188,58 @@
   }
 }
 
+/// \brief Collect registers that are modified in the function (ignoring
+/// FrameSetup/FrameDestroy/Return instructions). Debug variables that are
+/// mapped to such registers need to be described using debug location ranges
+/// (as they aren't valid throughout the function). Compare this to a variable
+/// that is an argument to the function, being received in a register that isn't
+/// modified. Such a variable can be printed from anywhere inside the function
+/// and no range information is needed.
+static void collectChangingRegsInBody(const MachineFunction *MF,
+                                      const TargetRegisterInfo *TRI,
+                                      BitVector &Regs) {
+  for (const auto &MBB : *MF) {
+    // A bundle might contain a mix of FrameSetup/FrameDestroy and other
+    // instructions. So we need to use the instr iterator to analyse the
+    // individual instructions.
+    for (const auto &MI : MBB.instrs()) {
+      // We look inside the bundle, so skip the BUNDLE head.
+      if (MI.isBundle())
+        continue;
+      // Avoid looking at prologue or epilogue instructions.
+      if (MI.isReturn() ||
+          MI.getFlag(MachineInstr::FrameSetup) ||
+          MI.getFlag(MachineInstr::FrameDestroy))
+        continue;
+
+      // Look for register defs and register masks. Register masks are
+      // typically on calls and they clobber everything not in the mask.
+      for (const MachineOperand &MO : MI.operands()) {
+        // Skip virtual registers since they are handled by the parent.
+        if (MO.isReg() && MO.isDef() && MO.getReg() &&
+            !TRI->isVirtualRegister(MO.getReg())) {
+          for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
+               ++AI)
+            Regs.set(*AI);
+        } else if (MO.isRegMask()) {
+          Regs.setBitsNotInMask(MO.getRegMask());
+        }
+      }
+    }
+  }
+}
+
 void llvm::calculateDbgValueHistory(const MachineFunction *MF,
                                     const TargetRegisterInfo *TRI,
                                     DbgValueHistoryMap &Result) {
+  const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
+  bool LookInsideBundlesAndRelyOnFrameDestroy =
+    TFI->isFrameSetupAndFrameDestroySupported();
   BitVector ChangingRegs(TRI->getNumRegs());
-  collectChangingRegs(MF, TRI, ChangingRegs);
+  if (LookInsideBundlesAndRelyOnFrameDestroy)
+    collectChangingRegsInBody(MF, TRI, ChangingRegs);
+  else
+    collectChangingRegs(MF, TRI, ChangingRegs);
 
   const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
   unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
Index: include/llvm/CodeGen/TargetFrameLowering.h
===================================================================
--- include/llvm/CodeGen/TargetFrameLowering.h
+++ include/llvm/CodeGen/TargetFrameLowering.h
@@ -282,6 +282,12 @@
     report_fatal_error("WinEH not implemented for this target");
   }
 
+  /// Check if the target is updating FrameSetup and FrameDestroy attributes on
+  /// machine instructions.
+  virtual bool isFrameSetupAndFrameDestroySupported() const {
+    return false;
+  }
+
   /// This method is called during prolog/epilog code insertion to eliminate
   /// call frame setup and destroy pseudo instructions (but only if the Target
   /// is using them).  It is responsible for eliminating these instructions,


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D50638.160361.patch
Type: text/x-patch
Size: 4020 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180813/24cf6682/attachment.bin>


More information about the llvm-commits mailing list