llvm.org GIT mirror llvm / a40db4f
[RS4GC] Revert optimization attempt due to memory corruption This change reverts "246133 [RewriteStatepointsForGC] Reduce the number of new instructions for base pointers" and a follow on bugfix 12575. As pointed out in pr25846, this code suffers from a memory corruption bug. Since I'm (empirically) not going to get back to this any time soon, simply reverting the problematic change is the right answer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@261565 91177308-0d34-0410-b5e6-96231b3b80d8 Philip Reames 3 years ago
6 changed file(s) with 44 addition(s) and 76 deletion(s). Raw diff Collapse all Expand all
1313
1414 #include "llvm/Pass.h"
1515 #include "llvm/Analysis/CFG.h"
16 #include "llvm/Analysis/InstructionSimplify.h"
1716 #include "llvm/Analysis/TargetTransformInfo.h"
1817 #include "llvm/ADT/SetOperations.h"
1918 #include "llvm/ADT/Statistic.h"
10241023
10251024 }
10261025
1027 // Now that we're done with the algorithm, see if we can optimize the
1028 // results slightly by reducing the number of new instructions needed.
1029 // Arguably, this should be integrated into the algorithm above, but
1030 // doing as a post process step is easier to reason about for the moment.
1031 DenseMap ReverseMap;
1032 SmallPtrSet NewInsts;
1033 SmallSetVector, 16> Worklist;
1034 // Note: We need to visit the states in a deterministic order. We uses the
1035 // Keys we sorted above for this purpose. Note that we are papering over a
1036 // bigger problem with the algorithm above - it's visit order is not
1037 // deterministic. A larger change is needed to fix this.
1038 for (auto Pair : States) {
1039 auto *BDV = Pair.first;
1040 auto State = Pair.second;
1041 Value *Base = State.getBase();
1042 assert(BDV && Base);
1043 assert(!isKnownBaseResult(BDV) && "why did it get added?");
1044 assert(isKnownBaseResult(Base) &&
1045 "must be something we 'know' is a base pointer");
1046 if (!State.isConflict())
1047 continue;
1048
1049 ReverseMap[Base] = BDV;
1050 if (auto *BaseI = dyn_cast(Base)) {
1051 NewInsts.insert(BaseI);
1052 Worklist.insert(BaseI);
1053 }
1054 }
1055 auto ReplaceBaseInstWith = [&](Value *BDV, Instruction *BaseI,
1056 Value *Replacement) {
1057 // Add users which are new instructions (excluding self references)
1058 for (User *U : BaseI->users())
1059 if (auto *UI = dyn_cast(U))
1060 if (NewInsts.count(UI) && UI != BaseI)
1061 Worklist.insert(UI);
1062 // Then do the actual replacement
1063 NewInsts.erase(BaseI);
1064 ReverseMap.erase(BaseI);
1065 BaseI->replaceAllUsesWith(Replacement);
1066 assert(States.count(BDV));
1067 assert(States[BDV].isConflict() && States[BDV].getBase() == BaseI);
1068 States[BDV] = BDVState(BDVState::Conflict, Replacement);
1069 BaseI->eraseFromParent();
1070 };
1071 const DataLayout &DL = cast(def)->getModule()->getDataLayout();
1072 while (!Worklist.empty()) {
1073 Instruction *BaseI = Worklist.pop_back_val();
1074 assert(NewInsts.count(BaseI));
1075 Value *Bdv = ReverseMap[BaseI];
1076 if (auto *BdvI = dyn_cast(Bdv))
1077 if (BaseI->isIdenticalTo(BdvI)) {
1078 DEBUG(dbgs() << "Identical Base: " << *BaseI << "\n");
1079 ReplaceBaseInstWith(Bdv, BaseI, Bdv);
1080 continue;
1081 }
1082 if (Value *V = SimplifyInstruction(BaseI, DL)) {
1083 DEBUG(dbgs() << "Base " << *BaseI << " simplified to " << *V << "\n");
1084 ReplaceBaseInstWith(Bdv, BaseI, V);
1085 continue;
1086 }
1087 }
1088
10891026 // Cache all of our results so we can cheaply reuse them
10901027 // NOTE: This is actually two caches: one of the base defining value
10911028 // relation and one of the base pointer relation! FIXME
10931030 auto *BDV = Pair.first;
10941031 Value *base = Pair.second.getBase();
10951032 assert(BDV && base);
1033 assert(!isKnownBaseResult(BDV) && "why did it get added?");
10961034
10971035 std::string fromstr = cache.count(BDV) ? cache[BDV]->getName() : "none";
10981036 DEBUG(dbgs() << "Updating base value cache"
11011039 << " to: " << base->getName() << "\n");
11021040
11031041 if (cache.count(BDV)) {
1042 assert(isKnownBaseResult(base) &&
1043 "must be something we 'know' is a base pointer");
11041044 // Once we transition from the BDV relation being store in the cache to
11051045 // the base relation being stored, it must be stable
11061046 assert((!isKnownBaseResult(cache[BDV]) || cache[BDV] == base) &&
0 ; RUN: opt < %s -rewrite-statepoints-for-gc -spp-print-base-pointers -S 2>&1 | FileCheck %s
11
2 ; CHECK: derived %obj_to_consume base %obj_to_consume
2 ; CHECK: derived %obj_to_consume base %obj_to_consume.base
33
44 declare void @foo()
55
8080 ; we'd have commoned these, but that's a missed optimization, not correctness.
8181 ; CHECK-DAG: [ [[DISCARD:%.*.base.relocated.casted]], %loop ]
8282 ; CHECK-NOT: extra.base
83 ; CHECK: next.base = select
8384 ; CHECK: next = select
8485 ; CHECK: extra2.base = select
8586 ; CHECK: extra2 = select
106107
107108 merge: ; preds = %taken, %entry
108109 ; CHECK-LABEL: merge:
109 ; CHECK-NEXT: %bdv = phi
110 ; CHECK-NEXT: phi
111 ; CHECK-NEXT: phi
110112 ; CHECK-NEXT: gc.statepoint
111113 %bdv = phi i64 addrspace(1)* [ %obj, %entry ], [ %obj2, %taken ]
112114 call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
123125
124126 merge: ; preds = %taken, %entry
125127 ; CHECK-LABEL: merge:
126 ; CHECK-NEXT: %bdv = phi
128 ; CHECK-NEXT: phi
127129 ; CHECK-NEXT: gc.statepoint
128130 %bdv = phi i64 addrspace(1)* [ %obj, %entry ], [ %obj, %taken ]
129131 call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
137139
138140 merge: ; preds = %merge, %entry
139141 ; CHECK-LABEL: merge:
140 ; CHECK-NEXT: %bdv = phi
142 ; CHECK-NEXT: phi
143 ; CHECK-NEXT: phi
141144 ; CHECK-NEXT: br i1
142145 %bdv = phi i64 addrspace(1)* [ %obj, %entry ], [ %obj2, %merge ]
143146 br i1 %cnd, label %merge, label %next
4444
4545 merge2: ; preds = %untaken2, %taken2
4646 ; CHECK-LABEL: merge2:
47 ; CHECK-NEXT: %obj = phi i64 addrspace(1)*
48 ; CHECK-NEXT: statepoint
47 ; CHECK: %obj.base = phi i64 addrspace(1)*
48 ; CHECK: %obj = phi i64 addrspace(1)*
49 ; CHECK: statepoint
4950 ; CHECK: gc.relocate
50 ; CHECK-DAG: ; (%obj, %obj)
51 ; CHECK-DAG: ; (%obj.base, %obj)
52 ; CHECK: gc.relocate
53 ; CHECK-DAG: ; (%obj.base, %obj.base)
5154 %obj = phi i64 addrspace(1)* [ %obj0, %taken2 ], [ %obj1, %untaken2 ]
5255 call void @do_safepoint() [ "deopt"() ]
5356 ret i64 addrspace(1)* %obj
5962 ; CHECK: extractelement
6063 ; CHECK: statepoint
6164 ; CHECK: gc.relocate
62 ; CHECK-DAG: (%obj, %obj)
65 ; CHECK-DAG: (%obj.base, %obj)
6366 entry:
6467 %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %ptr, i32 0
6568 %obj = extractelement <2 x i64 addrspace(1)*> %vec, i32 0
7174 ; CHECK-LABEL: test4
7275 ; CHECK: statepoint
7376 ; CHECK: gc.relocate
74 ; CHECK-DAG: ; (%ptr, %obj)
75 ; CHECK: gc.relocate
76 ; CHECK-DAG: ; (%ptr, %ptr)
77 ; CHECK-DAG: ; (%obj.base, %obj)
7778 ; When we can optimize an extractelement from a known
7879 ; index and avoid introducing new base pointer instructions
7980 entry:
9091 define void @test5(i1 %cnd, i64 addrspace(1)* %obj) gc "statepoint-example" {
9192 ; CHECK-LABEL: @test5
9293 ; CHECK: gc.relocate
93 ; CHECK-DAG: (%obj, %bdv)
94 ; CHECK-DAG: (%bdv.base, %bdv)
9495 ; When we fundementally have to duplicate
9596 entry:
9697 %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
7272 define <2 x i64 addrspace(1)*> @test5(i64 addrspace(1)* %p) gc "statepoint-example" {
7373 ; CHECK-LABEL: test5
7474 ; CHECK: insertelement
75 ; CHECK-NEXT: insertelement
7576 ; CHECK-NEXT: gc.statepoint
77 ; CHECK-NEXT: gc.relocate
78 ; CHECK-NEXT: bitcast
7679 ; CHECK-NEXT: gc.relocate
7780 ; CHECK-NEXT: bitcast
7881 ; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %vec.relocated.casted
99102 merge: ; preds = %untaken, %taken
100103 ; CHECK-LABEL: merge:
101104 ; CHECK-NEXT: = phi
105 ; CHECK-NEXT: = phi
102106 ; CHECK-NEXT: gc.statepoint
107 ; CHECK-NEXT: gc.relocate
108 ; CHECK-NEXT: bitcast
103109 ; CHECK-NEXT: gc.relocate
104110 ; CHECK-NEXT: bitcast
105111 ; CHECK-NEXT: ret <2 x i64 addrspace(1)*>
9797 define <2 x i64 addrspace(1)*> @test5(i64 addrspace(1)* %p) gc "statepoint-example" {
9898 ; CHECK-LABEL: test5
9999 ; CHECK: insertelement
100 ; CHECK-NEXT: insertelement
101 ; CHECK-NEXT: extractelement
102 ; CHECK-NEXT: extractelement
100103 ; CHECK-NEXT: extractelement
101104 ; CHECK-NEXT: extractelement
102105 ; CHECK-NEXT: gc.statepoint
104107 ; CHECK-NEXT: bitcast
105108 ; CHECK-NEXT: gc.relocate
106109 ; CHECK-NEXT: bitcast
110 ; CHECK-NEXT: gc.relocate
111 ; CHECK-NEXT: bitcast
112 ; CHECK-NEXT: gc.relocate
113 ; CHECK-NEXT: bitcast
107114 ; CHECK-NEXT: insertelement
108115 ; CHECK-NEXT: insertelement
109 ; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %7
116 ; CHECK-NEXT: insertelement
117 ; CHECK-NEXT: insertelement
118 ; CHECK-NEXT: ret <2 x i64 addrspace(1)*>
110119 ; A base vector from a load
111120 entry:
112121 %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %p, i32 0
130139 merge: ; preds = %untaken, %taken
131140 ; CHECK-LABEL: merge:
132141 ; CHECK-NEXT: = phi
142 ; CHECK-NEXT: = phi
143 ; CHECK-NEXT: extractelement
144 ; CHECK-NEXT: extractelement
133145 ; CHECK-NEXT: extractelement
134146 ; CHECK-NEXT: extractelement
135147 ; CHECK-NEXT: gc.statepoint
137149 ; CHECK-NEXT: bitcast
138150 ; CHECK-NEXT: gc.relocate
139151 ; CHECK-NEXT: bitcast
152 ; CHECK-NEXT: gc.relocate
153 ; CHECK-NEXT: bitcast
154 ; CHECK-NEXT: gc.relocate
155 ; CHECK-NEXT: bitcast
156 ; CHECK-NEXT: insertelement
157 ; CHECK-NEXT: insertelement
140158 ; CHECK-NEXT: insertelement
141159 ; CHECK-NEXT: insertelement
142160 ; CHECK-NEXT: ret <2 x i64 addrspace(1)*>