Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/ByteProvider.h"
#include "llvm/CodeGen/DAGCombine.h"
#include "llvm/CodeGen/ISDOpcodes.h"
Expand All @@ -51,6 +52,7 @@
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Metadata.h"
Expand Down Expand Up @@ -78,6 +80,7 @@
#include <variant>

#include "MatchContext.h"
#include "SDNodeDbgValue.h"

using namespace llvm;
using namespace llvm::SDPatternMatch;
Expand Down Expand Up @@ -14455,15 +14458,31 @@ static SDValue tryToFoldExtOfLoad(SelectionDAG &DAG, DAGCombiner &Combiner,
LN0->getBasePtr(), N0.getValueType(),
LN0->getMemOperand());
Combiner.ExtendSetCCUses(SetCCs, N0, ExtLoad, ExtOpc);

// If the load value is used only by N, replace it via CombineTo N.
bool NoReplaceTrunc = SDValue(LN0, 0).hasOneUse();
SDValue OldLoadVal(LN0, 0);
SDValue OldExtValue(N, 0);
bool NoReplaceTrunc = OldLoadVal.hasOneUse();
Combiner.CombineTo(N, ExtLoad);

if (NoReplaceTrunc) {
if (LN0->getHasDebugValue()) {
DAG.transferDbgValues(OldLoadVal, ExtLoad);
DAG.salvageDebugInfo(*ExtLoad.getNode());
}
if (N->getHasDebugValue())
DAG.transferDbgValues(OldExtValue, ExtLoad);
DAG.ReplaceAllUsesOfValueWith(SDValue(LN0, 1), ExtLoad.getValue(1));
Combiner.recursivelyDeleteUnusedNodes(LN0);
} else {
SDValue Trunc =
DAG.getNode(ISD::TRUNCATE, SDLoc(N0), N0.getValueType(), ExtLoad);
if (LN0->getHasDebugValue()) {
DAG.transferDbgValues(OldLoadVal, Trunc);
DAG.salvageDebugInfo(*Trunc.getNode());
}
if (N->getHasDebugValue())
DAG.transferDbgValues(OldExtValue, Trunc);
Combiner.CombineTo(LN0, Trunc, ExtLoad.getValue(1));
}
return SDValue(N, 0); // Return N so it doesn't get rechecked!
Expand Down
40 changes: 40 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12123,6 +12123,46 @@ void SelectionDAG::salvageDebugInfo(SDNode &N) {
dbgs() << " into " << *DbgExpression << '\n');
break;
}
case ISD::LOAD: {
SDValue N0 = N.getOperand(0);
if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(&N)) {

// Currently, this is written to only work for S|Z EXT.
if (LD->getExtensionType() == ISD::NON_EXTLOAD ||
LD->getExtensionType() == ISD::EXTLOAD)
break;

// Because we are replacing a load and a s|zext with a load-s|zext
// instruction, the dbg_value attached to the load will be of a smaller
// bit width, and we have to add a DW_OP_LLVM_fragment to the
// DIExpression.
unsigned VarBitsTo = LD->getValueSizeInBits(0);
unsigned VarBitsFrom = LD->getMemoryVT().getSizeInBits();
bool IsSigned = LD->getExtensionType() == ISD::SEXTLOAD;

// Build a convert expression for the s|z extend.
const DIExpression *OldE = DV->getExpression();
SmallVector<uint64_t, 8> Ops;
dwarf::TypeKind TK =
IsSigned ? dwarf::DW_ATE_signed : dwarf::DW_ATE_unsigned;
Ops.append({dwarf::DW_OP_LLVM_convert, VarBitsFrom, TK,
dwarf::DW_OP_LLVM_convert, VarBitsTo, TK});
auto *NewE = DIExpression::get(OldE->getContext(), Ops);

// Create a new SDDbgValue that points at the widened node with the
// fragment.
SDDbgValue *NewDV =
getDbgValue(DV->getVariable(), NewE, &N, N0.getResNo(),
DV->isIndirect(), DV->getDebugLoc(), DV->getOrder());
ClonedDVs.push_back(NewDV);
DV->setIsInvalidated();
DV->setIsEmitted();
LLVM_DEBUG(dbgs() << "SALVAGE: Rewriting";
N0.getNode()->dumprFull(this);
dbgs() << " into " << *NewE << '\n');
break;
}
}
}
}

