<div dir="ltr">Hi Wei,<div><br></div><div>I believe that this change caused this bot failure:</div><div><a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/1428/steps/check-llvm%20msan/logs/stdio">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/1428/steps/check-llvm%20msan/logs/stdio</a><br></div><div>Can you please take a look?</div><div><br></div><div>Thanks,</div><div>Peter</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, May 26, 2017 at 5:54 PM, Wei Mi via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: wmi<br>
Date: Fri May 26 19:54:19 2017<br>
New Revision: 304050<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=304050&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=304050&view=rev</a><br>
Log:<br>
[GVN] Recommit the patch "Add phi-translate support in scalarpre".<br>
<br>
The recommit is to fix a bug about ExtractValue and InsertValue ops. For those<br>
ops, some varargs inside GVN::Expression are not value numbers but raw index<br>
numbers. It is wrong to do phi-translate for raw index numbers, and the fix is<br>
to stop doing that.<br>
<br>
Right now scalarpre doesn't have phi-translate support, so it will miss some<br>
simple pre opportunities. Like the following testcase, current scalarpre cannot<br>
recognize the last "a * b" is fully redundent because a and b used by the last<br>
"a * b" expr are both defined by phis.<br>
<br>
long a[100], b[100], g1, g2, g3;<br>
__attribute__((pure)) long goo();<br>
<br>
void foo(long a, long b, long c, long d) {<br>
  g1 = a * b;<br>
  if (__builtin_expect(g2 > 3, 0)) {<br>
    a = c;<br>
    b = d;<br>
    g2 = a * b;<br>
  }<br>
  g3 = a * b;      // fully redundant.<br>
}<br>
The patch adds phi-translate support in scalarpre. This is only a temporary<br>
solution before the newpre based on newgvn is available.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D32252" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D32252</a><br>
<br>
Added:<br>
    llvm/trunk/test/Transforms/<wbr>GVN/PRE/phi-translate-2.ll<br>
Modified:<br>
    llvm/trunk/include/llvm/<wbr>Transforms/Scalar/GVN.h<br>
    llvm/trunk/lib/Transforms/<wbr>Scalar/GVN.cpp<br>
    llvm/trunk/test/Transforms/<wbr>GVN/PRE/pre-gep-load.ll<br>
    llvm/trunk/test/Transforms/<wbr>GVN/PRE/pre-load.ll<br>
<br>
Modified: llvm/trunk/include/llvm/<wbr>Transforms/Scalar/GVN.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar/GVN.h?rev=304050&r1=304049&r2=304050&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/include/<wbr>llvm/Transforms/Scalar/GVN.h?<wbr>rev=304050&r1=304049&r2=<wbr>304050&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/<wbr>Transforms/Scalar/GVN.h (original)<br>
+++ llvm/trunk/include/llvm/<wbr>Transforms/Scalar/GVN.h Fri May 26 19:54:19 2017<br>
@@ -68,6 +68,24 @@ public:<br>
   class ValueTable {<br>
     DenseMap<Value *, uint32_t> valueNumbering;<br>
     DenseMap<Expression, uint32_t> expressionNumbering;<br>
+<br>
+    // Expressions is the vector of Expression. ExprIdx is the mapping from<br>
+    // value number to the index of Expression in Expressions. We use it<br>
+    // instead of a DenseMap because filling such mapping is faster than<br>
+    // filling a DenseMap and the compile time is a little better.<br>
+    uint32_t nextExprNumber;<br>
+    std::vector<Expression> Expressions;<br>
+    std::vector<uint32_t> ExprIdx;<br>
+    // Value number to PHINode mapping. Used for phi-translate in scalarpre.<br>
+    DenseMap<uint32_t, PHINode *> NumberingPhi;<br>
+    // Cache for phi-translate in scalarpre.<br>
+    typedef DenseMap<std::pair<uint32_t, const BasicBlock *>, uint32_t><br>
+        PhiTranslateMap;<br>
+    PhiTranslateMap PhiTranslateTable;<br>
+    // Map the block to reversed postorder traversal number. It is used to<br>
+    // find back edge easily.<br>
+    DenseMap<const BasicBlock *, uint32_t> BlockRPONumber;<br>
+<br>
     AliasAnalysis *AA;<br>
     MemoryDependenceResults *MD;<br>
     DominatorTree *DT;<br>
@@ -79,6 +97,10 @@ public:<br>
                              Value *LHS, Value *RHS);<br>
     Expression createExtractvalueExpr(<wbr>ExtractValueInst *EI);<br>
     uint32_t lookupOrAddCall(CallInst *C);<br>
