[GVN] Remove stale entries in phitranslate cache when new phi is generated for PRE
authorWei Mi <wmi@google.com>
Tue, 8 Aug 2017 21:40:14 +0000 (21:40 +0000)
committerWei Mi <wmi@google.com>
Tue, 8 Aug 2017 21:40:14 +0000 (21:40 +0000)
When a new phi is generated for scalarpre of an expression, the phiTranslate cache
will become stale: Before PRE, the candidate expression must not be available in a
predecessor block, and phitranslate will cache the information. After PRE, the
expression will become available in all predecessor blocks, so the related entries
in phiTranslate cache becomes stale. The patch will simply remove the stale entries
so phiTranslate can be recomputed next time.

The stale entries in phitranslate cache will not affect correctness but will cause
missing PRE opportunity for later instructions.

Differential Revision: https://reviews.llvm.org/D36124

llvm-svn: 310421

llvm/include/llvm/Transforms/Scalar/GVN.h
llvm/lib/Transforms/Scalar/GVN.cpp
llvm/test/Transforms/GVN/PRE/phi-translate-2.ll

index 4c585a2..e5ab6e0 100644 (file)
@@ -111,6 +111,7 @@ public:
                             Value *LHS, Value *RHS);
     uint32_t phiTranslate(const BasicBlock *BB, const BasicBlock *PhiBlock,
                           uint32_t Num, GVN &Gvn);
+    void eraseTranslateCacheEntry(uint32_t Num, const BasicBlock &CurrBlock);
     bool exists(Value *V) const;
     void add(Value *V, uint32_t num);
     void clear();
index d95fa57..5446f60 100644 (file)
@@ -1558,6 +1558,17 @@ uint32_t GVN::ValueTable::phiTranslateImpl(const BasicBlock *Pred,
   return Num;
 }
 
+/// Erase stale entry from phiTranslate cache so phiTranslate can be computed
+/// again.
+void GVN::ValueTable::eraseTranslateCacheEntry(uint32_t Num,
+                                               const BasicBlock &CurrBlock) {
+  for (const BasicBlock *Pred : predecessors(&CurrBlock)) {
+    auto FindRes = PhiTranslateTable.find({Num, Pred});
+    if (FindRes != PhiTranslateTable.end())
+      PhiTranslateTable.erase(FindRes);
+  }
+}
+
 // In order to find a leader for a given value number at a
 // specific basic block, we first obtain the list of all Values for that number,
 // and then scan the list to find one whose block dominates the block in
@@ -2210,6 +2221,9 @@ bool GVN::performScalarPRE(Instruction *CurInst) {
   }
 
   VN.add(Phi, ValNo);
+  // After creating a new PHI for ValNo, the phi translate result for ValNo will
+  // be changed, so erase the related stale entries in phi translate cache.
+  VN.eraseTranslateCacheEntry(ValNo, *CurrentBlock);
   addToLeaderTable(ValNo, Phi, CurrentBlock);
   Phi->setDebugLoc(CurInst->getDebugLoc());
   CurInst->replaceAllUsesWith(Phi);
index 78681e2..8920db9 100644 (file)
@@ -129,3 +129,48 @@ bb343:
 critedge.loopexit:
   unreachable
 }
+
+; Check sub expression will be pre transformed.
+; CHECK-LABEL: @test5(
+; CHECK: entry:
+; CHECK: %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
+; CHECK: br i1 %cmp
+; CHECK: if.then2:
+; CHECK: %[[PTRTOINT:.*]] = ptrtoint i32* %add.ptr to i64
+; CHECK: %[[SUB:.*]] = sub i64 %sub.ptr.lhs.cast, %[[PTRTOINT]]
+; CHECK: br label %if.end3
+; CHECK: if.end3:
+; CHECK: %[[PREPHI:.*]] = phi i64 [ %sub.ptr.sub, %if.else ], [ %[[SUB]], %if.then2 ], [ %sub.ptr.sub, %entry ]
+; CHECK: %[[DIV:.*]] = ashr exact i64 %[[PREPHI]], 2
+; CHECK: ret i64 %[[DIV]]
+
+declare void @bar(...) local_unnamed_addr #1
+
+; Function Attrs: nounwind uwtable
+define i64 @test5(i32* %start, i32* %e, i32 %n1, i32 %n2) local_unnamed_addr #0 {
+entry:
+  %sub.ptr.lhs.cast = ptrtoint i32* %e to i64
+  %sub.ptr.rhs.cast = ptrtoint i32* %start to i64
+  %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
+  %cmp = icmp sgt i64 %sub.ptr.sub, 4000
+  br i1 %cmp, label %if.then, label %if.end3
+
+if.then:                                          ; preds = %entry
+  %cmp1 = icmp sgt i32 %n1, %n2
+  br i1 %cmp1, label %if.then2, label %if.else
+
+if.then2:                                         ; preds = %if.then
+  %add.ptr = getelementptr inbounds i32, i32* %start, i64 800
+  br label %if.end3
+
+if.else:                                          ; preds = %if.then
+  tail call void (...) @bar() #2
+  br label %if.end3
+
+if.end3:                                          ; preds = %if.then2, %if.else, %entry
+  %p.0 = phi i32* [ %add.ptr, %if.then2 ], [ %start, %if.else ], [ %start, %entry ]
+  %sub.ptr.rhs.cast5 = ptrtoint i32* %p.0 to i64
+  %sub.ptr.sub6 = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast5
+  %sub.ptr.div7 = ashr exact i64 %sub.ptr.sub6, 2
+  ret i64 %sub.ptr.div7
+}