]> granicus.if.org Git - llvm/commitdiff
[GVN] PRE of unordered loads
authorPhilip Reames <listmail@philipreames.com>
Fri, 6 May 2016 21:43:51 +0000 (21:43 +0000)
committerPhilip Reames <listmail@philipreames.com>
Fri, 6 May 2016 21:43:51 +0000 (21:43 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@268804 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/GVN.cpp
test/Transforms/GVN/atomic.ll

index 7e937bf954a7e22973e2f4887b7bf7eb2145e2c4..97ec1eab65426a14bc3057858abe0a347c307e2d 100644 (file)
@@ -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;
index f8a70140cc3cd4ae682057ebd0af12a2b63784bf..509acd613e955b50ee0d3052b711f78b0d6d9f88 100644 (file)
@@ -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
+}
+