+    uint32_t phiTranslateImpl(const BasicBlock *BB, const BasicBlock *PhiBlock,<br>
+                              uint32_t Num, GVN &Gvn);<br>
+    std::pair<uint32_t, bool> assignExpNewValueNum(<wbr>Expression &exp);<br>
+    bool areAllValsInBB(uint32_t num, const BasicBlock *BB, GVN &Gvn);<br>
<br>
   public:<br>
     ValueTable();<br>
@@ -87,9 +109,12 @@ public:<br>
     ~ValueTable();<br>
<br>
     uint32_t lookupOrAdd(Value *V);<br>
-    uint32_t lookup(Value *V) const;<br>
+    uint32_t lookup(Value *V, bool Verify = true) const;<br>
     uint32_t lookupOrAddCmp(unsigned Opcode, CmpInst::Predicate Pred,<br>
                             Value *LHS, Value *RHS);<br>
+    uint32_t phiTranslate(const BasicBlock *BB, const BasicBlock *PhiBlock,<br>
+                          uint32_t Num, GVN &Gvn);<br>
+    void assignBlockRPONumber(Function &F);<br>
     bool exists(Value *V) const;<br>
     void add(Value *V, uint32_t num);<br>
     void clear();<br>
<br>
Modified: llvm/trunk/lib/Transforms/<wbr>Scalar/GVN.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=304050&r1=304049&r2=304050&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>Transforms/Scalar/GVN.cpp?rev=<wbr>304050&r1=304049&r2=304050&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/<wbr>Scalar/GVN.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/<wbr>Scalar/GVN.cpp Fri May 26 19:54:19 2017<br>
@@ -80,9 +80,10 @@ MaxRecurseDepth("max-recurse-<wbr>depth", cl:<br>
 struct llvm::GVN::Expression {<br>
   uint32_t opcode;<br>
   Type *type;<br>
+  bool commutative;<br>
   SmallVector<uint32_t, 4> varargs;<br>
<br>
-  Expression(uint32_t o = ~2U) : opcode(o) {}<br>
+  Expression(uint32_t o = ~2U) : opcode(o), commutative(false) {}<br>
<br>
   bool operator==(const Expression &other) const {<br>
     if (opcode != other.opcode)<br>
@@ -246,6 +247,7 @@ GVN::Expression GVN::ValueTable::createE<br>
     assert(I->getNumOperands() == 2 && "Unsupported commutative instruction!");<br>
     if (e.varargs[0] > e.varargs[1])<br>
       std::swap(e.varargs[0], e.varargs[1]);<br>
+    e.commutative = true;<br>
   }<br>
<br>
   if (CmpInst *C = dyn_cast<CmpInst>(I)) {<br>
@@ -256,6 +258,7 @@ GVN::Expression GVN::ValueTable::createE<br>
       Predicate = CmpInst::getSwappedPredicate(<wbr>Predicate);<br>
     }<br>
     e.opcode = (C->getOpcode() << 8) | Predicate;<br>
+    e.commutative = true;<br>
   } else if (InsertValueInst *E = dyn_cast<InsertValueInst>(I)) {<br>
     for (InsertValueInst::idx_iterator II = E->idx_begin(), IE = E->idx_end();<br>
          II != IE; ++II)<br>
@@ -281,6 +284,7 @@ GVN::Expression GVN::ValueTable::createC<br>
     Predicate = CmpInst::getSwappedPredicate(<wbr>Predicate);<br>
   }<br>
   e.opcode = (Opcode << 8) | Predicate;<br>
+  e.commutative = true;<br>
   return e;<br>
 }<br>
<br>
@@ -348,25 +352,25 @@ GVN::ValueTable::~ValueTable() = default<br>
 /// add - Insert a value into the table with a specified value number.<br>
 void GVN::ValueTable::add(Value *V, uint32_t num) {<br>
   valueNumbering.insert(std::<wbr>make_pair(V, num));<br>
+  if (PHINode *PN = dyn_cast<PHINode>(V))<br>
+    NumberingPhi[num] = PN;<br>
 }<br>