Expand Down
53 changes: 53 additions & 0 deletions llvm/test/DebugInfo/X86/selectionDAG-load-sext.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
; This test checks that after SelectionDAG runs, it preserves the debug info that is lost due to the DAGCombiner combining a load and a sext instruction, where the #dbg_value is pointing to the result of the load.

; RUN: llc %s -mtriple=x86_64-unkown-linux -start-before=x86-isel -stop-after=x86-isel -o - | FileCheck %s --check-prefix=MIR
; RUN: llc -O2 %s -start-before=x86-isel -mtriple=x86_64-unkown-linux --filetype=obj -o %t.o
; RUN: llvm-dwarfdump %t.o --name Idx | FileCheck %s --check-prefix=DUMP

; MIR: ![[IDX:[0-9]+]] = !DILocalVariable(name: "Idx"
; MIR-LABEL: bb.0
; MIR: %{{[0-9a-f]+}}{{.*}} = MOVSX64rm32 ${{.*}}, 1, $noreg, @GlobArr, $noreg, debug-instr-number [[INSTR_NUM:[0-9]+]]
; MIR-NEXT: DBG_INSTR_REF ![[IDX]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_convert, 32, DW_ATE_signed, DW_OP_LLVM_convert, 64, DW_ATE_signed), dbg-instr-ref([[INSTR_NUM]], 0)

; DUMP: DW_AT_location (indexed ({{[0-9a-f]+}}x{{[0-9a-f]+}}) loclist = 0x{{[0-9]+}}:
; DUMP-NEXT: [0x{{[0-9a-f]+}}, 0x{{[0-9a-f]+}}): DW_OP_breg0 RAX+0, DW_OP_convert (0x{{[0-9a-f]+}}) "DW_ATE_signed_32", DW_OP_convert (0x{{[0-9a-f]+}}) "DW_ATE_signed_64")

@GlobArr = dso_local local_unnamed_addr global [5 x i32] [i32 1, i32 1, i32 2, i32 3, i32 5], align 16, !dbg !0
@__const.main.Data = private unnamed_addr constant [7 x i32] [i32 10, i32 20, i32 30, i32 40, i32 50, i32 60, i32 70], align 16
define dso_local void @_Z8useValuei(i32 noundef %0) local_unnamed_addr #0 !dbg !22 {
ret void, !dbg !28
}
define dso_local noundef i32 @main() local_unnamed_addr #1 !dbg !29 {
%1 = load i32, ptr @GlobArr
#dbg_value(i32 %1, !43, !DIExpression(), !52)
%2 = sext i32 %1 to i64
%3 = getelementptr inbounds i32, ptr @__const.main.Data, i64 %2
%4 = load i32, ptr %3
tail call void @_Z8useValuei(i32 noundef %4), !dbg !56
ret i32 0
}
!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!10, !11, !16}
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(type: !6, isDefinition: true)
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, emissionKind: FullDebug, nameTableKind: None)
!3 = !DIFile(filename: "/tmp/test.cpp", directory: "/Users/srastogi/Development/llvm-project/build_ninja", checksumkind: CSK_MD5, checksum: "0fe735937e606b4db3e3b2e9253eff90")
!6 = !DICompositeType(tag: DW_TAG_array_type, elements: !8)
!7 = !DIBasicType()
!8 = !{}
!10 = !{i32 7, !"Dwarf Version", i32 5}
!11 = !{i32 2, !"Debug Info Version", i32 3}
!16 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
!22 = distinct !DISubprogram(type: !23, unit: !2, keyInstructions: true)
!23 = !DISubroutineType(types: !24)
!24 = !{}
!28 = !DILocation(scope: !22, atomRank: 1)
!29 = distinct !DISubprogram(type: !30, unit: !2, keyInstructions: true)
!30 = !DISubroutineType(types: !31)
!31 = !{}
!38 = distinct !DILexicalBlock(scope: !29, line: 5, column: 3)
!43 = !DILocalVariable(name: "Idx", scope: !44, type: !7)
!44 = distinct !DILexicalBlock(scope: !38, line: 5, column: 3)
!46 = distinct !DILexicalBlock(scope: !44, line: 5, column: 27)
!52 = !DILocation(scope: !44)
!56 = !DILocation(scope: !46)
Loading