mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
ba7653634f
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 llvm-svn: 321382
94 lines
2.7 KiB
LLVM
94 lines
2.7 KiB
LLVM
; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
|
|
; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
|
|
;
|
|
; Ensures that volatile stores/loads count as MemoryDefs
|
|
|
|
; CHECK-LABEL: define i32 @foo
|
|
define i32 @foo() {
|
|
%1 = alloca i32, align 4
|
|
; CHECK: 1 = MemoryDef(liveOnEntry)
|
|
; CHECK-NEXT: store volatile i32 4
|
|
store volatile i32 4, i32* %1, align 4
|
|
; CHECK: 2 = MemoryDef(1)
|
|
; CHECK-NEXT: store volatile i32 8
|
|
store volatile i32 8, i32* %1, align 4
|
|
; CHECK: 3 = MemoryDef(2)
|
|
; CHECK-NEXT: %2 = load volatile i32
|
|
%2 = load volatile i32, i32* %1, align 4
|
|
; CHECK: 4 = MemoryDef(3)
|
|
; CHECK-NEXT: %3 = load volatile i32
|
|
%3 = load volatile i32, i32* %1, align 4
|
|
%4 = add i32 %3, %2
|
|
ret i32 %4
|
|
}
|
|
|
|
; Ensuring we allow hoisting nonvolatile loads around volatile loads.
|
|
; CHECK-LABEL define void @volatile_only
|
|
define void @volatile_only(i32* %arg1, i32* %arg2) {
|
|
; Trivially NoAlias/MustAlias
|
|
%a = alloca i32
|
|
%b = alloca i32
|
|
|
|
; CHECK: 1 = MemoryDef(liveOnEntry)
|
|
; CHECK-NEXT: load volatile i32, i32* %a
|
|
load volatile i32, i32* %a
|
|
; CHECK: MemoryUse(liveOnEntry)
|
|
; CHECK-NEXT: load i32, i32* %b
|
|
load i32, i32* %b
|
|
; CHECK: MemoryUse(liveOnEntry)
|
|
; CHECK-NEXT: load i32, i32* %a
|
|
load i32, i32* %a
|
|
|
|
; MayAlias
|
|
; CHECK: 2 = MemoryDef(1)
|
|
; CHECK-NEXT: load volatile i32, i32* %arg1
|
|
load volatile i32, i32* %arg1
|
|
; CHECK: MemoryUse(liveOnEntry)
|
|
; CHECK-NEXT: load i32, i32* %arg2
|
|
load i32, i32* %arg2
|
|
|
|
ret void
|
|
}
|
|
|
|
; Ensuring that volatile atomic operations work properly.
|
|
; CHECK-LABEL define void @volatile_atomics
|
|
define void @volatile_atomics(i32* %arg1, i32* %arg2) {
|
|
%a = alloca i32
|
|
%b = alloca i32
|
|
|
|
; Trivially NoAlias/MustAlias
|
|
|
|
; CHECK: 1 = MemoryDef(liveOnEntry)
|
|
; CHECK-NEXT: load atomic volatile i32, i32* %a acquire, align 4
|
|
load atomic volatile i32, i32* %a acquire, align 4
|
|
; CHECK: MemoryUse(1)
|
|
; CHECK-NEXT: load i32, i32* %b
|
|
load i32, i32* %b
|
|
|
|
; CHECK: 2 = MemoryDef(1)
|
|
; CHECK-NEXT: load atomic volatile i32, i32* %a monotonic, align 4
|
|
load atomic volatile i32, i32* %a monotonic, align 4
|
|
; CHECK: MemoryUse(1)
|
|
; CHECK-NEXT: load i32, i32* %b
|
|
load i32, i32* %b
|
|
; CHECK: MemoryUse(1)
|
|
; CHECK-NEXT: load atomic i32, i32* %b unordered, align 4
|
|
load atomic i32, i32* %b unordered, align 4
|
|
; CHECK: MemoryUse(1)
|
|
; CHECK-NEXT: load atomic i32, i32* %a unordered, align 4
|
|
load atomic i32, i32* %a unordered, align 4
|
|
; CHECK: MemoryUse(1)
|
|
; CHECK-NEXT: load i32, i32* %a
|
|
load i32, i32* %a
|
|
|
|
; MayAlias
|
|
; CHECK: 3 = MemoryDef(2)
|
|
; CHECK-NEXT: load atomic volatile i32, i32* %arg1 monotonic, align 4
|
|
load atomic volatile i32, i32* %arg1 monotonic, align 4
|
|
; CHECK: MemoryUse(1)
|
|
; CHECK-NEXT: load i32, i32* %arg2
|
|
load i32, i32* %arg2
|
|
|
|
ret void
|
|
}
|