Currently handlePhiDef does not take the probability operand of expect_with_probability into consideration.
When the probability is low, meaning the "expected value" is unlikely, we need to mark the branches from which the phi value is the same as "expected value" as unlikely.
The existing code treats __builtin_expect((a0==1)||(a1==1)||(a2==1), 1) and __builtin_expect_with_probability((a0==1)||(a1==1)||(a2==1), 1, 0) the same, when in fact they are very different: They both "expect" value 1, but the first says it is very likely and the second says it has probability 0, i.e. very unlikely.
An example of IR code we need to handle is:
b0: %c0 = icmp eq i8 %a0, 1 br i1 %c0, label %b3, label %b1 b1: %c1 = icmp eq i8 %a1, 1 br i1 %c1, label %b3, label %b2 b2: %c2 = icmp eq i8 %a2, 1 br label %b3 b3: %cond0 = phi i1 [ true, %b0 ], [ true, %b1 ], [ %c2, %b2 ] %cond1 = extend %cond0 to i64 %expval = call i64 @llvm.expect.with.probability.i64(i64 %cond1, i64 1, double 0.0)
We should also annotate the BranchInst of b0 and b1 because we know that "true" is unlikely. The only path that does not result in an unlikely outcome is through b2.
This helps __builtin_expect(x, 0) and __builtin_expect_with_probability(x, 1, 0) have the same behavior. For reference, GCC does already behave consistently like this.
In addition, we also added an ImmArg attribute to the expect.with.probability intrinsic to disallow non-constant probability arguments.
This issue was introduced by https://reviews.llvm.org/D79830, which did not update handlePhiDef correctly for the expect.with.probability case.
This should probably be made more biased.