summaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/CodeGenCommonISel.cpp
diff options
context:
space:
mode:
authorVladislav Dzhidzhoev <vdzhidzhoev@accesssoftek.com>2022-08-01 09:55:27 +0200
committerKristina Bessonova <kbessonova@accesssoftek.com>2022-08-01 11:14:53 +0200
commitfacb3ac385c3c5fc6775ea320ed2fcfeb2f595f6 (patch)
tree207d80099562f9152b630585dfdbefbd8218a04e /llvm/lib/CodeGen/CodeGenCommonISel.cpp
parent9bf2d8cbbe0e42a772d572e09f636e34dde357d6 (diff)
[GlobalISel][DebugInfo] salvageDebugInfo analogue for gMIR
Salvage debug info of instruction that is about to be deleted as dead in Combiner pass. Currently supported instructions are COPY and G_TRUNC. It allows to salvage debug info of some dead arguments of functions, by putting DWARF expression corresponding to the instruction being deleted into related DBG_VALUE instruction. Here is an example of missing variables location https://godbolt.org/z/K48osb9dK. We see that arguments x, y of function foo are not available in debugger, and corresponding DBG_VALUE instructions have undefined register operand instead of variables locaton after Aarch64PreLegalizerCombiner pass. The reason is that registers where variables are located are removed as dead (with instruction G_TRUNC). We can use salvageDebugInfo analogue for gMIR to preserve debug locations of dead variables. Statistics of llvm object files built with vs without this commit on -O2 optimization level (CMAKE_BUILD_TYPE=RelWithDebInfo, -fglobal-isel) on Aarch64 (macOS): Number of variables with 100% of parent scope covered by DW_AT_location has been increased by 7,9%. Number of variables with 0% coverage of parent scope has been decreased by 1,2%. Number of variables processed by location statistics has been increased by 2,9%. Average PC ranges coverage has been increased by 1,8 percentage points. Coverage can be improved by supporting more instructions, or by calling salvageDebugInfo for instructions that are deleted during Combiner rules exection. Reviewed By: aprantl Differential Revision: https://reviews.llvm.org/D129909
Diffstat (limited to 'llvm/lib/CodeGen/CodeGenCommonISel.cpp')
-rw-r--r--llvm/lib/CodeGen/CodeGenCommonISel.cpp88
1 files changed, 88 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/CodeGenCommonISel.cpp b/llvm/lib/CodeGen/CodeGenCommonISel.cpp
index 8f185a161bd0..44cdd8275bed 100644
--- a/llvm/lib/CodeGen/CodeGenCommonISel.cpp
+++ b/llvm/lib/CodeGen/CodeGenCommonISel.cpp
@@ -17,6 +17,9 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetOpcodes.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+
+#define DEBUG_TYPE "codegen-common"
using namespace llvm;
@@ -197,3 +200,88 @@ unsigned llvm::getInvertedFPClassTest(unsigned Test) {
}
return 0;
}
+
+static MachineOperand *getSalvageOpsForCopy(const MachineRegisterInfo &MRI,
+ MachineInstr &Copy) {
+ assert(Copy.getOpcode() == TargetOpcode::COPY && "Must be a COPY");
+
+ return &Copy.getOperand(1);
+}
+
+static MachineOperand *getSalvageOpsForTrunc(const MachineRegisterInfo &MRI,
+ MachineInstr &Trunc,
+ SmallVectorImpl<uint64_t> &Ops) {
+ assert(Trunc.getOpcode() == TargetOpcode::G_TRUNC && "Must be a G_TRUNC");
+
+ const auto FromLLT = MRI.getType(Trunc.getOperand(1).getReg());
+ const auto ToLLT = MRI.getType(Trunc.defs().begin()->getReg());
+
+ // TODO: Support non-scalar types.
+ if (!FromLLT.isScalar()) {
+ return nullptr;
+ }
+
+ auto ExtOps = DIExpression::getExtOps(FromLLT.getSizeInBits(),
+ ToLLT.getSizeInBits(), false);
+ Ops.append(ExtOps.begin(), ExtOps.end());
+ return &Trunc.getOperand(1);
+}
+
+static MachineOperand *salvageDebugInfoImpl(const MachineRegisterInfo &MRI,
+ MachineInstr &MI,
+ SmallVectorImpl<uint64_t> &Ops) {
+ switch (MI.getOpcode()) {
+ case TargetOpcode::G_TRUNC:
+ return getSalvageOpsForTrunc(MRI, MI, Ops);
+ case TargetOpcode::COPY:
+ return getSalvageOpsForCopy(MRI, MI);
+ default:
+ return nullptr;
+ }
+}
+
+void llvm::salvageDebugInfoForDbgValue(const MachineRegisterInfo &MRI,
+ MachineInstr &MI,
+ ArrayRef<MachineOperand *> DbgUsers) {
+ // These are arbitrary chosen limits on the maximum number of values and the
+ // maximum size of a debug expression we can salvage up to, used for
+ // performance reasons.
+ const unsigned MaxExpressionSize = 128;
+
+ for (auto *DefMO : DbgUsers) {
+ MachineInstr *DbgMI = DefMO->getParent();
+ if (DbgMI->isIndirectDebugValue()) {
+ continue;
+ }
+
+ int UseMOIdx = DbgMI->findRegisterUseOperandIdx(DefMO->getReg());
+ assert(UseMOIdx != -1 && DbgMI->hasDebugOperandForReg(DefMO->getReg()) &&
+ "Must use salvaged instruction as its location");
+
+ // TODO: Support DBG_VALUE_LIST.
+ if (DbgMI->getOpcode() != TargetOpcode::DBG_VALUE) {
+ assert(DbgMI->getOpcode() == TargetOpcode::DBG_VALUE_LIST &&
+ "Must be either DBG_VALUE or DBG_VALUE_LIST");
+ continue;
+ }
+
+ const DIExpression *SalvagedExpr = DbgMI->getDebugExpression();
+
+ SmallVector<uint64_t, 16> Ops;
+ auto Op0 = salvageDebugInfoImpl(MRI, MI, Ops);
+ if (!Op0)
+ continue;
+ SalvagedExpr = DIExpression::appendOpsToArg(SalvagedExpr, Ops, 0, true);
+
+ bool IsValidSalvageExpr =
+ SalvagedExpr->getNumElements() <= MaxExpressionSize;
+ if (IsValidSalvageExpr) {
+ auto &UseMO = DbgMI->getOperand(UseMOIdx);
+ UseMO.setReg(Op0->getReg());
+ UseMO.setSubReg(Op0->getSubReg());
+ DbgMI->getDebugExpressionOp().setMetadata(SalvagedExpr);
+
+ LLVM_DEBUG(dbgs() << "SALVAGE: " << *DbgMI << '\n');
+ }
+ }
+}