llvm.org GIT mirror llvm / 9b917c5
[DSE] Avoid iterator invalidation bugs. The dse_with_dbg_value.ll test committed with r273141 is removed because this we no longer performs any type of back tracking, which is what was causing the codegen differences with and without debug information. Differential Revision: http://reviews.llvm.org/D21613 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@274660 91177308-0d34-0410-b5e6-96231b3b80d8 Chad Rosier 3 years ago
2 changed file(s) with 37 addition(s) and 126 deletion(s). Raw diff Collapse all Expand all
6464 /// the computation tree that feeds them.
6565 /// If ValueSet is non-null, remove any deleted instructions from it as well.
6666 static void
67 deleteDeadInstruction(Instruction *I, MemoryDependenceResults &MD,
68 const TargetLibraryInfo &TLI,
67 deleteDeadInstruction(Instruction *I, BasicBlock::iterator *BBI,
68 MemoryDependenceResults &MD, const TargetLibraryInfo &TLI,
6969 SmallSetVector *ValueSet = nullptr) {
7070 SmallVector NowDeadInsts;
7171
7272 NowDeadInsts.push_back(I);
7373 --NumFastOther;
74
75 // Keeping the iterator straight is a pain, so we let this routine tell the
76 // caller what the next instruction is after we're done mucking about.
77 BasicBlock::iterator NewIter = *BBI;
7478
7579 // Before we touch this instruction, remove it from memdep!
7680 do {
9498 NowDeadInsts.push_back(OpI);
9599 }
96100
97 DeadInst->eraseFromParent();
101
102 if (NewIter == DeadInst->getIterator())
103 NewIter = DeadInst->eraseFromParent();
104 else
105 DeadInst->eraseFromParent();
98106
99107 if (ValueSet) ValueSet->remove(DeadInst);
100108 } while (!NowDeadInsts.empty());
109 *BBI = NewIter;
101110 }
102111
103112 /// Does this instruction write some memory? This only returns true for things
602611 if (!AA->isMustAlias(F->getArgOperand(0), DepPointer))
603612 break;
604613
605 auto Next = ++Dependency->getIterator();
606
607614 // DCE instructions only used to calculate that store.
608 deleteDeadInstruction(Dependency, *MD, *TLI);
615 BasicBlock::iterator BBI(Dependency);
616 deleteDeadInstruction(Dependency, &BBI, *MD, *TLI);
609617 ++NumFastStores;
610618 MadeChange = true;
611619
614622 // s[0] = 0;
615623 // s[1] = 0; // This has just been deleted.
616624 // free(s);
617 Dep = MD->getPointerDependencyFrom(Loc, false, Next, BB);
625 Dep = MD->getPointerDependencyFrom(Loc, false, BBI, BB);
618626 }
619627
620628 if (Dep.isNonLocal())
706714 }
707715
708716 if (AllDead) {
709 Instruction *Dead = &*BBI++;
717 Instruction *Dead = &*BBI;
710718
711719 DEBUG(dbgs() << "DSE: Dead Store at End of Block:\n DEAD: "
712720 << *Dead << "\n Objects: ";
719727 dbgs() << '\n');
720728
721729 // DCE instructions only used to calculate that store.
722 deleteDeadInstruction(Dead, *MD, *TLI, &DeadStackObjects);
730 deleteDeadInstruction(Dead, &BBI, *MD, *TLI, &DeadStackObjects);
723731 ++NumFastStores;
724732 MadeChange = true;
725733 continue;
728736
729737 // Remove any dead non-memory-mutating instructions.
730738 if (isInstructionTriviallyDead(&*BBI, TLI)) {
731 Instruction *Inst = &*BBI++;
732 deleteDeadInstruction(Inst, *MD, *TLI, &DeadStackObjects);
739 deleteDeadInstruction(&*BBI, &BBI, *MD, *TLI, &DeadStackObjects);
733740 ++NumFastOther;
734741 MadeChange = true;
735742 continue;
814821
815822 // Do a top-down walk on the BB.
816823 for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ) {
824 // Handle 'free' calls specially.
825 if (CallInst *F = isFreeCall(&*BBI, TLI)) {
826 MadeChange |= handleFree(F, AA, MD, DT, TLI);
827 // Increment BBI after handleFree has potentially deleted instructions.
828 // This ensures we maintain a valid iterator.
829 ++BBI;
830 continue;
831 }
832
817833 Instruction *Inst = &*BBI++;
818
819 // Handle 'free' calls specially.
820 if (CallInst *F = isFreeCall(Inst, TLI)) {
821 MadeChange |= handleFree(F, AA, MD, DT, TLI);
822 continue;
823 }
824834
825835 // If we find something that writes memory, get its memory dependence.
826836 if (!hasMemoryWrite(Inst, *TLI))
829839 // If we're storing the same value back to a pointer that we just
830840 // loaded from, then the store can be removed.
831841 if (StoreInst *SI = dyn_cast(Inst)) {
832
833 auto RemoveDeadInstAndUpdateBBI = [&](Instruction *DeadInst) {
834 // deleteDeadInstruction can delete the current instruction. Save BBI
835 // in case we need it.
836 WeakVH NextInst(&*BBI);
837
838 deleteDeadInstruction(DeadInst, *MD, *TLI);
839
840 if (!NextInst) // Next instruction deleted.
841 BBI = BB.begin();
842 else if (BBI != BB.begin()) // Revisit this instruction if possible.
843 --BBI;
844 ++NumRedundantStores;
845 MadeChange = true;
846 };
847
848842 if (LoadInst *DepLoad = dyn_cast(SI->getValueOperand())) {
849843 if (SI->getPointerOperand() == DepLoad->getPointerOperand() &&
850844 isRemovable(SI) &&
853847 DEBUG(dbgs() << "DSE: Remove Store Of Load from same pointer:\n "
854848 << "LOAD: " << *DepLoad << "\n STORE: " << *SI << '\n');
855849
856 RemoveDeadInstAndUpdateBBI(SI);
850 deleteDeadInstruction(SI, &BBI, *MD, *TLI);
851 ++NumRedundantStores;
852 MadeChange = true;
857853 continue;
858854 }
859855 }
872868 << "DSE: Remove null store to the calloc'ed object:\n DEAD: "
873869 << *Inst << "\n OBJECT: " << *UnderlyingPointer << '\n');
874870
875 RemoveDeadInstAndUpdateBBI(SI);
871 deleteDeadInstruction(SI, &BBI, *MD, *TLI);
872 ++NumRedundantStores;
873 MadeChange = true;
876874 continue;
877875 }
878876 }
920918 << *DepWrite << "\n KILLER: " << *Inst << '\n');
921919
922920 // Delete the store and now-dead instructions that feed it.
923 deleteDeadInstruction(DepWrite, *MD, *TLI);
921 deleteDeadInstruction(DepWrite, &BBI, *MD, *TLI);
924922 ++NumFastStores;
925923 MadeChange = true;
926924
927 // deleteDeadInstruction can delete the current instruction in loop
928 // cases, reset BBI.
929 BBI = Inst->getIterator();
930 auto BBBegin = BB.begin();
931 while (BBI != BBBegin && isa(*(--BBI)))
932 ;
933 break;
925 // We erased DepWrite; start over.
926 InstDep = MD->getDependency(Inst);
927 continue;
934928 } else if ((OR == OverwriteEnd && isShortenableAtTheEnd(DepWrite)) ||
935929 ((OR == OverwriteBegin &&
936930 isShortenableAtTheBeginning(DepWrite)))) {
+0
-83
test/Transforms/DeadStoreElimination/dse_with_dbg_value.ll less more
None ; RUN: opt -basicaa -dse -S < %s | FileCheck %s
1 ; RUN: opt -strip-debug -basicaa -dse -S < %s | FileCheck %s
2
3 ; Test that stores are removed both with and without debug info.
4
5 ; CHECK-NOT: store i32 4, i32* @g_31, align 1
6 ; CHECK-NOT: %_tmp17.i.i = load i16, i16* %_tmp16.i.i, align 1
7 ; CHECK-NOT: store i16 %_tmp17.i.i, i16* @g_118, align 1
8 ; CHECK: store i32 0, i32* @g_31, align 1
9
10 @g_31 = global i32 0
11 @g_30 = global i16* null
12 @g_118 = global i16 0
13
14 define i16 @S0() !dbg !17 {
15 bb1:
16 store i32 4, i32* @g_31, align 1, !dbg !20
17 %_tmp16.i.i = load volatile i16*, i16** @g_30, align 1, !dbg !28
18 %_tmp17.i.i = load i16, i16* %_tmp16.i.i, align 1, !dbg !28
19 store i16 %_tmp17.i.i, i16* @g_118, align 1, !dbg !20
20 store i32 0, i32* @g_31, align 1, !dbg !31
21 tail call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !40, metadata !41), !dbg !42
22 store i16 0, i16* @g_118, align 1, !dbg !43
23 br label %bb2.i, !dbg !44
24
25 bb2.i:
26 br label %bb2.i, !dbg !44
27 }
28
29 ; Function Attrs: nounwind readnone
30 declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #0
31
32 attributes #0 = { nounwind readnone }
33
34 !llvm.dbg.cu = !{!0}
35 !llvm.module.flags = !{!14, !15}
36 !llvm.ident = !{!16}
37
38 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "FlexASIC FlexC Compiler v6.38 for FADER (LLVM)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !3)
39 !1 = !DIFile(filename: "csmith23219270180033.c", directory: "/local/repo/uabsson/llvm")
40 !2 = !{}
41 !3 = !{!4, !9, !13}
42 !4 = !DIGlobalVariable(name: "g_31", scope: null, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, variable: i32* @g_31)
43 !5 = !DIDerivedType(tag: DW_TAG_typedef, name: "int32_t", file: !6, line: 104, baseType: !7)
44 !6 = !DIFile(filename: "/local/repo/uabsson/llvm/sdk-bin/cosy/fader2_sdk/compiler/fader2_arch/fader2_2/include/stdint.h", directory: "/local/repo/uabsson/llvm")
45 !7 = !DIDerivedType(tag: DW_TAG_typedef, name: "__i32_t", file: !1, baseType: !8)
46 !8 = !DIBasicType(name: "signed long", size: 32, align: 16, encoding: DW_ATE_signed)
47 !9 = !DIGlobalVariable(name: "g_30", scope: null, file: !1, line: 4, type: !10, isLocal: false, isDefinition: true, variable: i16** @g_30)
48 !10 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !11)
49 !11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 16, align: 16)
50 !12 = !DIBasicType(name: "int", size: 16, align: 16, encoding: DW_ATE_signed)
51 !13 = !DIGlobalVariable(name: "g_118", scope: null, file: !1, line: 5, type: !12, isLocal: false, isDefinition: true, variable: i16* @g_118)
52 !14 = !{i32 2, !"Dwarf Version", i32 4}
53 !15 = !{i32 2, !"Debug Info Version", i32 3}
54 !16 = !{!"FlexASIC FlexC Compiler v6.38 for FADER (CoSy 6231.35) (LLVM)"}
55 !17 = distinct !DISubprogram(name: "S0", scope: !1, file: !1, line: 10, type: !18, isLocal: false, isDefinition: true, scopeLine: 10, isOptimized: false, unit: !0, variables: !2)
56 !18 = !DISubroutineType(types: !19)
57 !19 = !{!12}
58 !20 = !DILocation(line: 14, column: 3, scope: !21, inlinedAt: !27)
59 !21 = distinct !DISubprogram(name: "func_54", scope: !1, file: !1, line: 12, type: !22, isLocal: false, isDefinition: true, scopeLine: 12, isOptimized: false, unit: !0, variables: !2)
60 !22 = !DISubroutineType(types: !23)
61 !23 = !{!24, !12, !12}
62 !24 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint64_t", file: !6, line: 107, baseType: !25)
63 !25 = !DIDerivedType(tag: DW_TAG_typedef, name: "__u64_t", file: !1, baseType: !26)
64 !26 = !DIBasicType(name: "unsigned long long", size: 64, align: 16, encoding: DW_ATE_unsigned)
65 !27 = distinct !DILocation(line: 10, column: 8, scope: !17)
66 !28 = !DILocation(line: 8, column: 12, scope: !29, inlinedAt: !30)
67 !29 = distinct !DISubprogram(name: "func_9", scope: !1, file: !1, line: 8, type: !18, isLocal: false, isDefinition: true, scopeLine: 8, isOptimized: false, unit: !0, variables: !2)
68 !30 = distinct !DILocation(line: 14, column: 3, scope: !21, inlinedAt: !27)
69 !31 = !DILocation(line: 20, column: 8, scope: !32, inlinedAt: !39)
70 !32 = distinct !DISubprogram(name: "func_61", scope: !1, file: !1, line: 19, type: !33, isLocal: false, isDefinition: true, scopeLine: 19, isOptimized: false, unit: !0, variables: !2)
71 !33 = !DISubroutineType(types: !34)
72 !34 = !{!35, !36, !5, !35, !35}
73 !35 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 16, align: 16)
74 !36 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint32_t", file: !6, line: 105, baseType: !37)
75 !37 = !DIDerivedType(tag: DW_TAG_typedef, name: "__u32_t", file: !1, baseType: !38)
76 !38 = !DIBasicType(name: "unsigned long", size: 32, align: 16, encoding: DW_ATE_unsigned)
77 !39 = distinct !DILocation(line: 14, column: 3, scope: !21, inlinedAt: !27)
78 !40 = !DILocalVariable(name: "p_63", arg: 2, scope: !32, line: 19, type: !5)
79 !41 = !DIExpression()
80 !42 = !DILocation(line: 19, column: 41, scope: !32, inlinedAt: !39)
81 !43 = !DILocation(line: 15, column: 10, scope: !21, inlinedAt: !27)
82 !44 = !DILocation(line: 15, column: 20, scope: !21, inlinedAt: !27)