This is an archive of the discontinued LLVM Phabricator instance.

[SCEV] Ensure ScalarEvolution::createAddRecFromPHIWithCastsImpl is working with an add expression.
AbandonedPublic

Authored by dneilson on Aug 28 2017, 11:53 AM.

Details

Reviewers
sanjoy
reames
Summary

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.

Event Timeline

dneilson created this revision.Aug 28 2017, 11:53 AM
dneilson updated this revision to Diff 112935.Aug 28 2017, 12:10 PM
  • Add 'RUN' line to test.
reames requested changes to this revision.Aug 28 2017, 1:32 PM
reames added a subscriber: reames.
reames added inline comments.
lib/Analysis/ScalarEvolution.cpp
4387

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.

This revision now requires changes to proceed.Aug 28 2017, 1:32 PM
dneilson added inline comments.Aug 28 2017, 1:40 PM
lib/Analysis/ScalarEvolution.cpp
4387

That doesn't mesh with what I was seeing here. What I was seeing with the added test case is that we get all the way down to line 4479, and blow up there. PHISCEV appears to be a constant value of -7 rather than any sort of AddRec, so the cast on that line ends up failing.

When I dump the intermediate values I find that BEValueV is the xor in the loop (%tmp4 = xor i64 %tmp3, -9223372036854775808). This method seems to be written assuming that BEValueV is an add operator -- the RHS is even cast to a SCEVAddExpr on line 4392. It seems pretty clear that an SCEVAddRec is for the addition operator, and constructing one from any other operator is just asking for trouble; hence the patch as written...

Also, the if directly before this one returns 'None' to signify an early bail-out, so it seems to me that's the expected behaviour of this method.

dneilson edited the summary of this revision. (Show Details)Aug 28 2017, 2:11 PM

Got some more info... changing the xor into an add in the test also results in the same assert firing. So, more digging needed.

dneilson abandoned this revision.Aug 29 2017, 6:27 AM