From 751f932d9a5f2bad69ed658ccf732023a0e4971a Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Fri, 6 May 2016 21:43:51 +0000 Subject: [PATCH] [GVN] PRE of unordered loads Again, fairly simple. Only change is ensuring that we actually copy the property of the load correctly. The aliasing legality constraints were already handled by the FRE patches. There's nothing special about unorder atomics from the perspective of the PRE algorithm itself. llvm-svn: 268804 --- lib/Transforms/Scalar/GVN.cpp | 12 ++-- test/Transforms/GVN/atomic.ll | 109 ++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 8 deletions(-) diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index 7e937bf954a..97ec1eab654 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/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/test/Transforms/GVN/atomic.ll b/test/Transforms/GVN/atomic.ll index f8a70140cc3..509acd613e9 100644 --- a/test/Transforms/GVN/atomic.ll +++ b/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 +} +