<div dir="ltr">Hi,<div><br></div><div>We spotted a new assertion failure starting with this commit (sorry it took a few days to spot and report).  I've put details in:</div><div><a href="https://bugs.llvm.org/show_bug.cgi?id=33346">https://bugs.llvm.org/show_bug.cgi?id=33346</a><br></div><div><br></div><div>-Greg</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On 2 June 2017 at 03:09, Xinliang David Li 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: davidxl<br>
Date: Thu Jun  1 21:09:31 2017<br>
New Revision: 304517<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=304517&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=304517&view=rev</a><br>
Log:<br>
[Profile] Enhance expect lowering to handle correlated branches<br>
<br>
builtin_expect applied on && or || expressions were not<br>
handled properly before. With this patch, the problem is fixed.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D33164" rel="noreferrer" target="_blank">http://reviews.llvm.org/D33164</a><br>
<br>
Added:<br>
    llvm/trunk/test/Transforms/<wbr>LowerExpectIntrinsic/phi_<wbr>merge.ll<br>
    llvm/trunk/test/Transforms/<wbr>LowerExpectIntrinsic/phi_or.ll<br>
    llvm/trunk/test/Transforms/<wbr>LowerExpectIntrinsic/phi_tern.<wbr>ll<br>
Modified:<br>
    llvm/trunk/lib/Transforms/<wbr>Scalar/LowerExpectIntrinsic.<wbr>cpp<br>
<br>
Modified: llvm/trunk/lib/Transforms/<wbr>Scalar/LowerExpectIntrinsic.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp?rev=304517&r1=304516&r2=304517&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>Transforms/Scalar/<wbr>LowerExpectIntrinsic.cpp?rev=<wbr>304517&r1=304516&r2=304517&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/<wbr>Scalar/LowerExpectIntrinsic.<wbr>cpp (original)<br>
+++ llvm/trunk/lib/Transforms/<wbr>Scalar/LowerExpectIntrinsic.<wbr>cpp Thu Jun  1 21:09:31 2017<br>
@@ -14,6 +14,7 @@<br>
 #include "llvm/Transforms/Scalar/<wbr>LowerExpectIntrinsic.h"<br>
 #include "llvm/ADT/SmallVector.h"<br>
 #include "llvm/ADT/Statistic.h"<br>
+#include "llvm/ADT/iterator_range.h"<br>
 #include "llvm/IR/BasicBlock.h"<br>
 #include "llvm/IR/Constants.h"<br>
 #include "llvm/IR/Function.h"<br>
@@ -83,6 +84,149 @@ static bool handleSwitchExpect(SwitchIns<br>
   return true;<br>
 }<br>
