diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -561,15 +561,11 @@ MachineBasicBlock::iterator MBBI = MBB.end(); DebugLoc DL; if (!MBB.empty()) { + MBBI = MBB.getLastNonDebugInstr(); + if (MBBI != MBB.end()) + DL = MBBI->getDebugLoc(); + MBBI = MBB.getFirstTerminator(); - if (MBBI == MBB.end()) - MBBI = MBB.getLastNonDebugInstr(); - DL = MBBI->getDebugLoc(); - - // If this is not a terminator, the actual insert location should be after the - // last instruction. - if (!MBBI->isTerminator()) - MBBI = std::next(MBBI); // If callee-saved registers are saved via libcall, place stack adjustment // before this call. diff --git a/llvm/test/CodeGen/RISCV/xform_ah-min.mir b/llvm/test/CodeGen/RISCV/xform_ah-min.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/xform_ah-min.mir @@ -0,0 +1,177 @@ +# RUN: llc -mtriple=riscv64 -run-pass=prologepilog -o - %s | FileCheck %s + +# Check that we don't crash in prologepilog insertion when the restore +# point block has only debug value +--- | + ; ModuleID = 'xform_ah-min.ll' + source_filename = "xform_ah-min.ll" + target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128" + target triple = "riscv64" + + %struct.a = type { i32, i16 } + + define dso_local signext i32 @c(%struct.a* noundef readonly %d) local_unnamed_addr !dbg !8 { + entry: + call void @llvm.dbg.value(metadata %struct.a* %d, metadata !20, metadata !DIExpression()), !dbg !22 + %cmp = icmp eq %struct.a* %d, null, !dbg !23 + br i1 %cmp, label %cleanup, label %if.end, !dbg !25 + + if.end: ; preds = %entry + %b1 = bitcast %struct.a* %d to i32*, !dbg !26 + %0 = load i32, i32* %b1, align 4, !dbg !26, !tbaa !27 + %switch = icmp ult i32 %0, 2, !dbg !33 + br i1 %switch, label %sw.epilog.sink.split, label %sw.epilog, !dbg !33 + + sw.epilog.sink.split: ; preds = %if.end + %ab2 = getelementptr inbounds %struct.a, %struct.a* %d, i64 0, i32 1, !dbg !34 + %1 = load i16, i16* %ab2, align 4, !dbg !34, !tbaa !36 + br label %sw.epilog, !dbg !34 + + sw.epilog: ; preds = %sw.epilog.sink.split, %if.end + %a.0.shrunk = phi i16 [ 0, %if.end ], [ %1, %sw.epilog.sink.split ] + %a.0 = zext i16 %a.0.shrunk to i32, !dbg !34 + call void @llvm.dbg.value(metadata i32 %a.0, metadata !21, metadata !DIExpression()), !dbg !22 + br label %cleanup, !dbg !37 + + cleanup: ; preds = %sw.epilog, %entry + %retval.0 = phi i32 [ %a.0, %sw.epilog ], [ 0, %entry ], !dbg !22 + ret i32 %retval.0, !dbg !38 + } + + ; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn + declare void @llvm.dbg.value(metadata, metadata, metadata) + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!2, !3, !4, !5, !6} + !llvm.ident = !{!7} + + !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 15.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) + !1 = !DIFile(filename: "xform_ah-min.c", directory: "") + !2 = !{i32 7, !"Dwarf Version", i32 5} + !3 = !{i32 2, !"Debug Info Version", i32 3} + !4 = !{i32 1, !"wchar_size", i32 4} + !5 = !{i32 1, !"target-abi", !"lp64"} + !6 = !{i32 1, !"SmallDataLimit", i32 8} + !7 = !{!"clang version 15.0.0"} + !8 = distinct !DISubprogram(name: "c", scope: !1, file: !1, line: 6, type: !9, scopeLine: 6, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !19) + !9 = !DISubroutineType(types: !10) + !10 = !{!11, !12} + !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) + !12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64) + !13 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !14) + !14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "a", file: !1, line: 1, size: 64, elements: !15) + !15 = !{!16, !17} + !16 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !14, file: !1, line: 2, baseType: !11, size: 32) + !17 = !DIDerivedType(tag: DW_TAG_member, name: "ab", scope: !14, file: !1, line: 3, baseType: !18, size: 16, offset: 32) + !18 = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned) + !19 = !{!20, !21} + !20 = !DILocalVariable(name: "d", arg: 1, scope: !8, file: !1, line: 6, type: !12) + !21 = !DILocalVariable(name: "a", scope: !8, file: !1, line: 7, type: !11) + !22 = !DILocation(line: 0, scope: !8) + !23 = !DILocation(line: 8, column: 9, scope: !24) + !24 = distinct !DILexicalBlock(scope: !8, file: !1, line: 8, column: 7) + !25 = !DILocation(line: 8, column: 7, scope: !8) + !26 = !DILocation(line: 10, column: 14, scope: !8) + !27 = !{!28, !29, i64 0} + !28 = !{!"a", !29, i64 0, !32, i64 4} + !29 = !{!"int", !30, i64 0} + !30 = !{!"omnipotent char", !31, i64 0} + !31 = !{!"Simple C/C++ TBAA"} + !32 = !{!"short", !30, i64 0} + !33 = !DILocation(line: 10, column: 3, scope: !8) + !34 = !DILocation(line: 0, scope: !35) + !35 = distinct !DILexicalBlock(scope: !8, file: !1, line: 10, column: 17) + !36 = !{!28, !32, i64 4} + !37 = !DILocation(line: 20, column: 3, scope: !8) + !38 = !DILocation(line: 21, column: 1, scope: !8) + +... +--- +name: c +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +failsVerification: false +tracksDebugUserValues: true +registers: [] +liveins: + - { reg: '$x10', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 1 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + localFrameSize: 0 + savePoint: '%bb.2' + restorePoint: '%bb.5' +fixedStack: [] +stack: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + varArgsFrameIndex: 0 + varArgsSaveSize: 0 +body: | + bb.0.entry: + successors: %bb.1(0x30000000), %bb.2(0x50000000) + liveins: $x10 + + DBG_VALUE $x10, $noreg, !20, !DIExpression(), debug-location !22 + BNE renamable $x10, $x0, %bb.2, debug-location !25 + + bb.1: + successors: %bb.6(0x80000000) + liveins: $x10 + + PseudoBR %bb.6 + + bb.2.if.end: + successors: %bb.4(0x40000000), %bb.3(0x40000000) + liveins: $x10 + + renamable $x11 = LW renamable $x10, 0, debug-location !26 :: (load (s32) from %ir.b1, !tbaa !27) + renamable $x12 = ADDI $x0, 1 + BGEU killed renamable $x12, killed renamable $x11, %bb.4, debug-location !33 + + bb.3: + successors: %bb.5(0x80000000) + + renamable $x10 = COPY $x0 + PseudoBR %bb.5 + + bb.4.sw.epilog.sink.split: + successors: %bb.5(0x80000000) + liveins: $x10 + + renamable $x10 = LHU killed renamable $x10, 4, debug-location !34 :: (load (s16) from %ir.ab2, align 4, !tbaa !36) + + bb.5.sw.epilog: + successors: %bb.6(0x80000000) + liveins: $x10 + ; CHECK: DBG_VALUE $noreg, $noreg, !21, !DIExpression(), debug-location !22 + DBG_VALUE $noreg, $noreg, !21, !DIExpression(), debug-location !22 + + bb.6.cleanup: + liveins: $x10 + + PseudoRET implicit $x10, debug-location !38 + +...