In ScalarEvolution::createAddRecFromPHIWithCastsImpl() with the added test we get to the cast below, and then throw an assert because the PHISCEV is not actually a SCEVAddRecExpr -- getAddRecExpr seems to have simplified it down to a constant -7.
const SCEV *PHISCEV = getAddRecExpr(getTruncateExpr(StartVal, TruncTy), getTruncateExpr(Accum, TruncTy), L, SCEV::FlagAnyWrap); const auto *AR = cast<SCEVAddRecExpr>(PHISCEV);
The test is:
define void @foo() { bb: br label %bb1 bb1: %tmp = phi i64 [ -7, %bb ], [ %tmp4, %bb1 ] %tmp2 = shl i64 %tmp, 32 %tmp3 = ashr exact i64 %tmp2, 32 %tmp4 = xor i64 %tmp3, -9223372036854775808 br i1 undef, label %bb5, label %bb1 bb5: unreachable }
With this test, we end up with the back-edge value (BEValueV) being the %tmp4 = xor... This strikes me as odd that we would try to reason about an 'add' that is actually an xor, so this patch bails out early if we identify that the back-edge value that we have is anything other than an add.
I'm not entirely sure this is the 100% correct way to approach this fix. I'm adding this patch as a starting point to figure out how to tackle this.
I think you've misdiagnosed the bug here. getSCEV is supposed to always return a SCEV for a value when requested. It may return SCEVUnknown, but that's still a valid SCEV. As such, the check for AddRec just below this should prevent the xor flowing through. I suspect you're actual issue is that getSCEV has return nullptr.
p.s. I suggest chatting with Max or Sanjoy to confirm everything I just said. I'm not SCEV expert.