Index: llvm/lib/CodeGen/MachineLICM.cpp =================================================================== --- llvm/lib/CodeGen/MachineLICM.cpp +++ llvm/lib/CodeGen/MachineLICM.cpp @@ -635,6 +635,11 @@ MachineBasicBlock *MBB = MI->getParent(); Preheader->splice(Preheader->getFirstTerminator(), MBB, MI); + // Since we are moving the instruction out of its basic block, we do not + // retain its debug location. Doing so would degrade the debugging + // experience and adversely affect the accuracy of profiling information. + MI->setDebugLoc(DebugLoc()); + // Add register to livein list to all the BBs in the current loop since a // loop invariant must be kept live throughout the whole loop. This is // important to ensure later passes do not scavenge the def register. @@ -829,7 +834,14 @@ } if (!CanSink || !B || B == Preheader) continue; + + LLVM_DEBUG(dbgs() << "Sinking to " << printMBBReference(*B) << " from " + << printMBBReference(*I->getParent()) << ": " << *I); B->splice(B->getFirstNonPHI(), Preheader, I); + + // The instructrions is moved from its basic block, so do not retain the + // debug information. + I->setDebugLoc(DebugLoc()); } } Index: llvm/test/DebugInfo/MIR/X86/mlicm-hoist-post-regalloc.mir =================================================================== --- /dev/null +++ llvm/test/DebugInfo/MIR/X86/mlicm-hoist-post-regalloc.mir @@ -0,0 +1,100 @@ +--- | + ; RUN: llc -start-before=phi-node-elimination -stop-after=machinelicm -debug-only=machinelicm -o - %s | FileCheck %s + ; Ensure we execute machinelicm post register allocation. + ; Line numbers should not be retained when loop invariant instructions are hoisted. + ; + ; CHECK-LABEL: bb.0.entry: + ; CHECK: MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @x, $noreg :: (load 8 from got) + ; CHECK-LABEL: bb.1.while.body: + ; + + @x = common local_unnamed_addr global i32 0, align 4, !dbg !0 + + ; Function Attrs: noreturn nounwind uwtable + define void @Process(i32* nocapture readonly %p) !dbg !9 { + entry: + tail call void @llvm.dbg.value(metadata i32* %p, i64 0, metadata !16, metadata !17), !dbg !18 + br label %while.body, !dbg !19 + + while.body: ; preds = %while.body, %entry + %p.addr.0 = phi i32* [ %p, %entry ], [ %incdec.ptr, %while.body ] + tail call void @llvm.dbg.value(metadata i32* %p.addr.0, i64 0, metadata !16, metadata !17), !dbg !18 + %incdec.ptr = getelementptr inbounds i32, i32* %p.addr.0, i64 1, !dbg !20 + tail call void @llvm.dbg.value(metadata i32* %incdec.ptr, i64 0, metadata !16, metadata !17), !dbg !18 + %0 = load i32, i32* %p.addr.0, align 4, !dbg !21, !tbaa !22 + store i32 %0, i32* @x, align 4, !dbg !26, !tbaa !22 + br label %while.body, !dbg !27, !llvm.loop !29 + } + + ; Function Attrs: nounwind readnone + declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1 + + + + !llvm.dbg.cu = !{!1} + !llvm.module.flags = !{!6, !7} + !llvm.ident = !{!8} + + !0 = !DIGlobalVariableExpression(var: !DIGlobalVariable(name: "x", scope: !1, file: !2, line: 1, type: !5, isLocal: false, isDefinition: true), expr: !DIExpression()) + !1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang version 10.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !4) + !2 = !DIFile(filename: "t.ll", directory: "/tmp/") + !3 = !{} + !4 = !{!0} + !5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) + !6 = !{i32 2, !"Dwarf Version", i32 4} + !7 = !{i32 2, !"Debug Info Version", i32 3} + !8 = !{!"clang version 4.0.0 "} + !9 = distinct !DISubprogram(name: "Process", scope: !2, file: !2, line: 2, type: !10, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !1, retainedNodes: !15) + !10 = !DISubroutineType(types: !11) + !11 = !{null, !12} + !12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64) + !13 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !14) + !14 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) + !15 = !{!16} + !16 = !DILocalVariable(name: "p", arg: 1, scope: !9, file: !2, line: 2, type: !12) + !17 = !DIExpression() + !18 = !DILocation(line: 2, column: 34, scope: !9) + !19 = !DILocation(line: 4, column: 3, scope: !9) + !20 = !DILocation(line: 5, column: 11, scope: !9) + !21 = !DILocation(line: 5, column: 9, scope: !9) + !22 = !{!23, !23, i64 0} + !23 = !{!"int", !24, i64 0} + !24 = !{!"omnipotent char", !25, i64 0} + !25 = !{!"C/C++"} + !26 = !DILocation(line: 5, column: 7, scope: !9) + !27 = !DILocation(line: 4, column: 3, scope: !28) + !28 = !DILexicalBlockFile(scope: !9, file: !2, discriminator: 1) + !29 = distinct !{!29, !19, !20} + +... +--- +name: Process +tracksRegLiveness: true +registers: + - { id: 0, class: gr64 } + - { id: 1, class: gr64 } + - { id: 2, class: gr64 } + - { id: 3, class: gr32 } + - { id: 4, class: gr64 } +body: | + bb.0.entry: + successors: %bb.1.while.body(0x80000000) + liveins: $rdi + + DBG_VALUE $rdi, _, !16, !17, debug-location !18 + %2 = COPY $rdi + DBG_VALUE %2, _, !16, !17, debug-location !18 + + bb.1.while.body: + successors: %bb.1.while.body(0x80000000) + + %0 = PHI %2, %bb.0.entry, %1, %bb.1.while.body + DBG_VALUE %0, _, !16, !17, debug-location !18 + %1 = ADD64ri8 %0, 4, implicit-def dead $eflags, debug-location !20 + DBG_VALUE %1, _, !16, !17, debug-location !18 + %3 = MOV32rm %0, 1, _, 0, _, debug-location !21 :: (load 4 from %ir.p.addr.0, !tbaa !22) + %4 = MOV64rm $rip, 1, _, target-flags(x86-gotpcrel) @x, _, debug-location !26 :: (load 8 from got) + MOV32mr killed %4, 1, _, 0, _, killed %3, debug-location !26 :: (store 4 into @x, !tbaa !22) + JMP_1 %bb.1.while.body, debug-location !27 + +... Index: llvm/test/DebugInfo/MIR/X86/mlicm-hoist-pre-regalloc.mir =================================================================== --- llvm/test/DebugInfo/MIR/X86/mlicm-hoist-pre-regalloc.mir +++ llvm/test/DebugInfo/MIR/X86/mlicm-hoist-pre-regalloc.mir @@ -23,13 +23,11 @@ ; ; ModuleID = 'tx.ll' source_filename = "t.c" - target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" - target triple = "x86_64-unknown-linux-gnu" @x = common local_unnamed_addr global i32 0, align 4, !dbg !0 ; Function Attrs: noreturn nounwind uwtable - define void @Process(i32* nocapture readonly %p) local_unnamed_addr #0 !dbg !9 { + define void @Process(i32* nocapture readonly %p) local_unnamed_addr !dbg !9 { entry: tail call void @llvm.dbg.value(metadata i32* %p, i64 0, metadata !16, metadata !17), !dbg !18 br label %while.body, !dbg !19 @@ -45,11 +43,7 @@ } ; Function Attrs: nounwind readnone - declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1 - - attributes #0 = { noreturn nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } - attributes #1 = { nounwind readnone } - attributes #2 = { nounwind } + declare void @llvm.dbg.value(metadata, i64, metadata, metadata) !llvm.dbg.cu = !{!1} !llvm.module.flags = !{!6, !7} @@ -80,7 +74,7 @@ !22 = !{!23, !23, i64 0} !23 = !{!"int", !24, i64 0} !24 = !{!"omnipotent char", !25, i64 0} - !25 = !{!"Simple C/C++ TBAA"} + !25 = !{!"C++"} !26 = !DILocation(line: 5, column: 7, scope: !9) !27 = !DILocation(line: 4, column: 3, scope: !28) !28 = !DILexicalBlockFile(scope: !9, file: !2, discriminator: 1) @@ -89,11 +83,6 @@ ... --- name: Process -alignment: 16 -exposesReturnsTwice: false -legalized: false -regBankSelected: false -selected: false tracksRegLiveness: true registers: - { id: 0, class: gr64 } @@ -101,22 +90,6 @@ - { id: 2, class: gr64 } - { id: 3, class: gr32 } - { id: 4, class: gr64 } -liveins: - - { reg: '$rdi', virtual-reg: '%2' } -frameInfo: - isFrameAddressTaken: false - isReturnAddressTaken: false - hasStackMap: false - hasPatchPoint: false - stackSize: 0 - offsetAdjustment: 0 - maxAlignment: 0 - adjustsStack: false - hasCalls: false - maxCallFrameSize: 0 - hasOpaqueSPAdjustment: false - hasVAStart: false - hasMustTailInVarArgFunc: false body: | bb.0.entry: successors: %bb.1.while.body(0x80000000) Index: llvm/test/DebugInfo/MIR/X86/mlicm-sink.mir =================================================================== --- /dev/null +++ llvm/test/DebugInfo/MIR/X86/mlicm-sink.mir @@ -0,0 +1,216 @@ +--- | + ; RUN: llc --run-pass=machinelicm -sink-insts-to-avoid-spills %s -o - | FileCheck %s + ; CHECK-LABEL: bb.4 (%ir-block.9): + ; CHECK: %0:gr64 = nuw ADD64ri8 %9, 4, implicit-def dead $eflags + ; + ; When instructions are sunk to prevent register spills, line numbers should not be retained. + + %struct.A = type { i32, i32, i32, i32, i32, i32 } + + define void @p(i8* nocapture readonly %input, %struct.A* %a) !dbg !10 { + %1 = getelementptr inbounds %struct.A, %struct.A* %a, i64 0, i32 1, !dbg !18 + %2 = getelementptr inbounds %struct.A, %struct.A* %a, i64 0, i32 2 + %3 = getelementptr inbounds %struct.A, %struct.A* %a, i64 0, i32 3 + %4 = getelementptr inbounds %struct.A, %struct.A* %a, i64 0, i32 4 + %5 = getelementptr inbounds %struct.A, %struct.A* %a, i64 0, i32 5 + %scevgep = getelementptr i8, i8* %input, i64 1 + br label %.backedge + + .backedge: ; preds = %.backedge.backedge, %0 + %lsr.iv = phi i8* [ %scevgep1, %.backedge.backedge ], [ %scevgep, %0 ] + %6 = load i8, i8* %lsr.iv, align 1 + switch i8 %6, label %.backedge.backedge [ + i8 0, label %7 + i8 10, label %9 + i8 20, label %10 + i8 30, label %11 + i8 40, label %12 + i8 50, label %13 + ] + + 7: ; preds = %.backedge + %8 = bitcast %struct.A* %a to i32* + tail call void @f(i32* %8) + br label %.backedge.backedge + + 9: ; preds = %.backedge + tail call void @f(i32* %1) + br label %.backedge.backedge + + .backedge.backedge: ; preds = %13, %12, %11, %10, %9, %7, %.backedge + %scevgep1 = getelementptr i8, i8* %lsr.iv, i64 1 + br label %.backedge + + 10: ; preds = %.backedge + tail call void @f(i32* %2) + br label %.backedge.backedge + + 11: ; preds = %.backedge + tail call void @f(i32* %3) + br label %.backedge.backedge + + 12: ; preds = %.backedge + tail call void @f(i32* %4) + br label %.backedge.backedge + + 13: ; preds = %.backedge + tail call void @f(i32* %5) + br label %.backedge.backedge + } + + declare void @f(i32*) + + ; Function Attrs: nounwind + declare void @llvm.stackprotector(i8*, i8**) + + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!7, !8} + !llvm.ident = !{!9} + + !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3) + !1 = !DIFile(filename: "t.ll", directory: "tmp/X86") + !2 = !{} + !3 = !{!4} + !4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression()) + !5 = !DIGlobalVariable(name: "x", scope: !0, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true) + !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) + !7 = !{i32 2, !"Dwarf Version", i32 4} + !8 = !{i32 2, !"Debug Info Version", i32 3} + !9 = !{!"clang version 10.0.0 "} + !10 = distinct !DISubprogram(name: "p", scope: !1, file: !1, line: 2, type: !11, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !16) + !11 = !DISubroutineType(types: !12) + !12 = !{null, !13} + !13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64) + !14 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !15) + !15 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) + !16 = !{!17} + !17 = !DILocalVariable(name: "a", arg: 1, scope: !10, file: !1, line: 2, type: !15) + !18 = !DILocation(line: 4, column: 3, scope: !10) + + +... +--- +name: p +tracksRegLiveness: true +registers: + - { id: 0, class: gr64, preferred-register: '' } + - { id: 1, class: gr64, preferred-register: '' } + - { id: 2, class: gr64, preferred-register: '' } + - { id: 3, class: gr64, preferred-register: '' } + - { id: 4, class: gr64, preferred-register: '' } + - { id: 5, class: gr64, preferred-register: '' } + - { id: 6, class: gr64, preferred-register: '' } + - { id: 7, class: gr64, preferred-register: '' } + - { id: 8, class: gr64, preferred-register: '' } + - { id: 9, class: gr64, preferred-register: '' } + - { id: 10, class: gr64_nosp, preferred-register: '' } + - { id: 11, class: gr32, preferred-register: '' } + - { id: 12, class: gr64, preferred-register: '' } + - { id: 13, class: gr64, preferred-register: '' } + - { id: 14, class: gr64, preferred-register: '' } + - { id: 15, class: gr64, preferred-register: '' } +jumpTable: + kind: label-difference32 + entries: + - id: 0 + blocks: [ '%bb.2', '%bb.4', '%bb.4', '%bb.4', '%bb.4', '%bb.4', + '%bb.4', '%bb.4', '%bb.4', '%bb.4', '%bb.3', '%bb.4', + '%bb.4', '%bb.4', '%bb.4', '%bb.4', '%bb.4', '%bb.4', + '%bb.4', '%bb.4', '%bb.5', '%bb.4', '%bb.4', '%bb.4', + '%bb.4', '%bb.4', '%bb.4', '%bb.4', '%bb.4', '%bb.4', + '%bb.6', '%bb.4', '%bb.4', '%bb.4', '%bb.4', '%bb.4', + '%bb.4', '%bb.4', '%bb.4', '%bb.4', '%bb.7', '%bb.4', + '%bb.4', '%bb.4', '%bb.4', '%bb.4', '%bb.4', '%bb.4', + '%bb.4', '%bb.4', '%bb.8' ] +body: | + bb.0 (%ir-block.0): + successors: %bb.1(0x80000000) + liveins: $rdi, $rsi + + %9:gr64 = COPY $rsi + %8:gr64 = COPY $rdi + %0:gr64 = nuw ADD64ri8 %9, 4, implicit-def dead $eflags, debug-location !18 + %1:gr64 = nuw ADD64ri8 %9, 8, implicit-def dead $eflags + %2:gr64 = nuw ADD64ri8 %9, 12, implicit-def dead $eflags + %3:gr64 = nuw ADD64ri8 %9, 16, implicit-def dead $eflags + %4:gr64 = nuw ADD64ri8 %9, 20, implicit-def dead $eflags + %5:gr64 = INC64r %8, implicit-def dead $eflags + + bb.1..backedge: + successors: %bb.4(0x09249249), %bb.9(0x76db6db7) + + %6:gr64 = PHI %5, %bb.0, %7, %bb.4 + %11:gr32 = MOVZX32rm8 %6, 1, $noreg, 0, $noreg :: (load 1 from %ir.lsr.iv) + %10:gr64_nosp = SUBREG_TO_REG 0, killed %11, %subreg.sub_32bit + %12:gr64 = SUB64ri8 %10, 50, implicit-def $eflags + JCC_1 %bb.4, 7, implicit $eflags + + bb.9..backedge: + successors: %bb.2(0x13b13b14), %bb.4(0x09d89d8a), %bb.3(0x13b13b14), %bb.5(0x13b13b14), %bb.6(0x13b13b14), %bb.7(0x13b13b14), %bb.8(0x13b13b14) + + %13:gr64 = LEA64r $rip, 1, $noreg, %jump-table.0, $noreg + %14:gr64 = MOVSX64rm32 %13, 4, %10, 0, $noreg :: (load 4 from jump-table) + %15:gr64 = ADD64rr %14, %13, implicit-def dead $eflags + JMP64r killed %15 + + bb.2 (%ir-block.7): + successors: %bb.4(0x80000000) + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %9 + CALL64pcrel32 target-flags(x86-plt) @f, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + JMP_1 %bb.4 + + bb.3 (%ir-block.9): + successors: %bb.4(0x80000000) + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %0 + CALL64pcrel32 target-flags(x86-plt) @f, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + + bb.4..backedge.backedge: + successors: %bb.1(0x80000000) + + %7:gr64 = INC64r %6, implicit-def dead $eflags + JMP_1 %bb.1 + + bb.5 (%ir-block.10): + successors: %bb.4(0x80000000) + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %1 + CALL64pcrel32 target-flags(x86-plt) @f, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + JMP_1 %bb.4 + + bb.6 (%ir-block.11): + successors: %bb.4(0x80000000) + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %2 + CALL64pcrel32 target-flags(x86-plt) @f, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + JMP_1 %bb.4 + + bb.7 (%ir-block.12): + successors: %bb.4(0x80000000) + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %3 + CALL64pcrel32 target-flags(x86-plt) @f, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + JMP_1 %bb.4 + + bb.8 (%ir-block.13): + successors: %bb.4(0x80000000) + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rdi = COPY %4 + CALL64pcrel32 target-flags(x86-plt) @f, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + JMP_1 %bb.4 + +...