summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Analysis/Loads.cpp20
-rw-r--r--llvm/test/Transforms/InstCombine/atomic.ll48
2 files changed, 67 insertions, 1 deletions
diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp
index 21503ef668b..c5d23136733 100644
--- a/llvm/lib/Analysis/Loads.cpp
+++ b/llvm/lib/Analysis/Loads.cpp
@@ -416,6 +416,14 @@ Value *llvm::FindAvailableLoadedValue(LoadInst *Load, BasicBlock *ScanBB,
Value *Ptr = Load->getPointerOperand();
Type *AccessTy = Load->getType();
+ // We can never remove a volatile load
+ if (Load->isVolatile())
+ return nullptr;
+
+ // Anything stronger than unordered is currently unimplemented.
+ if (!Load->isUnordered())
+ return nullptr;
+
const DataLayout &DL = ScanBB->getModule()->getDataLayout();
// Try to get the store size for the type.
@@ -445,6 +453,12 @@ Value *llvm::FindAvailableLoadedValue(LoadInst *Load, BasicBlock *ScanBB,
if (AreEquivalentAddressValues(
LI->getPointerOperand()->stripPointerCasts(), StrippedPtr) &&
CastInst::isBitOrNoopPointerCastable(LI->getType(), AccessTy, DL)) {
+
+ // We can value forward from an atomic to a non-atomic, but not the
+ // other way around.
+ if (LI->isAtomic() < Load->isAtomic())
+ return nullptr;
+
if (AATags)
LI->getAAMetadata(*AATags);
return LI;
@@ -458,6 +472,12 @@ Value *llvm::FindAvailableLoadedValue(LoadInst *Load, BasicBlock *ScanBB,
if (AreEquivalentAddressValues(StorePtr, StrippedPtr) &&
CastInst::isBitOrNoopPointerCastable(SI->getValueOperand()->getType(),
AccessTy, DL)) {
+
+ // We can value forward from an atomic to a non-atomic, but not the
+ // other way around.
+ if (SI->isAtomic() < Load->isAtomic())
+ return nullptr;
+
if (AATags)
SI->getAAMetadata(*AATags);
return SI->getOperand(0);
diff --git a/llvm/test/Transforms/InstCombine/atomic.ll b/llvm/test/Transforms/InstCombine/atomic.ll
index 5754a5a4ba5..bf576ba4b3a 100644
--- a/llvm/test/Transforms/InstCombine/atomic.ll
+++ b/llvm/test/Transforms/InstCombine/atomic.ll
@@ -5,12 +5,58 @@ target triple = "x86_64-apple-macosx10.7.0"
; Check transforms involving atomic operations
+define i32 @test1(i32* %p) {
+; CHECK-LABEL: define i32 @test1(
+; CHECK: %x = load atomic i32, i32* %p seq_cst, align 4
+; CHECK: shl i32 %x, 1
+ %x = load atomic i32, i32* %p seq_cst, align 4
+ %y = load i32, i32* %p, align 4
+ %z = add i32 %x, %y
+ ret i32 %z
+}
+
define i32 @test2(i32* %p) {
; CHECK-LABEL: define i32 @test2(
+; CHECK: %x = load volatile i32, i32* %p, align 4
+; CHECK: %y = load volatile i32, i32* %p, align 4
+ %x = load volatile i32, i32* %p, align 4
+ %y = load volatile i32, i32* %p, align 4
+ %z = add i32 %x, %y
+ ret i32 %z
+}
+
+; The exact semantics of mixing volatile and non-volatile on the same
+; memory location are a bit unclear, but conservatively, we know we don't
+; want to remove the volatile.
+define i32 @test3(i32* %p) {
+; CHECK-LABEL: define i32 @test3(
+; CHECK: %x = load volatile i32, i32* %p, align 4
+ %x = load volatile i32, i32* %p, align 4
+ %y = load i32, i32* %p, align 4
+ %z = add i32 %x, %y
+ ret i32 %z
+}
+
+; FIXME: Forwarding from a stronger atomic is fine
+define i32 @test4(i32* %p) {
+; CHECK-LABEL: define i32 @test4(
; CHECK: %x = load atomic i32, i32* %p seq_cst, align 4
-; CHECK: shl i32 %x, 1
+; CHECK: %y = load atomic i32, i32* %p unordered, align 4
%x = load atomic i32, i32* %p seq_cst, align 4
+ %y = load atomic i32, i32* %p unordered, align 4
+ %z = add i32 %x, %y
+ ret i32 %z
+}
+
+; Forwarding from a non-atomic is not. (The earlier load
+; could in priciple be promoted to atomic and then forwarded,
+; but we can't just drop the atomic from the load.)
+define i32 @test5(i32* %p) {
+; CHECK-LABEL: define i32 @test5(
+; CHECK: %x = load atomic i32, i32* %p unordered, align 4
+ %x = load atomic i32, i32* %p unordered, align 4
%y = load i32, i32* %p, align 4
%z = add i32 %x, %y
ret i32 %z
}
+
OpenPOWER on IntegriCloud