This is an archive of the discontinued LLVM Phabricator instance.

[ValueLattice] Merging unknown with empty CR is unknown.
ClosedPublic

Authored by fhahn on Apr 22 2020, 1:36 PM.

Details

Summary

Currently an unknown/undef value is marked as overdefined when merged
with an empty range. An empty range can occur in unreachable/dead code.
When merging the new unknown state (= no value known yet) with an empty
range, there still isn't any information about the value yet and we can
stay in unknown.

This gives a few nice improvements on the number of instructions removed
by IPSCCP:
Same hash: 170 (filtered out)
Remaining: 67
Metric: sccp.IPNumInstRemoved

Program base patch diff
test-suite...rks/FreeBench/mason/mason.test 3.00 6.00 100.0%
test-suite...nchmarks/McCat/18-imp/imp.test 3.00 5.00 66.7%
test-suite...C/CFP2000/179.art/179.art.test 2.00 3.00 50.0%
test-suite...ijndael/security-rijndael.test 2.00 3.00 50.0%
test-suite...ks/Prolangs-C/agrep/agrep.test 40.00 58.00 45.0%
test-suite...ce/Applications/Burg/burg.test 26.00 37.00 42.3%
test-suite...cCat/03-testtrie/testtrie.test 3.00 4.00 33.3%
test-suite...Source/Benchmarks/sim/sim.test 29.00 36.00 24.1%
test-suite.../Applications/spiff/spiff.test 9.00 11.00 22.2%
test-suite...s/FreeBench/neural/neural.test 5.00 6.00 20.0%
test-suite...pplications/treecc/treecc.test 66.00 79.00 19.7%
test-suite...langs-C/football/football.test 85.00 101.00 18.8%
test-suite...ce/Benchmarks/PAQ8p/paq8p.test 90.00 105.00 16.7%
test-suite...oxyApps-C++/miniFE/miniFE.test 37.00 43.00 16.2%
test-suite...rks/FreeBench/pifft/pifft.test 26.00 30.00 15.4%
test-suite...lications/sqlite3/sqlite3.test 481.00 548.00 13.9%
test-suite...marks/7zip/7zip-benchmark.test 4875.00 5522.00 13.3%
test-suite.../CINT2000/176.gcc/176.gcc.test 1117.00 1197.00 7.2%
test-suite...0.perlbench/400.perlbench.test 1618.00 1732.00 7.0%

Diff Detail

Event Timeline

fhahn created this revision.Apr 22 2020, 1:36 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 22 2020, 1:36 PM
fhahn updated this revision to Diff 259379.Apr 22 2020, 1:38 PM

Rebased

nikic added inline comments.Apr 22 2020, 1:47 PM
llvm/include/llvm/Analysis/ValueLattice.h
361–362

Can't we do this for the isUndef() case as well, i.e. return false here unconditionally?

markConstantRange with an empty range should be equivalent to markUnknown (i.e. it shouldn't do anything at all).

(And if MayIncludeUndef is set, it's equivalent to markUndef().)

fhahn updated this revision to Diff 259410.Apr 22 2020, 2:51 PM

update getRange() to return either unknown or undef for empty ranges, depending on MayIncludeUndef. In markConstantRange, assert that only non-empty ranges are passed. I'll update the description accordinly

fhahn marked an inline comment as done.Apr 22 2020, 2:53 PM
fhahn added inline comments.
llvm/include/llvm/Analysis/ValueLattice.h
361–362

Can't we do this for the isUndef() case as well, i.e. return false here unconditionally?

I can't think of a reason now why not, but it seems like this has been there for a long time. Not sure if that is/was a LVI specific assumption in the original code. I've adjusted the code and now empty ranges should never reach markConstantRange.

(@efriedma I'll include the responses to your comments inline here, as they seem to fit with the context here)

markConstantRange with an empty range should be equivalent to markUnknown (i.e. it shouldn't do anything at all).

Eli, do you by any chance remember why the restriction was there in the first place? I agree, it seems like we should just treat empty set as if merging with unknown. I think the better fix would be to not create constantrange lattice values in the first place with empty ranges (needs a fix in getRange()).

(And if MayIncludeUndef is set, it's equivalent to markUndef().)

I tried to come up with cases where markUndef would be required for empty ranges but I couldn't, as the empty ranges should only occur in dead blocks. But I guess it is better to start out with being a bit more conservative.

nikic added inline comments.Apr 22 2020, 3:26 PM
llvm/include/llvm/Analysis/ValueLattice.h
361–362

One thing to keep in mind here is that empty range can occur not only if the block is dead, but also if immediate UB is triggered (I believe you'll get an empty set from udiv by zero) and if an instruction always returns poison (e.g. due to nowrap flags -- SCCP is probably not wired up to this part, but LVI is). I don't think this changes anything about the conclusion here though.

If the behavior here is changed, this comment in LVI should also be updated: https://github.com/llvm/llvm-project/blob/45526d29a5b2cf126b83ada3991921970007d16f/llvm/lib/Analysis/LazyValueInfo.cpp#L125-L127

fhahn updated this revision to Diff 259590.Apr 23 2020, 8:58 AM

If the behavior here is changed, this comment in LVI should also be updated: https://github.com/llvm/llvm-project/blob/45526d29a5b2cf126b83ada3991921970007d16f/llvm/lib/Analysis/LazyValueInfo.cpp#L125-L127

Thanks, removed the TODO and updated the note.

efriedma accepted this revision.Apr 23 2020, 3:01 PM

LGTM

llvm/include/llvm/Analysis/ValueLattice.h
361–362

Eli, do you by any chance remember why the restriction was there in the first place?

You mean, why we sent empty ranges to overdefined? No memory of this. Tried to dig a bit into blame, and I think it goes back to https://reviews.llvm.org/rL110388 .

This revision is now accepted and ready to land.Apr 23 2020, 3:01 PM
This revision was automatically updated to reflect the committed changes.