<br>
+/// Handler for PHINodes that define the value argument to an<br>
+/// @llvm.expect call.<br>
+///<br>
+/// If the operand of the phi has a constant value and it 'contradicts'<br>
+/// with the expected value of phi def, then the corresponding incoming<br>
+/// edge of the phi is unlikely to be taken. Using that information,<br>
+/// the branch probability info for the originating branch can be inferred.<br>
+static void handlePhiDef(CallInst *Expect) {<br>
+  Value &Arg = *Expect->getArgOperand(0);<br>
+  ConstantInt *ExpectedValue = cast<ConstantInt>(Expect-><wbr>getArgOperand(1));<br>
+  const APInt &ExpectedPhiValue = ExpectedValue->getValue();<br>
+<br>
+  // Walk up in backward a list of instructions that<br>
+  // have 'copy' semantics by 'stripping' the copies<br>
+  // until a PHI node or an instruction of unknown kind<br>
+  // is reached. Negation via xor is also handled.<br>
+  //<br>
+  //       C = PHI(...);<br>
+  //       B = C;<br>
+  //       A = B;<br>
+  //       D = __builtin_expect(A, 0);<br>
+  //<br>
+  Value *V = &Arg;<br>
+  SmallVector<Instruction *, 4> Operations;<br>
+  while (!isa<PHINode>(V)) {<br>
+    if (ZExtInst *ZExt = dyn_cast<ZExtInst>(V)) {<br>
+      V = ZExt->getOperand(0);<br>
+      Operations.push_back(ZExt);<br>
+      continue;<br>
+    }<br>
+<br>
+    if (SExtInst *SExt = dyn_cast<SExtInst>(V)) {<br>
+      V = SExt->getOperand(0);<br>
+      Operations.push_back(SExt);<br>
+      continue;<br>
+    }<br>
+<br>
+    BinaryOperator *BinOp = dyn_cast<BinaryOperator>(V);<br>
+    if (!BinOp || BinOp->getOpcode() != Instruction::Xor)<br>
+      return;<br>
+<br>
+    ConstantInt *CInt = dyn_cast<ConstantInt>(BinOp-><wbr>getOperand(1));<br>
+    if (!CInt)<br>
+      return;<br>
+<br>
+    V = BinOp->getOperand(0);<br>
+    Operations.push_back(BinOp);<br>
+  }<br>
+<br>
+  // Executes the recorded operations on input 'Value'.<br>
+  auto ApplyOperations = [&](const APInt &Value) {<br>
+    APInt Result = Value;<br>
+    for (auto Op : llvm::reverse(Operations)) {<br>
+      switch (Op->getOpcode()) {<br>
+      case Instruction::Xor:<br>
+        Result ^= cast<ConstantInt>(Op-><wbr>getOperand(1))->getValue();<br>
+        break;<br>
+      case Instruction::ZExt:<br>
+        Result = Result.zext(Op->getType()-><wbr>getIntegerBitWidth());<br>
+        break;<br>
+      case Instruction::SExt:<br>
+        Result = Result.sext(Op->getType()-><wbr>getIntegerBitWidth());<br>
+        break;<br>
+      default:<br>
+        llvm_unreachable("Unexpected operation");<br>
+      }<br>
+    }<br>
+    return Result;<br>
+  };<br>
+<br>
+  auto *PhiDef = dyn_cast<PHINode>(V);<br>
+<br>
+  // Get the first dominating conditional branch of the operand<br>
+  // i's incoming block.<br>
+  auto GetDomConditional = [&](unsigned i) -> BranchInst * {<br>
+    BasicBlock *BB = PhiDef->getIncomingBlock(i);<br>
+    BranchInst *BI = dyn_cast<BranchInst>(BB-><wbr>getTerminator());<br>
+    if (BI && BI->isConditional())<br>
+      return BI;<br>
+    BB = BB->getSinglePredecessor();<br>
+    if (!BB)<br>
+      return nullptr;<br>
+    BI = dyn_cast<BranchInst>(BB-><wbr>getTerminator());<br>
+    if (!BI || BI->isUnconditional())<br>
+      return nullptr;<br>
+    return BI;<br>
+  };<br>
+<br>
+  // Now walk through all Phi operands to find phi oprerands with values<br>
+  // conflicting with the expected phi output value. Any such operand<br>
+  // indicates the incoming edge to that operand is unlikely.<br>
+  for (unsigned i = 0, e = PhiDef->getNumIncomingValues()<wbr>; i != e; ++i) {<br>
+<br>
+    Value *PhiOpnd = PhiDef->getIncomingValue(i);<br>
+    ConstantInt *CI = dyn_cast<ConstantInt>(PhiOpnd)<wbr>;<br>
+    if (!CI)<br>
+      continue;<br>
+<br>
+    // Not an interesting case when IsUnlikely is false -- we can not infer<br>
+    // anything useful when the operand value matches the expected phi<br>
+    // output.<br>
+    if (ExpectedPhiValue == ApplyOperations(CI->getValue()<wbr>))<br>
+      continue;<br>
+<br>
+    BranchInst *BI = GetDomConditional(i);<br>
+    if (!BI)<br>
+      continue;<br>
+<br>
+    MDBuilder MDB(PhiDef->getContext());<br>
+<br>
+    // There are two situations in which an operand of the PhiDef comes<br>
+    // from a given successor of a branch instruction BI.<br>
+    // 1) When the incoming block of the operand is the successor block;<br>
+    // 2) When the incoming block is BI's enclosing block and the<br>
+    // successor is the PhiDef's enclosing block.<br>
+    //<br>
+    // Returns true if the operand which comes from OpndIncomingBB<br>
+    // comes from outgoing edge of BI that leads to Succ block.<br>
+    auto *OpndIncomingBB = PhiDef->getIncomingBlock(i);<br>
+    auto IsOpndComingFromSuccessor = [&](BasicBlock *Succ) {<br>
+      if (OpndIncomingBB == Succ)<br>
+        // If this successor is the incoming block for this<br>
+        // Phi operand, then this successor does lead to the Phi.<br>
+        return true;<br>
+      if (OpndIncomingBB == BI->getParent() && Succ == PhiDef->getParent())<br>
+        // Otherwise, if the edge is directly from the branch<br>
+        // to the Phi, this successor is the one feeding this<br>
+        // Phi operand.<br>
+        return true;<br>
+      return false;<br>
+    };<br>
+<br>
+    if (IsOpndComingFromSuccessor(BI-<wbr>>getSuccessor(1)))<br>
+      BI->setMetadata(<br>
+          LLVMContext::MD_prof,<br>
+          MDB.createBranchWeights(<wbr>LikelyBranchWeight, UnlikelyBranchWeight));<br>
+    else if (IsOpndComingFromSuccessor(BI-<wbr>>getSuccessor(0)))<br>
+      BI->setMetadata(<br>
+          LLVMContext::MD_prof,<br>
+          MDB.createBranchWeights(<wbr>UnlikelyBranchWeight, LikelyBranchWeight));<br>
+  }<br>
+}<br>
+<br>
 // Handle both BranchInst and SelectInst.<br>
 template <class BrSelInst> static bool handleBrSelExpect(BrSelInst &BSI) {<br>
<br>
@@ -187,6 +331,10 @@ static bool lowerExpectIntrinsic(Functio<br>
<br>
       Function *Fn = CI->getCalledFunction();<br>
       if (Fn && Fn->getIntrinsicID() == Intrinsic::expect) {<br>
+        // Before erasing the llvm.expect, walk backward to find<br>
+        // phi that define llvm.expect's first arg, and<br>
+        // infer branch probability:<br>
+        handlePhiDef(CI);<br>
         Value *Exp = CI->getArgOperand(0);<br>
         CI->replaceAllUsesWith(Exp);<br>
         CI->eraseFromParent();<br>
<br>
Added: llvm/trunk/test/Transforms/<wbr>LowerExpectIntrinsic/phi_<wbr>merge.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerExpectIntrinsic/phi_merge.ll?rev=304517&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>Transforms/<wbr>LowerExpectIntrinsic/phi_<wbr>merge.ll?rev=304517&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/Transforms/<wbr>LowerExpectIntrinsic/phi_<wbr>merge.ll (added)<br>
+++ llvm/trunk/test/Transforms/<wbr>LowerExpectIntrinsic/phi_<wbr>merge.ll Thu Jun  1 21:09:31 2017<br>
@@ -0,0 +1,356 @@<br>
+; RUN: opt -lower-expect  -S -o - < %s | FileCheck %s<br>
+; RUN: opt -S -passes='function(lower-<wbr>expect)' < %s | FileCheck %s<br>
+<br>
+; The C case<br>
+; if (__builtin_expect((x > goo() && y > hoo() && z > too()), 1))<br>
+; For the above case, all 3 branches should be annotated.<br>
+;<br>
+; if (__builtin_expect((x > goo() && y > hoo() && z > too()), 0))<br>
+; For the above case, we don't have enough information, so<br>
+; only the last branch is annotated.<br>
+<br>
+define void @foo(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3) {<br>
+; CHECK-LABEL: void @foo<br>
+bb:<br>
+  %tmp8 = call i32  @goo()<br>
+  %tmp9 = icmp sgt i32 %tmp8, %arg<br>
+  br i1 %tmp9, label %bb10, label %bb18<br>
+; CHECK: !prof [[WEIGHT:![0-9]+]]<br>
+<br>
+bb10:                                             ; preds = %bb<br>
+  %tmp12 = call i32  @hoo()<br>
+  %tmp13 = icmp sgt i32 %arg1, %tmp12<br>
+  br i1 %tmp13, label %bb14, label %bb18<br>
+; CHECK: br i1 %tmp13, {{.*}}!prof [[WEIGHT]]<br>
+<br>
+bb14:                                             ; preds = %bb10<br>
+  %tmp16 = call i32  @too()<br>
+  %tmp17 = icmp sgt i32 %arg2, %tmp16<br>
+  br label %bb18<br>
+<br>
+bb18:                                             ; preds = %bb14, %bb10, %bb<br>
+  %tmp19 = phi i1 [ false, %bb10 ], [ false, %bb ], [ %tmp17, %bb14 ]<br>
+  %tmp20 = xor i1 %tmp19, true<br>
+  %tmp21 = xor i1 %tmp20, true<br>
+  %tmp22 = zext i1 %tmp21 to i32<br>
+  %tmp23 = sext i32 %tmp22 to i64<br>
+  %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 1)<br>
+  %tmp25 = icmp ne i64 %tmp24, 0<br>
+  br i1 %tmp25, label %bb26, label %bb28<br>
+; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]<br>
+<br>
+bb26:                                             ; preds = %bb18<br>
+  %tmp27 = call i32  @goo()<br>
+  br label %bb30<br>
+<br>
+bb28:                                             ; preds = %bb18<br>
+  %tmp29 = call i32  @hoo()<br>
+  br label %bb30<br>
+<br>
+bb30:                                             ; preds = %bb28, %bb26<br>
+  ret void<br>
+}<br>
+<br>
+define void @foo2(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3) {<br>
+; CHECK-LABEL: void @foo2<br>
+bb:<br>
+  %tmp8 = call i32  @goo()<br>
+  %tmp9 = icmp sgt i32 %tmp8, %arg<br>
+  br i1 %tmp9, label %bb10, label %bb18<br>
+; CHECK:  br i1 %tmp9<br>
+; CHECK-NOT: !prof<br>
+<br>
+bb10:                                             ; preds = %bb<br>
+  %tmp12 = call i32  @hoo()<br>
+  %tmp13 = icmp sgt i32 %arg1, %tmp12<br>
+  br i1 %tmp13, label %bb14, label %bb18<br>
+; CHECK: br i1 %tmp13<br>
+; CHECK-NOT: !prof<br>
+<br>
+bb14:                                             ; preds = %bb10<br>
+  %tmp16 = call i32 @too()<br>
+  %tmp17 = icmp sgt i32 %arg2, %tmp16<br>
+  br label %bb18<br>
+<br>
+bb18:                                             ; preds = %bb14, %bb10, %bb<br>
+  %tmp19 = phi i1 [ false, %bb10 ], [ false, %bb ], [ %tmp17, %bb14 ]<br>
+  %tmp20 = xor i1 %tmp19, true<br>
+  %tmp21 = xor i1 %tmp20, true<br>
+  %tmp22 = zext i1 %tmp21 to i32<br>
+  %tmp23 = sext i32 %tmp22 to i64<br>
+  %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 0)<br>
+  %tmp25 = icmp ne i64 %tmp24, 0<br>
+  br i1 %tmp25, label %bb26, label %bb28<br>
+; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT2:![0-9]+]]<br>
+<br>
+bb26:                                             ; preds = %bb18<br>
+  %tmp27 = call i32 @goo()<br>
+  br label %bb30<br>
+<br>
+bb28:                                             ; preds = %bb18<br>
+  %tmp29 = call i32 @hoo()<br>
+  br label %bb30<br>
+<br>
+bb30:                                             ; preds = %bb28, %bb26<br>
+  ret void<br>
+}<br>
+<br>
+define void @foo_i32(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3) {<br>
+; CHECK-LABEL: void @foo_i32<br>
+bb:<br>
+  %tmp8 = call i32  @goo()<br>
+  %tmp9 = icmp sgt i32 %tmp8, %arg<br>
+  br i1 %tmp9, label %bb10, label %bb18<br>
+; CHECK: !prof [[WEIGHT]]<br>
+<br>
+bb10:                                             ; preds = %bb<br>
+  %tmp12 = call i32 @hoo()<br>
+  %tmp13 = icmp sgt i32 %arg1, %tmp12<br>
+  br i1 %tmp13, label %bb14, label %bb18<br>
+; CHECK: br i1 %tmp13, {{.*}}!prof [[WEIGHT]]<br>
+<br>
+bb14:                                             ; preds = %bb10<br>
+  %tmp16 = call i32 @too()<br>
+  %tmp17 = icmp sgt i32 %arg2, %tmp16<br>
+  br label %bb18<br>
+<br>
+bb18:                                             ; preds = %bb14, %bb10, %bb<br>
+  %tmp19 = phi i32 [ 5, %bb10 ], [ 5, %bb ], [ %tmp16, %bb14 ]<br>
+  %tmp23 = sext i32 %tmp19 to i64<br>
+  %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 4)<br>
+  %tmp25 = icmp ne i64 %tmp24, 0<br>
+  br i1 %tmp25, label %bb26, label %bb28<br>
+; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]<br>
+<br>
+bb26:                                             ; preds = %bb18<br>
+  %tmp27 = call i32 @goo()<br>
+  br label %bb30<br>
+<br>
+bb28:                                             ; preds = %bb18<br>
+  %tmp29 = call i32 @hoo()<br>
+  br label %bb30<br>
+<br>
+bb30:                                             ; preds = %bb28, %bb26<br>
+  ret void<br>
+}<br>
+<br>
+<br>
+define void @foo_i32_not_unlikely(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3)  {<br>
+; CHECK-LABEL: void @foo_i32_not_unlikely<br>
+bb:<br>
+  %tmp8 = call i32 @goo()<br>
+  %tmp9 = icmp sgt i32 %tmp8, %arg<br>
+  br i1 %tmp9, label %bb10, label %bb18<br>
+; CHECK: br i1 %tmp9<br>
+; CHECK-NOT: !prof<br>
+<br>
+bb10:                                             ; preds = %bb<br>
+  %tmp12 = call i32 @hoo()<br>
+  %tmp13 = icmp sgt i32 %arg1, %tmp12<br>
+  br i1 %tmp13, label %bb14, label %bb18<br>
+; CHECK: br i1 %tmp13<br>
+; CHECK-NOT: !prof<br>
+<br>
+bb14:                                             ; preds = %bb10<br>
+  %tmp16 = call i32  @too()<br>
+  %tmp17 = icmp sgt i32 %arg2, %tmp16<br>
+  br label %bb18<br>
+<br>
+bb18:                                             ; preds = %bb14, %bb10, %bb<br>
+  %tmp19 = phi i32 [ 4, %bb10 ], [ 4, %bb ], [ %tmp16, %bb14 ]<br>
+  %tmp23 = sext i32 %tmp19 to i64<br>
+  %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 4)<br>
+  %tmp25 = icmp ne i64 %tmp24, 0<br>
+  br i1 %tmp25, label %bb26, label %bb28<br>
+; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]<br>
+<br>
+bb26:                                             ; preds = %bb18<br>
+  %tmp27 = call i32  @goo()<br>
+  br label %bb30<br>
+<br>
+bb28:                                             ; preds = %bb18<br>
+  %tmp29 = call i32 @hoo()<br>
+  br label %bb30<br>
+<br>
+bb30:                                             ; preds = %bb28, %bb26<br>
+  ret void<br>
+}<br>
+<br>
+define void @foo_i32_xor(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3)  {<br>
+; CHECK-LABEL: void @foo_i32_xor<br>
+bb:<br>
+  %tmp8 = call i32  @goo()<br>
+  %tmp9 = icmp sgt i32 %tmp8, %arg<br>
+  br i1 %tmp9, label %bb10, label %bb18<br>
+; CHECK: br i1 %tmp9,{{.*}}!prof [[WEIGHT]]<br>
+<br>
+bb10:                                             ; preds = %bb<br>
+  %tmp12 = call i32  @hoo()<br>
+  %tmp13 = icmp sgt i32 %arg1, %tmp12<br>
+  br i1 %tmp13, label %bb14, label %bb18<br>
+; CHECK: br i1 %tmp13,{{.*}}!prof [[WEIGHT]]<br>
+<br>
+bb14:                                             ; preds = %bb10<br>
+  %tmp16 = call i32  @too()<br>
+  %tmp17 = icmp sgt i32 %arg2, %tmp16<br>
+  br label %bb18<br>
+<br>
+bb18:                                             ; preds = %bb14, %bb10, %bb<br>
+  %tmp19 = phi i32 [ 6, %bb10 ], [ 6, %bb ], [ %tmp16, %bb14 ]<br>
+  %tmp20 = xor i32 %tmp19, 3<br>
+  %tmp23 = sext i32 %tmp20 to i64<br>
+  %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 4)<br>
+  %tmp25 = icmp ne i64 %tmp24, 0<br>
+  br i1 %tmp25, label %bb26, label %bb28<br>
+; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]<br>
+<br>
+bb26:                                             ; preds = %bb18<br>
+  %tmp27 = call i32 @goo()<br>
+  br label %bb30<br>
+<br>
+bb28:                                             ; preds = %bb18<br>
+  %tmp29 = call i32 @hoo()<br>
+  br label %bb30<br>
+bb30:                                             ; preds = %bb28, %bb26<br>
+  ret void<br>
+}<br>
+<br>
+define void @foo_i8_sext(i32 %arg, i32 %arg1, i8 %arg2, i32 %arg3)  {<br>
+; CHECK-LABEL: void @foo_i8_sext<br>
+bb:<br>
+  %tmp8 = call i32  @goo()<br>
+  %tmp9 = icmp sgt i32 %tmp8, %arg<br>
+  br i1 %tmp9, label %bb10, label %bb18<br>
+; CHECK: br i1 %tmp9,{{.*}}!prof [[WEIGHT]]<br>
+<br>
+bb10:                                             ; preds = %bb<br>
+  %tmp12 = call i32  @hoo()<br>
+  %tmp13 = icmp sgt i32 %arg1, %tmp12<br>
+  br i1 %tmp13, label %bb14, label %bb18<br>
+; CHECK: br i1 %tmp13,{{.*}}!prof [[WEIGHT]]<br>
+<br>
+bb14:                                             ; preds = %bb10<br>
+  %tmp16 = call i8  @too8()<br>
+  %tmp17 = icmp sgt i8 %arg2, %tmp16<br>
+  br label %bb18<br>
+<br>
+bb18:                                             ; preds = %bb14, %bb10, %bb<br>
+  %tmp19 = phi i8 [ 255, %bb10 ], [ 255, %bb ], [ %tmp16, %bb14 ]<br>
+  %tmp23 = sext i8 %tmp19 to i64<br>
+; after sign extension, the operand value becomes -1 which does not match 255<br>
+  %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 255)<br>
+  %tmp25 = icmp ne i64 %tmp24, 0<br>
+  br i1 %tmp25, label %bb26, label %bb28<br>
+; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]<br>
+<br>
+bb26:                                             ; preds = %bb18<br>
+  %tmp27 = call i32 @goo()<br>
+  br label %bb30<br>
+<br>
+bb28:                                             ; preds = %bb18<br>
+  %tmp29 = call i32 @hoo()<br>
+  br label %bb30<br>
+bb30:                                             ; preds = %bb28, %bb26<br>
+  ret void<br>
+}<br>
+<br>
+define void @foo_i8_sext_not_unlikely(i32 %arg, i32 %arg1, i8 %arg2, i32 %arg3)  {<br>
+; CHECK-LABEL: void @foo_i8_sext_not_unlikely<br>
+bb:<br>
+  %tmp8 = call i32  @goo()<br>
+  %tmp9 = icmp sgt i32 %tmp8, %arg<br>
+  br i1 %tmp9, label %bb10, label %bb18<br>
+; CHECK: br i1 %tmp9<br>
+; CHECK-NOT: !prof<br>
+<br>
+bb10:                                             ; preds = %bb<br>
+  %tmp12 = call i32  @hoo()<br>
+  %tmp13 = icmp sgt i32 %arg1, %tmp12<br>
+  br i1 %tmp13, label %bb14, label %bb18<br>
+; CHECK: br i1 %tmp13<br>
+; CHECK-NOT: !prof<br>
+<br>
+bb14:                                             ; preds = %bb10<br>
+  %tmp16 = call i8  @too8()<br>
+  %tmp17 = icmp sgt i8 %arg2, %tmp16<br>
+  br label %bb18<br>
+<br>
+bb18:                                             ; preds = %bb14, %bb10, %bb<br>
+  %tmp19 = phi i8 [ 255, %bb10 ], [ 255, %bb ], [ %tmp16, %bb14 ]<br>
+  %tmp23 = sext i8 %tmp19 to i64<br>
+; after sign extension, the operand value becomes -1 which matches -1<br>
+  %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 -1)<br>
+  %tmp25 = icmp ne i64 %tmp24, 0<br>
+  br i1 %tmp25, label %bb26, label %bb28<br>
+; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]<br>
+<br>
+bb26:                                             ; preds = %bb18<br>
+  %tmp27 = call i32 @goo()<br>
+  br label %bb30<br>
+<br>
+bb28:                                             ; preds = %bb18<br>
+  %tmp29 = call i32 @hoo()<br>
+  br label %bb30<br>
+bb30:                                             ; preds = %bb28, %bb26<br>
+  ret void<br>
+}<br>
+<br>
+<br>
+define void @foo_i32_xor_not_unlikely(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3)  {<br>
+; CHECK-LABEL: void @foo_i32_xor_not_unlikely<br>
+bb:<br>
+  %tmp8 = call i32 @goo()<br>
+  %tmp9 = icmp sgt i32 %tmp8, %arg<br>
+  br i1 %tmp9, label %bb10, label %bb18<br>
+; CHECK: br i1 %tmp9<br>
+; CHECK-NOT: !prof<br>
+<br>
+bb10:                                             ; preds = %bb<br>
+  %tmp12 = call i32  @hoo()<br>
+  %tmp13 = icmp sgt i32 %arg1, %tmp12<br>
+  br i1 %tmp13, label %bb14, label %bb18<br>
+; CHECK: br i1 %tmp13<br>
+; CHECK-NOT: !prof<br>
+<br>
+bb14:                                             ; preds = %bb10<br>
+  %tmp16 = call i32 @too()<br>
+  %tmp17 = icmp sgt i32 %arg2, %tmp16<br>
+  br label %bb18<br>
+<br>
+bb18:                                             ; preds = %bb14, %bb10, %bb<br>
+  %tmp19 = phi i32 [ 6, %bb10 ], [ 6, %bb ], [ %tmp16, %bb14 ]<br>
+  %tmp20 = xor i32 %tmp19, 2<br>
+  %tmp23 = sext i32 %tmp20 to i64<br>
+  %tmp24 = call i64 @llvm.expect.i64(i64 %tmp23, i64 4)<br>
+  %tmp25 = icmp ne i64 %tmp24, 0<br>
+  br i1 %tmp25, label %bb26, label %bb28<br>
+; CHECK: br i1 %tmp25,{{.*}}!prof [[WEIGHT]]<br>
+<br>
+bb26:                                             ; preds = %bb18<br>
+  %tmp27 = call i32 @goo()<br>
+  br label %bb30<br>
+<br>
+bb28:                                             ; preds = %bb18<br>
+  %tmp29 = call i32  @hoo()<br>
+  br label %bb30<br>
+<br>
+bb30:                                             ; preds = %bb28, %bb26<br>
+  ret void<br>
+}<br>
+<br>
+declare i32 @goo()<br>
+<br>
+declare i32 @hoo()<br>
+<br>
+declare i32 @too()<br>
+<br>
+declare i8 @too8()<br>
+<br>
+; Function Attrs: nounwind readnone<br>
+declare i64 @llvm.expect.i64(i64, i64)<br>
+<br>
+!llvm.ident = !{!0}<br>
+<br>
+!0 = !{!"clang version 5.0.0 (trunk 302965)"}<br>
+; CHECK: [[WEIGHT]] = !{!"branch_weights", i32 2000, i32 1}<br>
+; CHECK: [[WEIGHT2]] = !{!"branch_weights", i32 1, i32 2000}<br>
<br>
Added: llvm/trunk/test/Transforms/<wbr>LowerExpectIntrinsic/phi_or.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerExpectIntrinsic/phi_or.ll?rev=304517&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>Transforms/<wbr>LowerExpectIntrinsic/phi_or.<wbr>ll?rev=304517&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/Transforms/<wbr>LowerExpectIntrinsic/phi_or.ll (added)<br>
+++ llvm/trunk/test/Transforms/<wbr>LowerExpectIntrinsic/phi_or.ll Thu Jun  1 21:09:31 2017<br>
@@ -0,0 +1,103 @@<br>
+; RUN: opt -lower-expect  -S -o - < %s | FileCheck %s<br>
+; RUN: opt -S -passes='function(lower-<wbr>expect)' < %s | FileCheck %s<br>
+;<br>
+; if (__builtin_expect((x > goo() || y > hoo()), 1)) {<br>
+;  ..<br>
+; }<br>
+; For the above case, only the second branch should be<br>
+; annotated.<br>
+; if (__builtin_expect((x > goo() || y > hoo()), 0)) {<br>
+;  ..<br>
+; }<br>
+; For the above case, two branches should be annotated.<br>
+; Function Attrs: noinline nounwind uwtable<br>
+define void @foo(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3)  {<br>
+; CHECK-LABEL: void @foo<br>
+bb:<br>
+  %tmp8 = call i32 @goo()<br>
+  %tmp9 = icmp slt i32 %arg, %tmp8<br>
+  br i1 %tmp9, label %bb14, label %bb10<br>
+; CHECK: br i1 %tmp9<br>
+; CHECK-NOT: br i1 %tmp9{{.*}}!prof<br>
+<br>
+bb10:                                             ; preds = %bb<br>
+  %tmp12 = call i32  @hoo()<br>
+  %tmp13 = icmp sgt i32 %arg1, %tmp12<br>
+  br label %bb14<br>
+<br>
+bb14:                                             ; preds = %bb10, %bb<br>
+  %tmp15 = phi i1 [ true, %bb ], [ %tmp13, %bb10 ]<br>
+  %tmp16 = zext i1 %tmp15 to i32<br>
+  %tmp17 = sext i32 %tmp16 to i64<br>
+  %expect = call i64 @llvm.expect.i64(i64 %tmp17, i64 1)<br>
+  %tmp18 = icmp ne i64 %expect, 0<br>
+  br i1 %tmp18, label %bb19, label %bb21<br>
+; CHECK: br i1 %tmp18{{.*}}!prof [[WEIGHT:![0-9]+]]<br>
+<br>
+bb19:                                             ; preds = %bb14<br>
+  %tmp20 = call i32 @goo()<br>
+  br label %bb23<br>
+<br>
+bb21:                                             ; preds = %bb14<br>
+  %tmp22 = call i32  @hoo()<br>
+  br label %bb23<br>
+<br>
+bb23:                                             ; preds = %bb21, %bb19<br>
+  ret void<br>
+}<br>
+<br>
+define void @foo2(i32 %arg, i32 %arg1, i32 %arg2, i32 %arg3)  {<br>
+; CHECK-LABEL: void @foo2<br>
+bb:<br>
+  %tmp = alloca i32, align 4<br>
+  %tmp4 = alloca i32, align 4<br>
+  %tmp5 = alloca i32, align 4<br>
+  %tmp6 = alloca i32, align 4<br>
+  store i32 %arg, i32* %tmp, align 4<br>
+  store i32 %arg1, i32* %tmp4, align 4<br>
+  store i32 %arg2, i32* %tmp5, align 4<br>
+  store i32 %arg3, i32* %tmp6, align 4<br>
+  %tmp7 = load i32, i32* %tmp, align 4<br>
+  %tmp8 = call i32  @goo()<br>
+  %tmp9 = icmp slt i32 %tmp7, %tmp8<br>
+  br i1 %tmp9, label %bb14, label %bb10<br>
+; CHECK: br i1 %tmp9{{.*}}!prof [[WEIGHT2:![0-9]+]]<br>
+<br>
+bb10:                                             ; preds = %bb<br>
+  %tmp11 = load i32, i32* %tmp5, align 4<br>
+  %tmp12 = call i32 @hoo()<br>
+  %tmp13 = icmp sgt i32 %tmp11, %tmp12<br>
+  br label %bb14<br>
+<br>
+bb14:                                             ; preds = %bb10, %bb<br>
+  %tmp15 = phi i1 [ true, %bb ], [ %tmp13, %bb10 ]<br>
+  %tmp16 = zext i1 %tmp15 to i32<br>
+  %tmp17 = sext i32 %tmp16 to i64<br>
+  %expect = call i64 @llvm.expect.i64(i64 %tmp17, i64 0)<br>
+  %tmp18 = icmp ne i64 %expect, 0<br>
+  br i1 %tmp18, label %bb19, label %bb21<br>
+; CHECK: br i1 %tmp18{{.*}}!prof [[WEIGHT2]]<br>
+<br>
+bb19:                                             ; preds = %bb14<br>
+  %tmp20 = call i32 @goo()<br>
+  br label %bb23<br>
+<br>
+bb21:                                             ; preds = %bb14<br>
+  %tmp22 = call i32 @hoo()<br>
+  br label %bb23<br>
+<br>
+bb23:                                             ; preds = %bb21, %bb19<br>
+  ret void<br>
+}<br>
+<br>
+declare i32 @goo()<br>
+declare i32 @hoo()<br>
+declare i64 @llvm.expect.i64(i64, i64)<br>
+<br>
+<br>
+!llvm.ident = !{!0}<br>
+<br>
+<br>
+!0 = !{!"clang version 5.0.0 (trunk 302965)"}<br>
+; CHECK: [[WEIGHT]] = !{!"branch_weights", i32 2000, i32 1}<br>
+; CHECK: [[WEIGHT2]] = !{!"branch_weights", i32 1, i32 2000}<br>
<br>
Added: llvm/trunk/test/Transforms/<wbr>LowerExpectIntrinsic/phi_tern.<wbr>ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerExpectIntrinsic/phi_tern.ll?rev=304517&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>Transforms/<wbr>LowerExpectIntrinsic/phi_tern.<wbr>ll?rev=304517&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/Transforms/<wbr>LowerExpectIntrinsic/phi_tern.<wbr>ll (added)<br>
+++ llvm/trunk/test/Transforms/<wbr>LowerExpectIntrinsic/phi_tern.<wbr>ll Thu Jun  1 21:09:31 2017<br>
@@ -0,0 +1,56 @@<br>
+; RUN: opt -lower-expect  -S -o - < %s | FileCheck %s<br>
+; RUN: opt -S -passes='function(lower-<wbr>expect)' < %s | FileCheck %s<br>
+<br>
+; return __builtin_expect((a > b ? 1, goo(), 0);<br>
+;<br>
+; Function Attrs: noinline nounwind uwtable<br>
+define i32 @foo(i32 %arg, i32 %arg1)  {<br>
+; CHECK-LABEL: i32 @foo<br>
+bb:<br>
+  %tmp5 = icmp sgt i32 %arg, %arg1<br>
+  br i1 %tmp5, label %bb9, label %bb7<br>
+; CHECK: br i1 %tmp5{{.*}}!prof [[WEIGHT:![0-9]+]]<br>
+<br>
+bb7:                                              ; preds = %bb<br>
+  %tmp8 = call i32 @goo()<br>
+  br label %bb9<br>
+<br>
+bb9:                                              ; preds = %bb7, %bb9<br>
+  %tmp10 = phi i32 [ 1, %bb ], [ %tmp8, %bb7 ]<br>
+  %tmp11 = sext i32 %tmp10 to i64<br>
+  %expect = call i64 @llvm.expect.i64(i64 %tmp11, i64 0)<br>
+  %tmp12 = trunc i64 %expect to i32<br>
+  ret i32 %tmp12<br>
+}<br>
+<br>
+define i32 @foo2(i32 %arg, i32 %arg1)  {<br>
+bb:<br>
+  %tmp5 = icmp sgt i32 %arg, %arg1<br>
+  br i1 %tmp5, label %bb6, label %bb7<br>
+; CHECK: br i1 %tmp5{{.*}}!prof [[WEIGHT:![0-9]+]]<br>
+<br>
+bb6:                                              ; preds = %bb<br>
+  br label %bb9<br>
+<br>
+bb7:                                              ; preds = %bb<br>
+  %tmp8 = call i32 @goo()<br>
+  br label %bb9<br>
+<br>
+bb9:                                              ; preds = %bb7, %bb6<br>
+  %tmp10 = phi i32 [ 1, %bb6 ], [ %tmp8, %bb7 ]<br>
+  %tmp11 = sext i32 %tmp10 to i64<br>
+  %expect = call i64 @llvm.expect.i64(i64 %tmp11, i64 0)<br>
+  %tmp12 = trunc i64 %expect to i32<br>
+  ret i32 %tmp12<br>
+}<br>
+<br>
+declare i32 @goo()<br>
+declare i64 @llvm.expect.i64(i64, i64)<br>
+<br>
+<br>
+<br>
+!llvm.ident = !{!0}<br>
+<br>
+!0 = !{!"clang version 5.0.0 (trunk 302965)"}<br>
+<br>
+; CHECK: [[WEIGHT]] = !{!"branch_weights", i32 1, i32 2000}<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></div>