<br>
 uint32_t GVN::ValueTable::<wbr>lookupOrAddCall(CallInst *C) {<br>
   if (AA->doesNotAccessMemory(C)) {<br>
     Expression exp = createExpr(C);<br>
-    uint32_t &e = expressionNumbering[exp];<br>
-    if (!e) e = nextValueNumber++;<br>
+    uint32_t e = assignExpNewValueNum(exp).<wbr>first;<br>
     valueNumbering[C] = e;<br>
     return e;<br>
   } else if (AA->onlyReadsMemory(C)) {<br>
     Expression exp = createExpr(C);<br>
-    uint32_t &e = expressionNumbering[exp];<br>
-    if (!e) {<br>
-      e = nextValueNumber++;<br>
-      valueNumbering[C] = e;<br>
-      return e;<br>
+    auto ValNum = assignExpNewValueNum(exp);<br>
+    if (ValNum.second) {<br>
+      valueNumbering[C] = ValNum.first;<br>
+      return ValNum.first;<br>
     }<br>
     if (!MD) {<br>
-      e = nextValueNumber++;<br>
+      uint32_t e = assignExpNewValueNum(exp).<wbr>first;<br>
       valueNumbering[C] = e;<br>
       return e;<br>
     }<br>
@@ -522,23 +526,29 @@ uint32_t GVN::ValueTable::lookupOrAdd(<wbr>Va<br>
     case Instruction::ExtractValue:<br>
       exp = createExtractvalueExpr(cast<<wbr>ExtractValueInst>(I));<br>
       break;<br>
+    case Instruction::PHI:<br>
+      valueNumbering[V] = nextValueNumber;<br>
+      NumberingPhi[nextValueNumber] = cast<PHINode>(V);<br>
+      return nextValueNumber++;<br>
     default:<br>
       valueNumbering[V] = nextValueNumber;<br>
       return nextValueNumber++;<br>
   }<br>
<br>
-  uint32_t& e = expressionNumbering[exp];<br>
-  if (!e) e = nextValueNumber++;<br>
+  uint32_t e = assignExpNewValueNum(exp).<wbr>first;<br>
   valueNumbering[V] = e;<br>
   return e;<br>
 }<br>
<br>
 /// Returns the value number of the specified value. Fails if<br>
 /// the value has not yet been numbered.<br>
-uint32_t GVN::ValueTable::lookup(Value *V) const {<br>
+uint32_t GVN::ValueTable::lookup(Value *V, bool Verify) const {<br>
   DenseMap<Value*, uint32_t>::const_iterator VI = valueNumbering.find(V);<br>
-  assert(VI != valueNumbering.end() && "Value not numbered?");<br>
-  return VI->second;<br>
+  if (Verify) {<br>
+    assert(VI != valueNumbering.end() && "Value not numbered?");<br>
+    return VI->second;<br>
+  }<br>
+  return (VI != valueNumbering.end()) ? VI->second : 0;<br>
 }<br>
<br>
 /// Returns the value number of the given comparison,<br>
@@ -549,21 +559,29 @@ uint32_t GVN::ValueTable::<wbr>lookupOrAddCmp<br>
                                          CmpInst::Predicate Predicate,<br>
                                          Value *LHS, Value *RHS) {<br>
   Expression exp = createCmpExpr(Opcode, Predicate, LHS, RHS);<br>
-  uint32_t& e = expressionNumbering[exp];<br>
-  if (!e) e = nextValueNumber++;<br>
-  return e;<br>
+  return assignExpNewValueNum(exp).<wbr>first;<br>
 }<br>
<br>
 /// Remove all entries from the ValueTable.<br>
 void GVN::ValueTable::clear() {<br>
   valueNumbering.clear();<br>
   expressionNumbering.clear();<br>
+  NumberingPhi.clear();<br>
+  PhiTranslateTable.clear();<br>
+  BlockRPONumber.clear();<br>
   nextValueNumber = 1;<br>
+  Expressions.clear();<br>
+  ExprIdx.clear();<br>
+  nextExprNumber = 0;<br>
 }<br>
<br>
 /// Remove a value from the value numbering.<br>
 void GVN::ValueTable::erase(Value *V) {<br>
+  uint32_t Num = valueNumbering.lookup(V);<br>
   valueNumbering.erase(V);<br>
+  // If V is PHINode, V <--> value number is an one-to-one mapping.<br>
+  if (isa<PHINode>(V))<br>
+    NumberingPhi.erase(Num);<br>
 }<br>
<br>
 /// verifyRemoved - Verify that the value is removed from all internal data<br>
@@ -1451,6 +1469,104 @@ bool GVN::processLoad(LoadInst *L) {<br>
   return false;<br>
 }<br>
<br>
+/// Return a pair the first field showing the value number of \p Exp and the<br>
+/// second field showing whether it is a value number newly created.<br>
+std::pair<uint32_t, bool><br>
+GVN::ValueTable::<wbr>assignExpNewValueNum(<wbr>Expression &Exp) {<br>
+  uint32_t &e = expressionNumbering[Exp];<br>
+  bool CreateNewValNum = !e;<br>
+  if (CreateNewValNum) {<br>
+    Expressions.push_back(Exp);<br>
+    if (ExprIdx.size() < nextValueNumber + 1)<br>
+      ExprIdx.resize(nextValueNumber * 2);<br>
+    e = nextValueNumber;<br>
+    ExprIdx[nextValueNumber++] = nextExprNumber++;<br>
+  }<br>
+  return {e, CreateNewValNum};<br>
+}<br>
+<br>
+void GVN::ValueTable::<wbr>assignBlockRPONumber(Function &F) {<br>
+  uint32_t NextBlockNumber = 1;<br>
+  ReversePostOrderTraversal<<wbr>Function *> RPOT(&F);<br>
+  for (BasicBlock *BB : RPOT)<br>
+    BlockRPONumber[BB] = NextBlockNumber++;<br>
+}<br>
+<br>
+/// Return whether all the values related with the same \p num are<br>
+/// defined in \p BB.<br>
+bool GVN::ValueTable::<wbr>areAllValsInBB(uint32_t Num, const BasicBlock *BB,<br>
+                                     GVN &Gvn) {<br>
+  LeaderTableEntry *Vals = &Gvn.LeaderTable[Num];<br>
+  while (Vals && Vals->BB == BB)<br>
+    Vals = Vals->Next;<br>
+  return !Vals;<br>
+}<br>
+<br>
+/// Wrap phiTranslateImpl to provide caching functionality.<br>
+uint32_t GVN::ValueTable::phiTranslate(<wbr>const BasicBlock *Pred,<br>
+                                       const BasicBlock *PhiBlock, uint32_t Num,<br>
+                                       GVN &Gvn) {<br>
+  auto FindRes = PhiTranslateTable.find({Num, Pred});<br>
+  if (FindRes != PhiTranslateTable.end())<br>
+    return FindRes->second;<br>
+  uint32_t NewNum = phiTranslateImpl(Pred, PhiBlock, Num, Gvn);<br>
+  PhiTranslateTable.insert({{<wbr>Num, Pred}, NewNum});<br>
+  return NewNum;<br>
+}<br>
+<br>
+/// Translate value number \p Num using phis, so that it has the values of<br>
+/// the phis in BB.<br>
+uint32_t GVN::ValueTable::<wbr>phiTranslateImpl(const BasicBlock *Pred,<br>
+                                           const BasicBlock *PhiBlock,<br>
+                                           uint32_t Num, GVN &Gvn) {<br>
+  if (PHINode *PN = NumberingPhi[Num]) {<br>
+    if (BlockRPONumber[Pred] >= BlockRPONumber[PhiBlock])<br>
+      return Num;<br>
+    for (unsigned i = 0; i != PN->getNumIncomingValues(); ++i) {<br>
+      if (PN->getParent() == PhiBlock && PN->getIncomingBlock(i) == Pred)<br>
+        if (uint32_t TransVal = lookup(PN->getIncomingValue(i)<wbr>, false))<br>
+          return TransVal;<br>
+    }<br>
+    return Num;<br>
+  }<br>
+<br>
+  // If there is any value related with Num is defined in a BB other than<br>
+  // PhiBlock, it cannot depend on a phi in PhiBlock without going through<br>
+  // a backedge. We can do an early exit in that case to save compile time.<br>
+  if (!areAllValsInBB(Num, PhiBlock, Gvn))<br>
+    return Num;<br>
+<br>
+  if (ExprIdx[Num] == 0 || Num >= ExprIdx.size())<br>
+    return Num;<br>
+  Expression Exp = Expressions[ExprIdx[Num]];<br>
+<br>
+  for (unsigned i = 0; i < Exp.varargs.size(); i++) {<br>
+    // For InsertValue and ExtractValue, some varargs are index numbers<br>
+    // instead of value numbers. Those index numbers should not be<br>
+    // translated.<br>
+    if ((i > 1 && Exp.opcode == Instruction::InsertValue) ||<br>
+        (i > 0 && Exp.opcode == Instruction::ExtractValue))<br>
+      continue;<br>
+    Exp.varargs[i] = phiTranslate(Pred, PhiBlock, Exp.varargs[i], Gvn);<br>
+  }<br>
+<br>
+  if (Exp.commutative) {<br>
+    assert(Exp.varargs.size() == 2 && "Unsupported commutative expression!");<br>
+    if (Exp.varargs[0] > Exp.varargs[1]) {<br>
+      std::swap(Exp.varargs[0], Exp.varargs[1]);<br>
+      uint32_t Opcode = Exp.opcode >> 8;<br>
+      if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp)<br>
+        Exp.opcode = (Opcode << 8) |<br>
+                     CmpInst::getSwappedPredicate(<br>
+                         static_cast<CmpInst::<wbr>Predicate>(Exp.opcode & 255));<br>
+    }<br>
+  }<br>
+<br>
+  if (uint32_t NewNum = expressionNumbering[Exp])<br>
+    return NewNum;<br>
+  return Num;<br>
+}<br>
+<br>
 // In order to find a leader for a given value number at a<br>
 // specific basic block, we first obtain the list of all Values for that number,<br>
 // and then scan the list to find one whose block dominates the block in<br>
@@ -1856,6 +1972,7 @@ bool GVN::runImpl(Function &F, Assumptio<br>
     // Fabricate val-num for dead-code in order to suppress assertion in<br>
     // performPRE().<br>
     assignValNumForDeadCode();<br>
+    VN.assignBlockRPONumber(F);<br>
     bool PREChanged = true;<br>
     while (PREChanged) {<br>
       PREChanged = performPRE(F);<br>
@@ -1945,7 +2062,9 @@ bool GVN::<wbr>performScalarPREInsertion(Inst<br>
       success = false;<br>
       break;<br>
     }<br>
-    if (Value *V = findLeader(Pred, VN.lookup(Op))) {<br>
+    uint32_t TValNo =<br>
+        VN.phiTranslate(Pred, Instr->getParent(), VN.lookup(Op), *this);<br>
+    if (Value *V = findLeader(Pred, TValNo)) {<br>
       Instr->setOperand(i, V);<br>
     } else {<br>
       success = false;<br>
@@ -1962,10 +2081,12 @@ bool GVN::<wbr>performScalarPREInsertion(Inst<br>
   Instr->insertBefore(Pred-><wbr>getTerminator());<br>
   Instr->setName(Instr->getName(<wbr>) + ".pre");<br>
   Instr->setDebugLoc(Instr-><wbr>getDebugLoc());<br>
-  VN.add(Instr, ValNo);<br>
+<br>
+  unsigned Num = VN.lookupOrAdd(Instr);<br>
+  VN.add(Instr, Num);<br>
<br>
   // Update the availability map to include the new instruction.<br>
-  addToLeaderTable(ValNo, Instr, Pred);<br>
+  addToLeaderTable(Num, Instr, Pred);<br>
   return true;<br>
 }<br>
<br>
@@ -2014,7 +2135,8 @@ bool GVN::performScalarPRE(<wbr>Instruction *<br>
       break;<br>
     }<br>
<br>
-    Value *predV = findLeader(P, ValNo);<br>
+    uint32_t TValNo = VN.phiTranslate(P, CurrentBlock, ValNo, *this);<br>
+    Value *predV = findLeader(P, TValNo);<br>
     if (!predV) {<br>
       predMap.push_back(std::make_<wbr>pair(static_cast<Value *>(nullptr), P));<br>
       PREPred = P;<br>
<br>
Added: llvm/trunk/test/Transforms/<wbr>GVN/PRE/phi-translate-2.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/phi-translate-2.ll?rev=304050&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>Transforms/GVN/PRE/phi-<wbr>translate-2.ll?rev=304050&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/Transforms/<wbr>GVN/PRE/phi-translate-2.ll (added)<br>
+++ llvm/trunk/test/Transforms/<wbr>GVN/PRE/phi-translate-2.ll Fri May 26 19:54:19 2017<br>
@@ -0,0 +1,105 @@<br>
+; RUN: opt < %s -gvn -S | FileCheck %s<br>
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:<wbr>32:64-S128"<br>
+<br>
+@a = common global [100 x i64] zeroinitializer, align 16<br>
+@b = common global [100 x i64] zeroinitializer, align 16<br>
+@g1 = common global i64 0, align 8<br>
+@g2 = common global i64 0, align 8<br>
+@g3 = common global i64 0, align 8<br>
+declare i64 @goo(...) local_unnamed_addr #1<br>
+<br>
+define void @test1(i64 %a, i64 %b, i64 %c, i64 %d) {<br>
+entry:<br>
+  %mul = mul nsw i64 %b, %a<br>
+  store i64 %mul, i64* @g1, align 8<br>
+  %t0 = load i64, i64* @g2, align 8<br>
+  %cmp = icmp sgt i64 %t0, 3<br>
+  br i1 %cmp, label %if.then, label %if.end<br>
+<br>
+if.then:                                          ; preds = %entry<br>
+  %mul2 = mul nsw i64 %d, %c<br>
+  store i64 %mul2, i64* @g2, align 8<br>
+  br label %if.end<br>
+<br>
+; Check phi-translate works and mul is removed.<br>
+; CHECK-LABEL: @test1(<br>
+; CHECK: if.end:<br>
+; CHECK: %[[MULPHI:.*]] = phi i64 [ {{.*}}, %if.then ], [ %mul, %entry ]<br>
+; CHECK-NOT: = mul<br>
+; CHECK: store i64 %[[MULPHI]], i64* @g3, align 8<br>
+if.end:                                           ; preds = %if.then, %entry<br>
+  %b.addr.0 = phi i64 [ %d, %if.then ], [ %b, %entry ]<br>
+  %a.addr.0 = phi i64 [ %c, %if.then ], [ %a, %entry ]<br>
+  %mul3 = mul nsw i64 %a.addr.0, %b.addr.0<br>
+  store i64 %mul3, i64* @g3, align 8<br>
+  ret void<br>
+}<br>
+<br>
+define void @test2(i64 %i) {<br>
+entry:<br>
+  %arrayidx = getelementptr inbounds [100 x i64], [100 x i64]* @a, i64 0, i64 %i<br>
+  %t0 = load i64, i64* %arrayidx, align 8<br>
+  %arrayidx1 = getelementptr inbounds [100 x i64], [100 x i64]* @b, i64 0, i64 %i<br>
+  %t1 = load i64, i64* %arrayidx1, align 8<br>
+  %mul = mul nsw i64 %t1, %t0<br>
+  store i64 %mul, i64* @g1, align 8<br>
+  %cmp = icmp sgt i64 %mul, 3<br>
+  br i1 %cmp, label %if.then, label %if.end<br>
+<br>
+; Check phi-translate works for the phi generated by loadpre. A new mul will be<br>
+; inserted in if.then block.<br>
+; CHECK-LABEL: @test2(<br>
+; CHECK: if.then:<br>
+; CHECK: %[[MUL_THEN:.*]] = mul<br>
+; CHECK: br label %if.end<br>
+if.then:                                          ; preds = %entry<br>
+  %call = tail call i64 (...) @goo() #2<br>
+  store i64 %call, i64* @g2, align 8<br>
+  br label %if.end<br>
+<br>
+; CHECK: if.end:<br>
+; CHECK: %[[MULPHI:.*]] = phi i64 [ %[[MUL_THEN]], %if.then ], [ %mul, %entry ]<br>
+; CHECK-NOT: = mul<br>
+; CHECK: store i64 %[[MULPHI]], i64* @g3, align 8<br>
+if.end:                                           ; preds = %if.then, %entry<br>
+  %i.addr.0 = phi i64 [ 3, %if.then ], [ %i, %entry ]<br>
+  %arrayidx3 = getelementptr inbounds [100 x i64], [100 x i64]* @a, i64 0, i64 %i.addr.0<br>
+  %t2 = load i64, i64* %arrayidx3, align 8<br>
+  %arrayidx4 = getelementptr inbounds [100 x i64], [100 x i64]* @b, i64 0, i64 %i.addr.0<br>
+  %t3 = load i64, i64* %arrayidx4, align 8<br>
+  %mul5 = mul nsw i64 %t3, %t2<br>
+  store i64 %mul5, i64* @g3, align 8<br>
+  ret void<br>
+}<br>
+<br>
+; Check phi-translate doesn't go through backedge, which may lead to incorrect<br>
+; pre transformation.<br>
+; CHECK: for.end:<br>
+; CHECK-NOT: %{{.*pre-phi}} = phi<br>
+; CHECK: ret void<br>
+define void @test3(i64 %N, i64* nocapture readonly %a) {<br>
+entry:<br>
+  br label %for.cond<br>
+<br>
+for.cond:                                         ; preds = %for.body, %entry<br>
+  %i.0 = phi i64 [ 0, %entry ], [ %add, %for.body ]<br>
+  %add = add nuw nsw i64 %i.0, 1<br>
+  %arrayidx = getelementptr inbounds i64, i64* %a, i64 %add<br>
+  %tmp0 = load i64, i64* %arrayidx, align 8<br>
+  %cmp = icmp slt i64 %i.0, %N<br>
+  br i1 %cmp, label %for.body, label %for.end<br>
+<br>
+for.body:                                         ; preds = %for.cond<br>
+  %call = tail call i64 (...) @goo() #2<br>
+  %add1 = sub nsw i64 0, %call<br>
+  %tobool = icmp eq i64 %tmp0, %add1<br>
+  br i1 %tobool, label %for.cond, label %for.end<br>
+<br>
+for.end:                                          ; preds = %for.body, %for.cond<br>
+  %i.0.lcssa = phi i64 [ %i.0, %for.body ], [ %i.0, %for.cond ]<br>
+  %arrayidx2 = getelementptr inbounds i64, i64* %a, i64 %i.0.lcssa<br>
+  %tmp1 = load i64, i64* %arrayidx2, align 8<br>
+  store i64 %tmp1, i64* @g1, align 8<br>
+  ret void<br>
+}<br>
+<br>
<br>
Modified: llvm/trunk/test/Transforms/<wbr>GVN/PRE/pre-gep-load.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/pre-gep-load.ll?rev=304050&r1=304049&r2=304050&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>Transforms/GVN/PRE/pre-gep-<wbr>load.ll?rev=304050&r1=304049&<wbr>r2=304050&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/Transforms/<wbr>GVN/PRE/pre-gep-load.ll (original)<br>
+++ llvm/trunk/test/Transforms/<wbr>GVN/PRE/pre-gep-load.ll Fri May 26 19:54:19 2017<br>
@@ -37,7 +37,7 @@ sw.bb2:<br>
   %3 = load double, double* %arrayidx5, align 8<br>
 ; CHECK: sw.bb2:<br>
 ; CHECK-NOT: sext<br>
-; CHECK-NEXT: phi double [<br>
+; CHECK: phi double [<br>
 ; CHECK-NOT: load<br>
   %sub6 = fsub double 3.000000e+00, %3<br>
   br label %return<br>
<br>
Modified: llvm/trunk/test/Transforms/<wbr>GVN/PRE/pre-load.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/pre-load.ll?rev=304050&r1=304049&r2=304050&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>Transforms/GVN/PRE/pre-load.<wbr>ll?rev=304050&r1=304049&r2=<wbr>304050&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/Transforms/<wbr>GVN/PRE/pre-load.ll (original)<br>
+++ llvm/trunk/test/Transforms/<wbr>GVN/PRE/pre-load.ll Fri May 26 19:54:19 2017<br>
@@ -72,7 +72,7 @@ block4:<br>
   %PRE = load i32, i32* %P3<br>
   ret i32 %PRE<br>
 ; CHECK: block4:<br>
-; CHECK-NEXT: phi i32 [<br>
+; CHECK: phi i32 [<br>
 ; CHECK-NOT: load<br>
 ; CHECK: ret i32<br>
 }<br>
@@ -104,7 +104,7 @@ block4:<br>
   %PRE = load i32, i32* %P3<br>
   ret i32 %PRE<br>
 ; CHECK: block4:<br>
-; CHECK-NEXT: phi i32 [<br>
+; CHECK: phi i32 [<br>
 ; CHECK-NOT: load<br>
 ; CHECK: ret i32<br>
 }<br>
@@ -263,7 +263,7 @@ block4:<br>
   %PRE = load i32, i32* %P3<br>
   ret i32 %PRE<br>
 ; CHECK: block4:<br>
-; CHECK-NEXT: phi i32 [<br>
+; CHECK: phi i32 [<br>
 ; CHECK-NOT: load<br>
 ; CHECK: ret i32<br>
 }<br>
<br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr">-- <div>Peter</div></div></div>
</div>