llvm.org GIT mirror llvm / d14c0e6
[MemorySSA] Allow reordering of loads that alias in the presence of volatile loads. Summary: Make MemorySSA allow reordering of two loads that may alias, when one is volatile. This makes MemorySSA less conservative and behaving the same as the AliasSetTracker. For more context, see D16875. LLVM language reference: "The optimizers must not change the number of volatile operations or change their order of execution relative to other volatile operations. The optimizers may change the order of volatile operations relative to non-volatile operations. This is not Java’s “volatile” and has no cross-thread synchronization behavior." Reviewers: george.burgess.iv, dberlin Subscribers: sanjoy, reames, hfinkel, llvm-commits, Prazek Differential Revision: https://reviews.llvm.org/D41525 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@321382 91177308-0d34-0410-b5e6-96231b3b80d8 Alina Sbirlea 2 years ago
2 changed file(s) with 16 addition(s) and 36 deletion(s). Raw diff Collapse all Expand all
191191 }
192192 };
193193
194 enum class Reorderability { Always, IfNoAlias, Never };
195
196194 } // end namespace llvm
197195
198196 /// This does one-way checks to see if Use could theoretically be hoisted above
201199 /// This assumes that, for the purposes of MemorySSA, Use comes directly after
202200 /// MayClobber, with no potentially clobbering operations in between them.
203201 /// (Where potentially clobbering ops are memory barriers, aliased stores, etc.)
204 static Reorderability getLoadReorderability(const LoadInst *Use,
205 const LoadInst *MayClobber) {
202 static bool areLoadsReorderable(const LoadInst *Use,
203 const LoadInst *MayClobber) {
206204 bool VolatileUse = Use->isVolatile();
207205 bool VolatileClobber = MayClobber->isVolatile();
208206 // Volatile operations may never be reordered with other volatile operations.
209207 if (VolatileUse && VolatileClobber)
210 return Reorderability::Never;
211
212 // The lang ref allows reordering of volatile and non-volatile operations.
213 // Whether an aliasing nonvolatile load and volatile load can be reordered,
214 // though, is ambiguous. Because it may not be best to exploit this ambiguity,
215 // we only allow volatile/non-volatile reordering if the volatile and
216 // non-volatile operations don't alias.
217 Reorderability Result = VolatileUse || VolatileClobber
218 ? Reorderability::IfNoAlias
219 : Reorderability::Always;
208 return false;
209 // Otherwise, volatile doesn't matter here. From the language reference:
210 // 'optimizers may change the order of volatile operations relative to
211 // non-volatile operations.'"
220212
221213 // If a load is seq_cst, it cannot be moved above other loads. If its ordering
222214 // is weaker, it can be moved above other loads. We just need to be sure that
228220 bool SeqCstUse = Use->getOrdering() == AtomicOrdering::SequentiallyConsistent;
229221 bool MayClobberIsAcquire = isAtLeastOrStrongerThan(MayClobber->getOrdering(),
230222 AtomicOrdering::Acquire);
231 if (SeqCstUse || MayClobberIsAcquire)
232 return Reorderability::Never;
233 return Result;
223 return !(SeqCstUse || MayClobberIsAcquire);
234224 }
235225
236226 static bool instructionClobbersQuery(MemoryDef *MD,
264254 return isModOrRefSet(I);
265255 }
266256
267 if (auto *DefLoad = dyn_cast(DefInst)) {
268 if (auto *UseLoad = dyn_cast(UseInst)) {
269 switch (getLoadReorderability(UseLoad, DefLoad)) {
270 case Reorderability::Always:
271 return false;
272 case Reorderability::Never:
273 return true;
274 case Reorderability::IfNoAlias:
275 return !AA.isNoAlias(UseLoc, MemoryLocation::get(DefLoad));
276 }
277 }
278 }
257 if (auto *DefLoad = dyn_cast(DefInst))
258 if (auto *UseLoad = dyn_cast(UseInst))
259 return !areLoadsReorderable(UseLoad, DefLoad);
279260
280261 return isModSet(AA.getModRefInfo(DefInst, UseLoc));
281262 }
2121 ret i32 %4
2222 }
2323
24 ; Ensuring that we don't automatically hoist nonvolatile loads around volatile
25 ; loads
24 ; Ensuring we allow hoisting nonvolatile loads around volatile loads.
2625 ; CHECK-LABEL define void @volatile_only
2726 define void @volatile_only(i32* %arg1, i32* %arg2) {
2827 ; Trivially NoAlias/MustAlias
3534 ; CHECK: MemoryUse(liveOnEntry)
3635 ; CHECK-NEXT: load i32, i32* %b
3736 load i32, i32* %b
38 ; CHECK: MemoryUse(1)
37 ; CHECK: MemoryUse(liveOnEntry)
3938 ; CHECK-NEXT: load i32, i32* %a
4039 load i32, i32* %a
4140
4342 ; CHECK: 2 = MemoryDef(1)
4443 ; CHECK-NEXT: load volatile i32, i32* %arg1
4544 load volatile i32, i32* %arg1
46 ; CHECK: MemoryUse(2)
45 ; CHECK: MemoryUse(liveOnEntry)
4746 ; CHECK-NEXT: load i32, i32* %arg2
4847 load i32, i32* %arg2
4948
7473 ; CHECK: MemoryUse(1)
7574 ; CHECK-NEXT: load atomic i32, i32* %b unordered, align 4
7675 load atomic i32, i32* %b unordered, align 4
77 ; CHECK: MemoryUse(2)
76 ; CHECK: MemoryUse(1)
7877 ; CHECK-NEXT: load atomic i32, i32* %a unordered, align 4
7978 load atomic i32, i32* %a unordered, align 4
80 ; CHECK: MemoryUse(2)
79 ; CHECK: MemoryUse(1)
8180 ; CHECK-NEXT: load i32, i32* %a
8281 load i32, i32* %a
8382
8584 ; CHECK: 3 = MemoryDef(2)
8685 ; CHECK-NEXT: load atomic volatile i32, i32* %arg1 monotonic, align 4
8786 load atomic volatile i32, i32* %arg1 monotonic, align 4
88 ; CHECK: MemoryUse(3)
87 ; CHECK: MemoryUse(1)
8988 ; CHECK-NEXT: load i32, i32* %arg2
9089 load i32, i32* %arg2
9190