[GVNHoist] Preserve optimization hints which agree
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 21 Jul 2016 07:16:26 +0000 (07:16 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 21 Jul 2016 07:16:26 +0000 (07:16 +0000)
If we have optimization hints with agree with each other along different
paths, preserve them.

llvm-svn: 276248

llvm/lib/Transforms/Scalar/GVNHoist.cpp
llvm/test/Transforms/GVN/hoist-md.ll

index 9ca6ea0..cf2181b 100644 (file)
@@ -574,7 +574,8 @@ public:
     llvm_unreachable("Both I and J must be from same BB");
   }
 
-  bool makeOperandsAvailable(Instruction *Repl, BasicBlock *HoistPt) const {
+  bool makeOperandsAvailable(Instruction *Repl, BasicBlock *HoistPt,
+                             const SmallVecInsn &InstructionsToHoist) const {
     // Check whether the GEP of a ld/st can be synthesized at HoistPt.
     GetElementPtrInst *Gep = nullptr;
     Instruction *Val = nullptr;
@@ -606,7 +607,15 @@ public:
     // Conservatively discard any optimization hints, they may differ on the
     // other paths.
     ClonedGep->dropUnknownNonDebugMetadata();
-    ClonedGep->clearSubclassOptionalData();
+    for (const Instruction *OtherInst : InstructionsToHoist) {
+      const GetElementPtrInst *OtherGep;
+      if (auto *OtherLd = dyn_cast<LoadInst>(OtherInst))
+        OtherGep = cast<GetElementPtrInst>(OtherLd->getPointerOperand());
+      else
+        OtherGep = cast<GetElementPtrInst>(
+            cast<StoreInst>(OtherInst)->getPointerOperand());
+      ClonedGep->intersectOptionalDataWith(OtherGep);
+    }
     Repl->replaceUsesOfWith(Gep, ClonedGep);
 
     // Also copy Val.
@@ -616,6 +625,11 @@ public:
       // Conservatively discard any optimization hints, they may differ on the
       // other paths.
       ClonedVal->dropUnknownNonDebugMetadata();
+      for (const Instruction *OtherInst : InstructionsToHoist) {
+        const auto *OtherVal =
+            cast<Instruction>(cast<StoreInst>(OtherInst)->getValueOperand());
+        ClonedVal->intersectOptionalDataWith(OtherVal);
+      }
       ClonedVal->clearSubclassOptionalData();
       Repl->replaceUsesOfWith(Val, ClonedVal);
     }
@@ -652,7 +666,7 @@ public:
         // The order in which hoistings are done may influence the availability
         // of operands.
         if (!allOperandsAvailable(Repl, HoistPt) &&
-            !makeOperandsAvailable(Repl, HoistPt))
+            !makeOperandsAvailable(Repl, HoistPt, InstructionsToHoist))
           continue;
         Repl->moveBefore(HoistPt->getTerminator());
         // TBAA may differ on one of the other paths, we need to get rid of
index 14cc848..8661542 100644 (file)
@@ -21,6 +21,50 @@ if.end:                                           ; preds = %if.else, %if.then
 ; CHECK: store i32 2, i32* %x, align 4
 ; CHECK-NEXT: br i1 %b
 
+define void @test2(i1 %b, i32* %x) {
+entry:
+  br i1 %b, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %gep1 = getelementptr inbounds i32, i32* %x, i64 1
+  store i32 2, i32* %gep1, align 4, !tbaa !1
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %gep2 = getelementptr inbounds i32, i32* %x, i64 1
+  store i32 2, i32* %gep2, align 4, !tbaa !5
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  ret void
+}
+; CHECK-LABEL: define void @test2(
+; CHECK: %[[gep:.*]] = getelementptr inbounds i32, i32* %x, i64 1
+; CHECK: store i32 2, i32* %[[gep]], align 4
+; CHECK-NEXT: br i1 %b
+
+define void @test3(i1 %b, i32* %x) {
+entry:
+  br i1 %b, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %gep1 = getelementptr inbounds i32, i32* %x, i64 1
+  store i32 2, i32* %gep1, align 4, !tbaa !1
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %gep2 = getelementptr i32, i32* %x, i64 1
+  store i32 2, i32* %gep2, align 4, !tbaa !5
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  ret void
+}
+; CHECK-LABEL: define void @test3(
+; CHECK: %[[gep:.*]] = getelementptr i32, i32* %x, i64 1
+; CHECK: store i32 2, i32* %[[gep]], align 4
+; CHECK-NEXT: br i1 %b
+
 !1 = !{!2, !2, i64 0}
 !2 = !{!"int", !3, i64 0}
 !3 = !{!"omnipotent char", !4, i64 0}