432 Commits

Author SHA1 Message Date
Andreas Jonson
0561ff6a12
[LVI] Add support for trunc nuw range. (#154021)
Proof: https://alive2.llvm.org/ce/z/a5Yjb8
2025-08-17 20:24:09 +02:00
Kazu Hirata
25d7fd35b2
[Analysis] Remove unnecessary casts (NFC) (#146216)
PImpl is already of LazyValueInfoImpl *.
2025-06-28 13:03:31 -07:00
Yingwei Zheng
830cf36bd4
[LVI][ValueTracking] Take UB-implying attributes into account in isSafeToSpeculativelyExecute (#137604)
Closes https://github.com/llvm/llvm-project/issues/137582.

In the original case, LVI uses the edge information in `%entry ->
%if.end` to get a more precise result. However, since the call to `smin`
has an `noundef` return attribute, an immediate UB will be triggered
after optimization.

Currently, `isSafeToSpeculativelyExecuteWithOpcode(%min)` returns true
because
6a288c1e32
only checks whether the function is speculatable. However, it is not
enough in this case.

This patch takes UB-implying attributes into account if
`IgnoreUBImplyingAttrs` is set to false. If it is set to true, the
caller is responsible for correctly propagating UB-implying attributes.
2025-04-30 11:53:38 +08:00
Rahul Joshi
99e4b3927c
[LLVM] Cleanup pass initialization for Analysis passes (#135858)
- Do not call pass initialization from pass constructors.
- Instead, pass initialization should happen in the `initializeAnalysis`
function.
- https://github.com/llvm/llvm-project/issues/111767
2025-04-21 12:36:34 -07:00
Yingwei Zheng
2071ea24a2
[LVI] Skip self loops in solveBlockValueNonLocal (#127763)
We cannot infer more information from backedges in
`solveBlockValueNonLocal`. However, since DT is unavailable in LVI,
there is not a precise way to check whether a BB edge is a backedge.
This patch only skips self loops to unblock the range analysis.

The motivating case is extracted from
https://github.com/llvm/llvm-project/pull/127663.

Compile-time impact is high:
https://llvm-compile-time-tracker.com/compare.php?from=84ddda58c870681dd12ed765e9d59d5e00567f94&to=af032f1351358f2f5b5d9f4e87c5601c23b9bd37&stat=instructions:u
2025-02-23 17:52:38 +08:00
Yingwei Zheng
f17b9dde7a
[LVI] Handle nonnull attributes at callsite (#125377)
This patch is the followup of
https://github.com/llvm/llvm-project/pull/124908.
2025-02-03 10:22:38 +08:00
Andreas Jonson
8aebcebd90
[LVI] Add trunc to i1 handling. (#124480)
Proof: https://alive2.llvm.org/ce/z/yPrRp-
2025-02-02 19:45:50 +01:00
Stephen Senran Zhang
af656a8d42
[LVI] Learn value ranges from ctpop results (#121945)
Fixes #115751.
2025-01-15 09:53:31 +01:00
Yingwei Zheng
eaa1b05c48
[LVI] Thread binop over select with constant arms (#110212)
Motivating case from https://github.com/delta-io/delta-rs:
https://alive2.llvm.org/ce/z/3mzr4C
2024-12-09 12:56:19 +08:00
Nikita Popov
7a7a426188 [LVI] Fix insertelement of constexpr
Bail out when evaluating an insertelement of a constant expression.
Unlike other ValueLattice kinds, these don't have implicit splat
semantics and we end up with type mismatches. If we actually wanted
to handle these, we should actually evaluate the insertion via
constant folding. I'm not bothering with that, as these should
get constant folded on construction already.
2024-12-02 10:21:09 +01:00
Yingwei Zheng
c89d731c5d
[LVI] Infer non-zero from equality icmp (#112838)
This following pattern is common in loop headers:
```
  %101 = sub nuw i64 %78, %98
  %103 = icmp eq i64 %78, %98
  br i1 %103, label %.thread.i.i, label %.preheader.preheader.i.i

.preheader.preheader.i.i:
  %invariant.umin.i.i = call i64 @llvm.umin.i64(i64 %101, i64 9)
  %umax.i = call i64 @llvm.umax.i64(i64 %invariant.umin.i.i, i64 1)
  br label %.preheader.i.i

.preheader.i.i:
  ...
  %116 = add nuw nsw i64 %.011.i.i, 1
  %exitcond.not.i = icmp eq i64 %116, %umax.i
  br i1 %exitcond.not.i, label %.critedge.i.i, label %.preheader.i.i
```
As `%78` is not equal to `%98` in BB `.preheader.preheader.i.i`, we can
prove `%101` is non-zero. Then we can simplify the loop exit condition.

Addresses regression introduced by
https://github.com/llvm/llvm-project/pull/112742.
2024-10-18 21:19:02 +08:00
Rahul Joshi
6924fc0326
[LLVM] Add Intrinsic::getDeclarationIfExists (#112428)
Add `Intrinsic::getDeclarationIfExists` to lookup an existing
declaration of an intrinsic in a `Module`.
2024-10-16 07:21:10 -07:00
Nikita Popov
dc6876fc98
[ValueTracking] Use isSafeToSpeculativelyExecuteWithVariableReplaced() in more places (#109149)
This replaces some uses of isSafeToSpeculativelyExecute() with
isSafeToSpeculativelyExecuteWithVariableReplaced(), in cases where we
are guarding against operand changes rather plain speculation.

I believe that this is NFC with the current implementation of the
function (as it only does something different from loads), but this
makes us more defensive against future generalizations.
2024-09-19 09:38:20 +02:00
Nikita Popov
a5b6068446 [ValueLattice] Move intersect from LVI into ValueLattice API (NFC)
So we can reuse the logic inside IPSCCP.
2024-08-28 15:18:31 +02:00
Kazu Hirata
08acc3f73b
[Analysis] Copy-construct SmallVector (NFC) (#105911) 2024-08-24 07:13:42 -07:00
Thomas Fransham
8345289ded
[LLVM] Fix missing includes for function declarations that will be needed for explicit symbol visibility (#103900)
In multiple source files function definitions never sees there
declaration in a header because its never included causing linker errors
when explicit symbol visibility macros\dllexport are added to the
declarations.

Most of these were originally found by @tstellar in
https://github.com/llvm/llvm-project/pull/67502

TargetRegistry.h is needed in MCExternalSymbolizer.cpp for
createMCSymbolizer
Analysis/Passes.h is needed in LazyValueInfo.cpp and RegionInfo.cpp for
createLazyValueInfoPassin and createRegionInfoPass
Transforms/Scalar.h is needed in SpeculativeExecution.cpp for
createSpeculativeExecutionPass
2024-08-14 17:57:47 +02:00
Piotr Fusik
60a7d33106
[LVI][NFC] Delete an outdated comment (#101504)
Transitioned from inheritance to has-a relationship in 9db7948e
2024-08-02 07:48:54 +02:00
Rajat Bajpai
90668d2404
[CVP][LVI] Add support for InsertElementInst in LVI (#99368)
Currently, the LVI analysis pass doesn't support InsertElementInst
vector instruction. Due to this, some optimization opportunities are
missed. For example, in the below example, ICMP instruction can be
folded but it doesn't.

```
...
%ie1 = insertelement <2 x i32> poison, i32 10, i64 0
%ie2 = insertelement <2 x i32> %ie1, i32 20, i64 1
%icmp = icmp <2 x i1> %ie2, <i32 40, i32 40>
...
```

This change adds InsertElementInst support in the LVI analysis pass to
fix the motivating example.
2024-07-19 08:46:41 +02:00
Nikita Popov
9b754675d3 [ValueLattice] Add asConstantRange() helper (NFC)
Move the toConstantRange() helper from LVI into ValueLattice,
so it can be reused in other places like SCCP.
2024-07-08 10:49:15 +02:00
Nikita Popov
130f0f526d [LVI][CVP] Add support for vector comparisons 2024-07-05 17:02:03 +02:00
Nikita Popov
d177a94fbd [IR] Add Constant::toConstantRange() (NFC)
The logic in llvm::getVectorConstantRange() can be a bit
inconvenient to use in some cases because of the need to handle
the scalar case separately. Generalize it to handle all constants,
and move it to live directly on Constant.
2024-07-05 16:51:49 +02:00
Nikita Popov
79d6f52c4f [LVI] Use Constant instead of Tristate for predicate results
A lot of the users just end up converting it into a Constant
themselves. Doing this in the API leaves less room for error
with vector types, and brings getPredicateResult() closer to
LatticeValueElement::getCompare(), hopefully allowing us to
consolidate them.
2024-07-04 17:28:09 +02:00
Nikita Popov
a2ed21648c [LVI] Simplify the getPredicateResult() implementation (NFC)
By using ConstantRange::icmp().
2024-07-04 09:17:54 +02:00
goldsteinn
899fe2cf31
[CVP][LVI] Fix incorrect scalar type when getting constant folded vec (#97682)
Fixes #97674

After #97428 added support for vectors, our constant ranges can now be
from splat vectors so when they reduce to a singe constant value, we
need to return the original type as opposed to just an int.
2024-07-04 15:14:39 +08:00
Nikita Popov
c1004cad4b [LVI] Use CmpInst::Predicate in APIs (NFC)
Unfortunately this requires including InstrTypes.h in the header,
but I think that's fine given that that LazyValueInfo.h is not
widely used.
2024-07-03 15:26:57 +02:00
Nikita Popov
2dbb454791 [ValueTracking][LVI] Consolidate vector constant range calculation
Add a common helper used for computeConstantRange() and LVI. The
implementation is a mix of both, with the efficient handling for
ConstantDataVector taken from computeConstantRange(), and the
general handling (including non-splat poison) from LVI.
2024-07-03 15:19:26 +02:00
Nikita Popov
1eec81a831
[CVP][LVI] Add support for vectors (#97428)
The core change here is to add support for converting vector constants
into constant ranges. The rest is just relaxing isIntegerTy() checks and
making sure we don't use APIs that assume vectors.

There are a couple of places that don't support vectors yet, most
notably the "simplest" fold (comparisons to a constant) isn't supported
yet. I'll leave these to a followup.
2024-07-03 12:41:49 +02:00
Nikita Popov
4169338e75
[IR] Don't include Module.h in Analysis.h (NFC) (#97023)
Replace it with a forward declaration instead. Analysis.h is pulled in
by all passes, but not all passes need to access the module.
2024-06-28 14:30:47 +02:00
Nikita Popov
9df71d7673
[IR] Add getDataLayout() helpers to Function and GlobalValue (#96919)
Similar to https://github.com/llvm/llvm-project/pull/96902, this adds
`getDataLayout()` helpers to Function and GlobalValue, replacing the
current `getParent()->getDataLayout()` pattern.
2024-06-28 08:36:49 +02:00
Nikita Popov
2d209d964a
[IR] Add getDataLayout() helpers to BasicBlock and Instruction (#96902)
This is a helper to avoid writing `getModule()->getDataLayout()`. I
regularly try to use this method only to remember it doesn't exist...

`getModule()->getDataLayout()` is also a common (the most common?)
reason why code has to include the Module.h header.
2024-06-27 16:38:15 +02:00
Mohammed Keyvanzadeh
7b57a1b401
[llvm] format and terminate namespaces with closing comment (#94917)
Namespaces are terminated with a closing comment in the majority of the
codebase so do the same here for consistency. Also format code within
some namespaces to make clang-format happy.
2024-06-21 23:50:53 +03:30
Antonio Frighetto
c22d3917b9 [LVI][ConstantRange] Generalize mask not equal conditions handling
Extend `V & Mask != 0` for non-zero constants if satisfiable, when
retrieving constraint value information from a non-equality comparison.

Proof: https://alive2.llvm.org/ce/z/dc5BeT.

Motivating example: https://github.com/gcc-mirror/gcc/blob/master/gcc/testsuite/gcc.dg/tree-ssa/vrp76.c.
2024-06-17 21:13:52 +02:00
Andreas Jonson
dabd6349f7
[LVI] Remove unused get of Range metadata (#94914)
There is no test for this code and it also do not change the result of
https://github.com/dtcxzyw/llvm-opt-benchmark when I run it locally.
I have not been able to make a test for this and do not know how to
handle the range attribute for this so maybe it shall be removed?
2024-06-10 14:39:39 +02:00
Harald van Dijk
60de56c743
[ValueTracking] Restore isKnownNonZero parameter order. (#88873)
Prior to #85863, the required parameters of llvm::isKnownNonZero were
Value and DataLayout. After, they are Value, Depth, and SimplifyQuery,
where SimplifyQuery is implicitly constructible from DataLayout. The
change to move Depth before SimplifyQuery needed callers to be updated
unnecessarily, and as commented in #85863, we actually want Depth to be
after SimplifyQuery anyway so that it can be defaulted and the caller
does not need to specify it.
2024-04-16 15:21:09 +01:00
Yingwei Zheng
e0a628715a
[ValueTracking] Convert isKnownNonZero to use SimplifyQuery (#85863)
This patch converts `isKnownNonZero` to use SimplifyQuery. Then we can
use the context information from `DomCondCache`.

Fixes https://github.com/llvm/llvm-project/issues/85823.
Alive2: https://alive2.llvm.org/ce/z/QUvHVj
2024-04-12 23:47:20 +08:00
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