This is an archive of the discontinued LLVM Phabricator instance.

[InstSimplify] Fold X {lshr,udiv} C <u X --> true for nonzero X, non-identity C
ClosedPublic

Authored by erikdesjardins on Nov 19 2021, 1:20 PM.

Details

Summary

This eliminates the bounds check in Rust code like

pub fn mid(data: &[i32]) -> i32 {
  if data.is_empty() { return 0; }
  return data[data.len()/2];
}

(from https://blog.sigplan.org/2021/11/18/undefined-behavior-deserves-a-better-reputation/)

Alive proofs:
lshr https://alive2.llvm.org/ce/z/nyTu8D
udiv https://alive2.llvm.org/ce/z/CNUZH7

Diff Detail

Event Timeline

erikdesjardins created this revision.Nov 19 2021, 1:20 PM
erikdesjardins requested review of this revision.Nov 19 2021, 1:20 PM
Herald added a project: Restricted Project. · View Herald TranscriptNov 19 2021, 1:20 PM
erikdesjardins edited the summary of this revision. (Show Details)

tweak summary formatting

spatel added inline comments.Nov 22 2021, 10:51 AM
llvm/lib/Analysis/InstructionSimplify.cpp
2977–2978

Spell out the other preds/patterns for completeness? Might want to improve the comments on the block above here while we're at it to show the transform instead of just matched pattern.

2979

Is that TODO feasible? The lshr half could use isKnownNonZero, but how would we deal with ">1" for udiv?

llvm/test/Transforms/InstSimplify/compare.ll
580–581

Put the predicate in the test name rather than incrementing the '1' suffix. That makes it clearer that we're cycling through the preds. Add a couple of negative tests for signed preds?

erikdesjardins edited the summary of this revision. (Show Details)

make comments more explicit about matched patterns
use more general C != 0 and C != 1 instead of C >u 0 and C >u 1 respectively

erikdesjardins marked an inline comment as not done.Nov 23 2021, 4:45 PM
erikdesjardins added inline comments.
llvm/lib/Analysis/InstructionSimplify.cpp
2979

I think something like

KnownBits Known = computeKnownBits(Divisor, ...);
if (KnownBits::ne(Known, KnownBits::makeConstant(1)))

would technically work.

I don't know if this would help much in practice though; I can remove "divisor" from the comment if you prefer.

spatel accepted this revision.Nov 24 2021, 6:12 AM

LGTM

llvm/lib/Analysis/InstructionSimplify.cpp
2963–2966

Nit: here and below, we're using "u" or "udiv" to make the unsigned requirements explicit, but we're using the ambiguous ">>" for the shift op.
Better to make that ">>u" or spell out "lshr"?

2979

It's fine to leave it. I was just wondering how we'd do that. :)
There's also a question of whether it's worth the compile-time, but these patterns are probably rare enough that it is ok (assuming it would fire on real code enough times to make a difference).

This revision is now accepted and ready to land.Nov 24 2021, 6:12 AM

use >>u to make shift type explicit

Thanks!

I don't have write access, please commit this (and tests in parent revision https://reviews.llvm.org/D114280) on my behalf: Erik Desjardins <erikdesjardinspublic@gmail.com>