This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Fix negative GEP offset evaluation for 32-bit pointers
ClosedPublic

Authored by nikic on Dec 7 2018, 11:59 AM.

Details

Summary

This fixes https://bugs.llvm.org/show_bug.cgi?id=39908.

The evaluateGEPOffsetExpression() function simplifies GEP offsets for use in comparisons against zero, basically by converting X*Scale+Offset==0 to X+Offset/Scale==0 if Scale divides Offset. However, before this is done, Offset is masked down to the pointer size. This results in incorrect results for negative Offsets, because we basically end up dividing the 32-bit offset *zero* extended to 64-bit bits (rather than sign extended).

The masking code could be fixed to properly replicate sign bits. However, as we are operating on inbounds GEPs here, I would expect that we do not have to care about address space overflows, because these would result in poison anyway. If that understanding is correct, then we can just drop this code entirely, which is what this patch does.

Diff Detail

Event Timeline

nikic created this revision.Dec 7 2018, 11:59 AM
mati865 added a subscriber: mati865.Dec 8 2018, 3:44 AM

I think I would rather SignExtend64(X, 32) or something like that... yes, it's effectively the same for well-defined code, but I'd rather explicitly truncate the offset rather than implicitly truncate it in ConstantInt::get.

I think I would rather SignExtend64(X, 32) or something like that... yes, it's effectively the same for well-defined code, but I'd rather explicitly truncate the offset rather than implicitly truncate it in ConstantInt::get.

Another possibility would be to not apply the simplification if the offsets are too large, i.e. make isIntN(IntPtrWidth, Offset) && isIntN(IntPtrWidth, VariableScale) a precondition for this transform. What do you think?

Checking for overflow would also be fine, but I think you would want to check overflow on each operation that modifies the offset, as opposed to the final result (which might have overflowed the 64-bit integer anyway).

nikic updated this revision to Diff 177908.Dec 12 2018, 1:52 PM

Use SignExtend64 for a signed truncation.

nikic added a comment.Dec 12 2018, 1:55 PM

I went with the SignExtend64 approach you suggested. Looking at the code directly above (for the zero offset case), it even explicitly inserts a truncate into IR, so it seems appropriate to just follow suit.

This revision is now accepted and ready to land.Dec 12 2018, 2:19 PM
This revision was automatically updated to reflect the committed changes.