397 Commits

Author SHA1 Message Date
Andreas Jonson
d4cd65ecf2
[LVI] Handle range attributes (#86413)
This adds handling of range attribute for return values of Call and
Invoke in getFromRangeMetadata and handling of argument with range
attribute in solveBlockValueNonLocal.
There is one additional check of the range metadata at line 1120 in
getValueFromSimpleICmpCondition that is not covered in this PR as after
https://github.com/llvm/llvm-project/pull/75311 there is no test that
cover that check any more and I have not been able to create a test that
trigger that code.
2024-04-04 14:48:11 +08:00
Noah Goldstein
0e78655731 [LVI] Use m_AddLike instead of m_Add when matching simple condition
We have more complete logic for handling `Add`, so try to use that
logic for `or disjoint` (which can definitionally be treated as
`add`).

Closes #86058
2024-03-28 13:49:05 -05:00
Antonio Frighetto
5620542e4d [IR] Add getNoWrapKind method for OverflowingBinaryOperator (NFC) 2024-03-08 17:00:58 +01:00
Nikita Popov
ef87e6643e [LVI] Assert that only one value is pushed (NFC) 2024-01-10 10:29:45 +01:00
Nikita Popov
a3e8e86fb6 [LVI] Don't push both sides of and/or at once
Same as the change in d5db2cdb22ab302acbb6e1a066e791f25dc612de,
but for condition handling. The same issue could occur here as well.
2024-01-02 11:28:48 +01:00
Nikita Popov
d5db2cdb22 [LVI] Don't push both binop operands at once
If one of the binop operands depends on the other, this may end
up evaluating them in the wrong order, producing sub-optimal
results.

Make sure that only one unevaluated operand gets pushed per
iteration.

Fixes https://github.com/llvm/llvm-project/issues/76705.
2024-01-02 11:24:47 +01:00
Nikita Popov
734ee0e01f
[LVI] Support using block values when handling conditions (#75311)
Currently, LVI will only use conditions like "X < C" to constrain the
value of X on the relevant edge. This patch extends it to handle
conditions like "X < Y" by querying the known range of Y.

This means that getValueFromCondition() and various related APIs can now
return nullopt to indicate that they have pushed to the worklist, and
need to be called again later. This behavior is currently controlled by
a UseBlockValue option, and only enabled for actual edge value handling.
All other places deriving constraints from conditions keep using the
previous logic for now.

This change was originally motivated as a fix for the regression
reported in
https://github.com/llvm/llvm-project/pull/73662#issuecomment-1849281758.
Unfortunately, it doesn't actually fix it, because we run into another
issue there (LVI currently is really bad at handling values used in
loops).

This change has some compile-time impact, but it's fairly small,
in the 0.05% range.
2024-01-02 10:49:45 +01:00
Nikita Popov
0d3d445223 [LVI] Remove unnecessary TLI dependency
Only used in ConstantFoldCompareInstOperands(), which does not
actually use TLI.
2023-12-19 14:32:43 +01:00
Nikita Popov
1f5ee80789 [LVI] Don't return optional from getEdgeValueLocal() (NFC)
The general convention inside LVI is that std::nullopt means that
a value has been pushed to the worklist. However, getEdgeValueLocal()
used it as an additional spelling for getOverdefined() instead.
2023-12-12 15:32:26 +01:00
Nikita Popov
7de592b9f9 [LVI] Move bulk of getConstantRangeAtUse() implementation into Impl (NFC)
Make the layering here similar to all the other methods:
LazyValueInfoImpl implements the underlying API returning a
ValueLatticeElement, and then LazyValueInfo exposes this as a
ConstantRange publicly.
2023-12-12 15:27:00 +01:00
Nikita Popov
edcc7fe9aa [LVI] Reuse LatticeValue to ConstantRange conversion more
Use the helper in the getConstantRange() and
getConstantRangeAtUse() APIs as well. For that purpose move the
handling of isUnknown() into the helper as well.
2023-12-12 14:42:24 +01:00
Nikita Popov
bfebadc8c3 [LVI] Don't require DataLayout in getConstantRangeOrFull() (NFC)
We're only working on integers here, so we don't need DataLayout
to determine the width.
2023-12-12 14:29:08 +01:00
Nikita Popov
0c2b6a0225 [LVI] Drop bitcast handling (NFCI)
The code only works on integer casts, and the only bitcasts
involving integers are trivial. The code as previously written
would try to handle things like float to integer bitcasts by
fetching a ConstantRange of a float value, which is an ill-defined
operation.
2023-12-12 13:09:51 +01:00
Nikita Popov
516e34d98a [LVI] Switch getValueFromCondition() to use recursion
The current implementation using a worklist and visited map adds
a significant amount of additional complexity and compile-time
overhead. All we really care about here is that we don't overflow
the stack or cause exponential complexity in degenerate cases. We
can achieve this with a simple depth limit.
2023-12-12 10:55:10 +01:00
Nikita Popov
4275da2278 [ValueTracking] Add isGuaranteedNotToBeUndef() variant (NFC)
We have a bunch of places where we have to guard against undef
to avoid multi-use issues, but would be fine with poison. Use a
different function for these to make it clear, and to indicate that
this check can be removed once we no longer support undef. I've
replaced some of the obvious cases, but there's probably more.

For now, the implementation is the same as UndefOrPoison, it just
has a more precise name.
2023-12-04 12:04:41 +01:00
Aiden Grossman
0bdb9cb1ea
[NewPM] Remove LazyValueInfoPrinter Pass (#73408)
This pass isn't used anywhere upstream and thus has no test coverage.
For these reasons, remove it.
2023-11-27 15:09:18 -08:00
Aiden Grossman
5a74805bd6
[LVI] Add NewPM printer pass (#73425)
This patch adds a NewPM printer pass for the LazyValueAnalysis.
2023-11-26 12:20:49 -08:00
Amara Emerson
9189822f2c
[LVI] Handle icmp of ashr. (#68010)
This handles the case where this combine:
icmp sgt (ashr X, ShAmtC), C --> icmp sgt X, ((C + 1) << ShAmtC) - 1

wasn't performed by instcombine.

Proof of the original combine: https://alive2.llvm.org/ce/z/SfpsvX

This is a port of the review in https://reviews.llvm.org/D151911 to
GitHub.
2023-10-20 11:16:05 -07:00
DianQK
81857940f2
[LVI][CVP] Treat undef like a full range (#68190)
When converting to ConstantRange, we should treat undef like a full range.
Fixes #68381.
2023-10-10 16:03:24 +08:00
Mikael Holmen
ee1a06b80f [Analysis] Fix gcc warnings about unused variables [NFC]
gcc warned with:
 [236/4788] Building CXX object lib/Analysis/CMakeFiles/LLVMAnalysis.dir/LazyValueInfo.cpp.o
 ../lib/Analysis/LazyValueInfo.cpp: In member function 'void llvm::LazyValueInfo::forgetValue(llvm::Value*)':
 ../lib/Analysis/LazyValueInfo.cpp:1978:13: warning: unused variable 'Impl' [-Wunused-variable]
  1978 |   if (auto *Impl = getImpl())
       |             ^~~~
 ../lib/Analysis/LazyValueInfo.cpp: In member function 'void llvm::LazyValueInfo::eraseBlock(llvm::BasicBlock*)':
 ../lib/Analysis/LazyValueInfo.cpp:1983:13: warning: unused variable 'Impl' [-Wunused-variable]
  1983 |   if (auto *Impl = getImpl())
       |             ^~~~
 ../lib/Analysis/LazyValueInfo.cpp: In member function 'void llvm::LazyValueInfo::clear()':
 ../lib/Analysis/LazyValueInfo.cpp:1988:13: warning: unused variable 'Impl' [-Wunused-variable]
  1988 |   if (auto *Impl = getImpl())
       |             ^~~~
 ../lib/Analysis/LazyValueInfo.cpp: In member function 'void llvm::LazyValueInfo::printLVI(llvm::Function&, llvm::DominatorTree&, llvm::raw_ostream&)':
 ../lib/Analysis/LazyValueInfo.cpp:1993:13: warning: unused variable 'Impl' [-Wunused-variable]
  1993 |   if (auto *Impl = getImpl())
       |             ^~~~

Use the locals instead of calling getImpl() again.
2023-09-29 11:25:36 +02:00
DianQK
7af408e89b
[JumpThreading][NFC] Improved access to LazyValueInfoImpl. 2023-09-04 11:50:14 +08:00
DianQK
7ded71b1e4
[JumpThreading] Invalidate LVI after combineMetadataForCSE. 2023-09-04 11:50:14 +08:00
Nikita Popov
781beb3de5 [LVI] Check ConstantFoldCompareInstOperands() failure (NFCI)
I don't believe this can happen right now (because we're only
working on icmps and as such can't hit the current fcmp null
paths), but this will be possible in the future when icmp
constant expressions are removed.
2023-07-20 14:51:03 +02:00
luxufan
82082b7da0 [LVI] Don't compute range on not guaranteed not to be undef condition in SelectInst
Fixes:https://github.com/llvm/llvm-project/issues/62901

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D151295
2023-05-24 16:02:13 +08:00
Kazu Hirata
1ca0cb717a [llvm] Replace None with std::nullopt in comments (NFC)
This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2023-04-25 23:53:32 -07:00
luxufan
1da0da903e [LVI][CVP] Don't compute CR at SelectInst Use if Cond value may not be well-defined
If the condition value of SelectInst may be a poison or undef value,
infer constant range at SelectInst use is in correct.

See https://alive2.llvm.org/ce/z/MWMTYn

Fixes: https://github.com/llvm/llvm-project/issues/62200

Differential Revision: https://reviews.llvm.org/D148709
2023-04-22 12:54:49 +08:00
Kazu Hirata
f8f3db2756 Use APInt::count{l,r}_{zero,one} (NFC) 2023-02-19 22:04:47 -08:00
Nikita Popov
bfbfbd8b65 [LVI] Fix and re-enable at-use reasoning (PR60629)
This fixes the handling of phi nodes in getConstantRangeAtUse()
and re-enables it, reverting the workaround from
c77c186a647b385c291ddabecd70a2b4f84ae342.

For phi nodes, while we can make use of the edge condition for the
incoming value, we shouldn't look past the phi node to look for
further conditions, because we might be reasoning about values
from two different cycle iterations (which will have the same
SSA value).

To handle this more specifically we would have to detect cycles,
and there doesn't seem to be any motivating case for that at this
point.
2023-02-14 15:56:39 +01:00
Dmitry Makogon
c77c186a64 [LVI] Don't traverse uses when calculating range at use
This effectively reverts 5c38c6a and 4f772b0.

A recently introduced LazyValueInfo::getConstantRangeAtUse returns incorrect
ranges for values in certain cases. One such example is described in PR60629.
The issue has something to do with traversing PHI uses of a value transitively.
As nikic pointed out, we're effectively reasoning about values from different
loop iterations.

In the faulting test case, CVP made a miscompilation because the calculated
range for a shift argument was incorrect. It returned empty-set, however it is
clearly not a dead code. CVP then erased the shift instruction because
of empty range.
2023-02-10 17:06:36 +07:00
Nikita Popov
2e9bc1b861 [LVI] Use !range metadata for supported intrinsics
Even if the intrinsic is supported by ConstantRange, we should
still make use of !range metadata. This doesn't matter much now,
but is important if we want to support ctlz style intrinsics,
which always have KnownBits-based !range metadata attached, which
might be better than what we can compute using ranges.
2023-01-26 15:09:48 +01:00
Nikita Popov
0a4d3eae33 [LVI] Check for non-speculatable instructions
When constraining an operand based on a condition at a (potentially
transitive) use site, make sure we don't skip over non-speculatable
instructions. While the result is only used under the condition,
the non-speculatable instruction may have a side-effect or UB.

Demonstrating this issue requires raising the limit on the walk,
so do that.
2023-01-13 16:10:12 +01:00
Nikita Popov
4f772b0955 [LVI][CVP] Make use of condition known at use
When an instruction is only used in a select or phi operand, we might
be able to make use of additional information from the select/branch
condition. For example in

  %sub = call i16 @llvm.usub.sat.i16(i16 %x, i16 10)
  %cmp = icmp uge i16 %x, 10
  %sel = select i1 %cmp, i16 %sub, i16 42

the usub.sat is only used in a select where %x uge 10 is known to
hold, so we can fold it based on that knowledge.

This addresses the regression reported at
https://reviews.llvm.org/D140798#4039748, but also provides a
solution to a recurring problem we've had, where we fail to make
use of range information after a branch+phi has been converted
into a select. Our current solution to this is to hope that IPSCCP
can perform the fold before that happens, but handling this in LVI
is a somewhat more general solution.

Currently we only make use of this for the willNotOverflow() fold,
but I plan to adjust other folds to use the new API as well.

Differential Revision: https://reviews.llvm.org/D141482
2023-01-12 16:41:31 +01:00
Keno Fischer
1436a9232b [LVI] Look through negations when evaluating conditions
This teaches LVI (and thus CVP) to extract range information
from branches whose condition is negated using (`xor %c, true`).
On the implementation side, we switch the cache to additionally
track whether we're looking for the inverted value or not and
otherwise using the existing support for computing inverted
conditions.

I think the biggest question here is why this negation shows up
here at all. After all, it should always be possible for some
other pass to fold such a negation into a branch, comparison or
some other logical operation. Indeed, instcombine does just that.
However, these negations can be otherwise fairly persistent, e.g.
instsimplify is not able to exchange branch conditions from
negations. In addition, jumpthreading, which sits at the same
point in default pass pipeline also handles this pattern, which
adds further evidence that we might expect these negations to
not have been canonicalized away yet at this point in the pass
pipeline.

In the particular case I was looking at there was a bit of a
circular dependency where flags computed by cvp were needed
by instcombine, and incstombine's folding of the negation was
needed for cvp. Adding a second instombine pass would have
worked of course, but instcombine can be somewhat expensive,
so it appeared desirable to not require it to have run
before cvp (as is the case in the default pass pipeline).

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D140933
2023-01-05 23:03:46 +00:00
Fangrui Song
2fa744e631 std::optional::value => operator*/operator->
value() has undesired exception checking semantics and calls
__throw_bad_optional_access in libc++. Moreover, the API is unavailable without
_LIBCPP_NO_EXCEPTIONS on older Mach-O platforms (see
_LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS).

This commit fixes LLVMAnalysis and its dependencies.
2022-12-16 22:44:08 +00:00
Kazu Hirata
6eb0b0a045 Don't include Optional.h
These files no longer use llvm::Optional.
2022-12-14 21:16:22 -08:00
Fangrui Song
d4b6fcb32e [Analysis] llvm::Optional => std::optional 2022-12-14 07:32:24 +00:00
Kazu Hirata
e275faa5fe [Analysis] Use std::optional in LazyValueInfo.cpp (NFC)
This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-11 01:18:36 -08:00
Kazu Hirata
19aff0f37d [Analysis] Use std::nullopt instead of None (NFC)
This patch mechanically replaces None with std::nullopt where the
compiler would warn if None were deprecated.  The intent is to reduce
the amount of manual work required in migrating from Optional to
std::optional.

This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-02 19:43:04 -08:00
Kazu Hirata
eb0b5a36be [Analysis] Use std::optional in LazyValueInfo.cpp (NFC)
This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-11-25 10:25:36 -08:00
Nikita Popov
2f211f865d [LVI] Improve debug message (NFC) 2022-11-04 16:58:02 +01:00
Nikita Popov
68b24c3b44 [CVP] Simplify comparisons without constant operand
CVP currently only tries to simplify comparisons if there is a
constant operand. However, even if both are non-constant, we may
be able to determine the result of the comparison based on range
information.

IPSCCP is already capable of doing this, but because it runs very
early, it may miss some cases.

Differential Revision: https://reviews.llvm.org/D137253
2022-11-03 15:35:27 +01:00
Kazu Hirata
601b3a13de [Analysis] Qualify auto variables in for loops (NFC) 2022-07-16 23:26:34 -07:00
Kazu Hirata
611ffcf4e4 [llvm] Use value instead of getValue (NFC) 2022-07-13 23:11:56 -07:00
Kazu Hirata
a7938c74f1 [llvm] Don't use Optional::hasValue (NFC)
This patch replaces Optional::hasValue with the implicit cast to bool
in conditionals only.
2022-06-25 21:42:52 -07:00
Kazu Hirata
3b7c3a654c Revert "Don't use Optional::hasValue (NFC)"
This reverts commit aa8feeefd3ac6c78ee8f67bf033976fc7d68bc6d.
2022-06-25 11:56:50 -07:00
Kazu Hirata
aa8feeefd3 Don't use Optional::hasValue (NFC) 2022-06-25 11:55:57 -07:00
Kazu Hirata
7a47ee51a1 [llvm] Don't use Optional::getValue (NFC) 2022-06-20 22:45:45 -07:00
Kazu Hirata
e0e687a615 [llvm] Don't use Optional::hasValue (NFC) 2022-06-20 10:38:12 -07:00
Kazu Hirata
129b531c9c [llvm] Use value_or instead of getValueOr (NFC) 2022-06-18 23:07:11 -07:00
Simon Moll
b8c2781ff6 [NFC] format InstructionSimplify & lowerCaseFunctionNames
Clang-format InstructionSimplify and convert all "FunctionName"s to
"functionName".  This patch does touch a lot of files but gets done with
the cleanup of InstructionSimplify in one commit.

This is the alternative to the less invasive clang-format only patch: D126783

Reviewed By: spatel, rengolin

Differential Revision: https://reviews.llvm.org/D126889
2022-06-09 16:10:08 +02:00