diff options
-rw-r--r-- | llvm/lib/Transforms/Scalar/GVN.cpp | 12 | ||||
-rw-r--r-- | llvm/test/Transforms/GVN/atomic.ll | 109 |
2 files changed, 113 insertions, 8 deletions
diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index 7e937bf954a..97ec1eab654 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -1552,9 +1552,10 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock, BasicBlock *UnavailablePred = PredLoad.first; Value *LoadPtr = PredLoad.second; - Instruction *NewLoad = new LoadInst(LoadPtr, LI->getName()+".pre", false, - LI->getAlignment(), - UnavailablePred->getTerminator()); + auto *NewLoad = new LoadInst(LoadPtr, LI->getName()+".pre", + LI->isVolatile(), LI->getAlignment(), + LI->getOrdering(), LI->getSynchScope(), + UnavailablePred->getTerminator()); // Transfer the old load's AA tags to the new load. AAMDNodes Tags; @@ -1664,11 +1665,6 @@ bool GVN::processNonLocalLoad(LoadInst *LI) { return true; } - // This code hasn't been audited for atomic, ordered, or volatile memory - // access. - if (!LI->isSimple()) - return false; - // Step 4: Eliminate partial redundancy. if (!EnablePRE || !EnableLoadPRE) return false; diff --git a/llvm/test/Transforms/GVN/atomic.ll b/llvm/test/Transforms/GVN/atomic.ll index f8a70140cc3..509acd613e9 100644 --- a/llvm/test/Transforms/GVN/atomic.ll +++ b/llvm/test/Transforms/GVN/atomic.ll @@ -392,3 +392,112 @@ next: %res = sub i32 %a, %b ret i32 %res } + +declare void @clobber() + +; unordered atomic to unordered atomic +define i32 @non_local_pre(i32* %P1) { +; CHECK-LABEL: @non_local_pre( +; CHECK: load atomic i32, i32* %P1 unordered +; CHECK: load atomic i32, i32* %P1 unordered +; CHECK: %b = phi i32 [ %b.pre, %early ], [ %a, %0 ] +; CHECK: ret i32 %b + %a = load atomic i32, i32* %P1 unordered, align 4 + %cmp = icmp eq i32 %a, 0 + br i1 %cmp, label %early, label %next +early: + call void @clobber() + br label %next +next: + %b = load atomic i32, i32* %P1 unordered, align 4 + ret i32 %b +} + +; unordered atomic to non-atomic +define i32 @non_local_pre2(i32* %P1) { +; CHECK-LABEL: @non_local_pre2( +; CHECK: load atomic i32, i32* %P1 unordered +; CHECK: load i32, i32* %P1 +; CHECK: %b = phi i32 [ %b.pre, %early ], [ %a, %0 ] +; CHECK: ret i32 %b + %a = load atomic i32, i32* %P1 unordered, align 4 + %cmp = icmp eq i32 %a, 0 + br i1 %cmp, label %early, label %next +early: + call void @clobber() + br label %next +next: + %b = load i32, i32* %P1 + ret i32 %b +} + +; non-atomic to unordered atomic - can't forward! +define i32 @non_local_pre3(i32* %P1) { +; CHECK-LABEL: @non_local_pre3( +; CHECK: %a = load i32, i32* %P1 +; CHECK: %b = load atomic i32, i32* %P1 unordered +; CHECK: ret i32 %b + %a = load i32, i32* %P1 + %cmp = icmp eq i32 %a, 0 + br i1 %cmp, label %early, label %next +early: + call void @clobber() + br label %next +next: + %b = load atomic i32, i32* %P1 unordered, align 4 + ret i32 %b +} + +; ordered atomic to ordered atomic - can't forward +define i32 @non_local_pre4(i32* %P1) { +; CHECK-LABEL: @non_local_pre4( +; CHECK: %a = load atomic i32, i32* %P1 seq_cst +; CHECK: %b = load atomic i32, i32* %P1 seq_cst +; CHECK: ret i32 %b + %a = load atomic i32, i32* %P1 seq_cst, align 4 + %cmp = icmp eq i32 %a, 0 + br i1 %cmp, label %early, label %next +early: + call void @clobber() + br label %next +next: + %b = load atomic i32, i32* %P1 seq_cst, align 4 + ret i32 %b +} + +; can't remove volatile on any path +define i32 @non_local_pre5(i32* %P1) { +; CHECK-LABEL: @non_local_pre5( +; CHECK: %a = load atomic i32, i32* %P1 seq_cst +; CHECK: %b = load volatile i32, i32* %P1 +; CHECK: ret i32 %b + %a = load atomic i32, i32* %P1 seq_cst, align 4 + %cmp = icmp eq i32 %a, 0 + br i1 %cmp, label %early, label %next +early: + call void @clobber() + br label %next +next: + %b = load volatile i32, i32* %P1 + ret i32 %b +} + + +; ordered atomic to unordered atomic +define i32 @non_local_pre6(i32* %P1) { +; CHECK-LABEL: @non_local_pre6( +; CHECK: load atomic i32, i32* %P1 seq_cst +; CHECK: load atomic i32, i32* %P1 unordered +; CHECK: %b = phi i32 [ %b.pre, %early ], [ %a, %0 ] +; CHECK: ret i32 %b + %a = load atomic i32, i32* %P1 seq_cst, align 4 + %cmp = icmp eq i32 %a, 0 + br i1 %cmp, label %early, label %next +early: + call void @clobber() + br label %next +next: + %b = load atomic i32, i32* %P1 unordered, align 4 + ret i32 %b +} + |