aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Dardis <simon.dardis@mips.com>2017-10-26 10:58:36 +0000
committerMiodrag Dinic <miodrag.dinic@mips.com>2018-03-07 09:38:23 +0100
commitdde7079dcaab96dda95fea06108811c26fd1223a (patch)
tree431fd47d0f446465bd3f9791e520a3d73482412d
parent78863c2c48e0b5dc8f0431e23879eb35c8c00e68 (diff)
downloadllvm-dde7079dcaab96dda95fea06108811c26fd1223a.tar.gz
[mips] Fix PR35071
PR35071 exposed the fact that MipsInstrInfo::removeBranch did not walk past debug instructions when removing branches for the control flow optimizer, which lead to duplicated conditional branches. If the target of the branch was a removable block, only the conditional branch in the terminating position would have it's MBB operands updated, leaving the first branch with a dangling MBB operand. The MIPS long branch pass would then trigger an assertion when attempting to examine the instruction with dangling MBB operand. This resolves PR35071. Thanks to Alex Richardson for reporting the issue! Reviewers: atanasyan Differential Revision: https://reviews.llvm.org/D39288 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@316654 91177308-0d34-0410-b5e6-96231b3b80d8 (cherry picked from commit 46690e4aa0b197b7576af99c7b4c6b753de4cdd8) Change-Id: I698e714ae99c4f2cb6aca162672c0220cdc0657a
-rw-r--r--lib/Target/Mips/MipsInstrInfo.cpp25
-rw-r--r--test/CodeGen/Mips/pr35071.ll73
2 files changed, 85 insertions, 13 deletions
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp
index f1526eb2e21..661ead4803b 100644
--- a/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/lib/Target/Mips/MipsInstrInfo.cpp
@@ -157,24 +157,23 @@ unsigned MipsInstrInfo::removeBranch(MachineBasicBlock &MBB,
assert(!BytesRemoved && "code size not handled");
MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend();
- unsigned removed;
-
- // Skip all the debug instructions.
- while (I != REnd && I->isDebugValue())
- ++I;
-
- if (I == REnd)
- return 0;
-
- MachineBasicBlock::iterator FirstBr = ++I.getReverse();
+ unsigned removed = 0;
// Up to 2 branches are removed.
// Note that indirect branches are not removed.
- for (removed = 0; I != REnd && removed < 2; ++I, ++removed)
+ while (I != REnd && removed < 2) {
+ // Skip past debug instructions.
+ if (I->isDebugValue()) {
+ ++I;
+ continue;
+ }
if (!getAnalyzableBrOpc(I->getOpcode()))
break;
-
- MBB.erase((--I).getReverse(), FirstBr);
+ // Remove the branch.
+ I->eraseFromParent();
+ I = MBB.rbegin();
+ ++removed;
+ }
return removed;
}
diff --git a/test/CodeGen/Mips/pr35071.ll b/test/CodeGen/Mips/pr35071.ll
new file mode 100644
index 00000000000..ae60f69a080
--- /dev/null
+++ b/test/CodeGen/Mips/pr35071.ll
@@ -0,0 +1,73 @@
+; RUN: llc -mtriple mips64-unknown-freebsd12.0 -relocation-model pic -mcpu=mips4 -target-abi n64 -O2 -o - %s
+
+; Test that the long branch pass does not crash due to the control flow
+; optimizer producing malformed basic block operands due to the backend
+; failing to handle debug information around branch instructions.
+
+define void @f() !dbg !5 {
+entry:
+ %cmp = icmp eq i32 undef, 0, !dbg !16
+ %conv = zext i1 %cmp to i32, !dbg !16
+ tail call void @llvm.dbg.value(metadata i32 %conv, metadata !11, metadata !DIExpression()), !dbg !17
+ %tobool = icmp eq i32 undef, 0, !dbg !18
+ br i1 %tobool, label %if.end, label %cleanup7.critedge, !dbg !21
+
+if.end: ; preds = %entry
+ %call6 = call i32 bitcast (i32 (...)* @j to i32 (i32)*)(i32 signext %conv)
+#4, !dbg !22
+ br label %cleanup7, !dbg !23
+
+cleanup7.critedge: ; preds = %entry
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull undef) #4, !dbg !24
+ br label %cleanup7
+
+cleanup7: ; preds = %cleanup7.critedge,
+ ret void
+}
+
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
+
+declare i32 @j(...)
+
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
+attributes #1 = { argmemonly nounwind }
+attributes #3 = { nounwind readnone speculatable }
+attributes #4 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang
+version 6.0.0", isOptimized: true, runtimeVersion:
+0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename:
+"/tmp//<stdin>", directory:
+"/tmp/")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 7, !"PIC Level", i32 2}
+!5 = distinct !DISubprogram(name: "f", scope: !6, file: !6, line: 8, type: !7,
+isLocal: false, isDefinition: true, scopeLine: 8, isOptimized: true, unit: !0,
+variables: !10)
+!6 = !DIFile(filename:
+"/tmp/test.c",
+directory: "/tmp")
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9}
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !{!11, !12, !14}
+!11 = !DILocalVariable(name: "e", scope: !5, file: !6, line: 9, type: !9)
+!12 = !DILocalVariable(name: "g", scope: !13, file: !6, line: 11, type: !9)
+!13 = distinct !DILexicalBlock(scope: !5, file: !6, line: 10, column: 3)
+!14 = !DILocalVariable(name: "d", scope: !13, file: !6, line: 12, type: !15)
+!15 = !DIDerivedType(tag: DW_TAG_typedef, name: "a", file: !6, line: 2,
+baseType: !9)
+!16 = !DILocation(line: 9, column: 15, scope: !5)
+!17 = !DILocation(line: 9, column: 7, scope: !5)
+!18 = !DILocation(line: 12, column: 5, scope: !19)
+!19 = distinct !DILexicalBlock(scope: !20, file: !6, line: 12, column: 5)
+!20 = distinct !DILexicalBlock(scope: !5, file: !6, line: 10, column: 3)
+!21 = !DILocation(line: 12, column: 5, scope: !20)
+!22 = !DILocation(line: 16, column: 3, scope: !5)
+!23 = !DILocation(line: 17, column: 1, scope: !5)
+!24 = !DILocation(line: 15, column: 3, scope: !5)