1108 Commits

Author SHA1 Message Date
Yingwei Zheng
65ed35393c
[IR] Add helper CmpPredicate::dropSameSign (#134071)
Address review comment
https://github.com/llvm/llvm-project/pull/133711#discussion_r2024519641
2025-04-02 22:25:01 +08:00
Veera
4cdcf3b193
[InstCombine] Fold (trunc nuw A to i1) == (trunc nuw B to i1) to A == B (#133368)
Fixes #133344

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

InstCombine couldn't optimize `i1` because `canonicalizeICmpBool()` was
transforming the comparison into bitwise operations before
`foldICmpTruncWithTruncOrExt()` was called.

This PR solves the ordering issue by placing
`foldICmpTruncWithTruncOrExt()` before `canonicalizeICmpBool()`.

I believe this will not cause any regressions since all tests are
passing.
2025-03-28 08:32:45 -04:00
Nikita Popov
e56a6a2683
Reapply [CaptureTracking][FunctionAttrs] Add support for CaptureInfo (#125880) (#128020)
Relative to the previous attempt this includes two fixes:
 * Adjust callCapturesBefore() to not skip captures(ret: address,
    provenance) arguments, as these will not count as a capture
    at the call-site.
 * When visiting uses during stack slot optimization, don't skip
    the ModRef check for passthru captures. Calls can both modref
    and be passthru for captures.

------

This extends CaptureTracking to support inferring non-trivial
CaptureInfos. The focus of this patch is to only support FunctionAttrs,
other users of CaptureTracking will be updated in followups.

The key API changes here are:

* DetermineUseCaptureKind() now returns a UseCaptureInfo where the UseCC
component specifies what is captured at that Use and the ResultCC
component specifies what may be captured via the return value of the
User. Usually only one or the other will be used (corresponding to
previous MAY_CAPTURE or PASSTHROUGH results), but both may be set for
call captures.
* The CaptureTracking::captures() extension point is passed this
UseCaptureInfo as well and then can decide what to do with it by
returning an Action, which is one of: Stop: stop traversal.
ContinueIgnoringReturn: continue traversal but don't follow the
instruction return value. Continue: continue traversal and follow the
instruction return value if it has additional CaptureComponents.

For now, this patch retains the (unsound) special logic for comparison
of null with a dereferenceable pointer. I'd like to switch key code to
take advantage of address/address_is_null before dropping it.

This PR mainly intends to introduce necessary API changes and basic
inference support, there are various possible improvements marked with
TODOs.
2025-02-27 09:38:29 +01:00
Nico Weber
e2ba1b6ffd Revert "Reapply [CaptureTracking][FunctionAttrs] Add support for CaptureInfo (#125880)"
This reverts commit 0fab404ee874bc5b0c442d1841c7d2005c3f8729.
Seems to break LTO builds of clang on Windows, see comments on
https://github.com/llvm/llvm-project/pull/125880
2025-02-19 11:32:57 -05:00
Yingwei Zheng
29f3a35206
[InstCombine] Do not keep samesign when speculatively executing icmps (#127007)
Closes https://github.com/llvm/llvm-project/issues/126974.
2025-02-16 20:18:29 +08:00
Nikita Popov
7e3735d1a1 Reapply [CaptureTracking][FunctionAttrs] Add support for CaptureInfo (#125880)
Relative to the previous attempt, this adjusts isEscapeSource()
to not treat calls with captures(ret: address, provenance) or similar
arguments as escape sources. This addresses the miscompile reported at:
https://github.com/llvm/llvm-project/pull/125880#issuecomment-2656632577

The implementation uses a helper function on CallBase to make this
check a bit more efficient (e.g. by skipping the byval checks) as
checking attributes on all arguments if fairly expensive.

------

This extends CaptureTracking to support inferring non-trivial
CaptureInfos. The focus of this patch is to only support FunctionAttrs,
other users of CaptureTracking will be updated in followups.

The key API changes here are:

* DetermineUseCaptureKind() now returns a UseCaptureInfo where the UseCC
component specifies what is captured at that Use and the ResultCC
component specifies what may be captured via the return value of the
User. Usually only one or the other will be used (corresponding to
previous MAY_CAPTURE or PASSTHROUGH results), but both may be set for
call captures.
* The CaptureTracking::captures() extension point is passed this
UseCaptureInfo as well and then can decide what to do with it by
returning an Action, which is one of: Stop: stop traversal.
ContinueIgnoringReturn: continue traversal but don't follow the
instruction return value. Continue: continue traversal and follow the
instruction return value if it has additional CaptureComponents.

For now, this patch retains the (unsound) special logic for comparison
of null with a dereferenceable pointer. I'd like to switch key code to
take advantage of address/address_is_null before dropping it.

This PR mainly intends to introduce necessary API changes and basic
inference support, there are various possible improvements marked with
TODOs.
2025-02-14 12:38:04 +01:00
Nikita Popov
1e64ea9914 Revert "[CaptureTracking][FunctionAttrs] Add support for CaptureInfo (#125880)"
This reverts commit ee655ca27aad466bcc54f6eba03f7e564940ad5a.

A miscompilation has been reported at:
https://github.com/llvm/llvm-project/pull/125880#issuecomment-2656632577
2025-02-13 14:56:12 +01:00
Nikita Popov
ee655ca27a
[CaptureTracking][FunctionAttrs] Add support for CaptureInfo (#125880)
This extends CaptureTracking to support inferring non-trivial
CaptureInfos. The focus of this patch is to only support FunctionAttrs,
other users of CaptureTracking will be updated in followups.

The key API changes here are:

* DetermineUseCaptureKind() now returns a UseCaptureInfo where the UseCC
component specifies what is captured at that Use and the ResultCC
component specifies what may be captured via the return value of the
User. Usually only one or the other will be used (corresponding to
previous MAY_CAPTURE or PASSTHROUGH results), but both may be set for
call captures.
* The CaptureTracking::captures() extension point is passed this
UseCaptureInfo as well and then can decide what to do with it by
returning an Action, which is one of: Stop: stop traversal.
ContinueIgnoringReturn: continue traversal but don't follow the
instruction return value. Continue: continue traversal and follow the
instruction return value if it has additional CaptureComponents.

For now, this patch retains the (unsound) special logic for comparison
of null with a dereferenceable pointer. I'd like to switch key code to
take advantage of address/address_is_null before dropping it.

This PR mainly intends to introduce necessary API changes and basic
inference support, there are various possible improvements marked with
TODOs.
2025-02-13 09:36:35 +01:00
hanbeom
553f8e71dd
[InstCombine] simplify icmp pred x, ~x (#73990)
simplify compare between specific variable `X` and  `NOT(X)`

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

Fixed https://github.com/llvm/llvm-project/issues/57532.
2025-02-06 23:43:26 +08:00
Yingwei Zheng
e4980c68c1
[InstCombine] Handle isSubnormalOrZero idiom (#125501)
Alive2: https://alive2.llvm.org/ce/z/9nYE3J
2025-02-04 00:49:51 +08:00
Yingwei Zheng
9725595f3a
[InstCombine] Check nowrap flags when folding comparison of GEPs with the same base pointer (#121892)
Alive2: https://alive2.llvm.org/ce/z/P5XbMx
Closes https://github.com/llvm/llvm-project/issues/121890

TODO: It is still safe to perform this transform without nowrap flags if
the corresponding scale factor is 1 byte:
https://alive2.llvm.org/ce/z/J-JCJd
2025-02-01 20:41:15 +08:00
Yingwei Zheng
626c23112f
[ValueTracking] Use SimplifyQuery in isKnownNonEqual (#124942)
It is needed by https://github.com/llvm/llvm-project/pull/117442.
2025-02-01 15:13:11 +08:00
David Majnemer
503e4b2d54 [InstCombine] Perform some cleanups, add some tests
No functional change is intended.
2025-01-31 20:30:14 +00:00
Jacob Young
bb59eb8ed5
[InstCombine] fold unsigned predicates on srem result (#122520)
This allows optimization of more signed floor implementations when the
divisor is a known power of two to an arithmetic shift.

Proof for the implemented optimizations:
https://alive2.llvm.org/ce/z/j6C-Nz

Proof for the test cases:
https://alive2.llvm.org/ce/z/M_PBjw

---------

Co-authored-by: Jacob Young <jacobly0@users.noreply.github.com>
2025-01-18 14:05:31 -08:00
Yingwei Zheng
03e7862962
[ValueTracking] Move getFlippedStrictnessPredicateAndConstant into ValueTracking. NFC. (#122064)
Needed by https://github.com/llvm/llvm-project/pull/121958.
2025-01-08 20:02:49 +08:00
Nikita Popov
63d4e0fb66 [InstCombine] Compute result directly on APInts
If the bitwidth is 2 and we add two 1s, the result may overflow.
This is fine in terms of correctness, but triggers the APInt ctor
assertion. Fix this by performing the calculation directly on APInts.

Fixes the issue reported in:
https://github.com/llvm/llvm-project/pull/114539#issuecomment-2574845003
2025-01-07 12:13:19 +01:00
Yingwei Zheng
fac4646997
[InstCombine] Check no wrap flags before folding icmp of GEPs with same indices (#121628)
Alive2: https://alive2.llvm.org/ce/z/Dr3Sbe
Closes https://github.com/llvm/llvm-project/issues/121581.
2025-01-04 17:23:57 +08:00
Ramkumar Ramachandra
4a0d53a0b0
PatternMatch: migrate to CmpPredicate (#118534)
With the introduction of CmpPredicate in 51a895a (IR: introduce struct
with CmpInst::Predicate and samesign), PatternMatch is one of the first
key pieces of infrastructure that must be updated to match a CmpInst
respecting samesign information. Implement this change to Cmp-matchers.

This is a preparatory step in migrating the codebase over to
CmpPredicate. Since we no functional changes are desired at this stage,
we have chosen not to migrate CmpPredicate::operator==(CmpPredicate)
calls to use CmpPredicate::getMatching(), as that would have visible
impact on tests that are not yet written: instead, we call
CmpPredicate::operator==(Predicate), preserving the old behavior, while
also inserting a few FIXME comments for follow-ups.
2024-12-13 14:18:33 +00:00
Yingwei Zheng
f4f6566e44
[InstCombine] Fix type mismatch in foldICmpBinOpEqualityWithConstant (#119068)
Closes https://github.com/llvm/llvm-project/issues/119063.
2024-12-08 13:21:34 +08:00
Nikita Popov
ae73bc8e94 Reapply [InstCombine] Support gep nuw in icmp folds (#118472)
The profile runtime test failure this caused has been addressed in:
https://github.com/llvm/llvm-project/pull/118782

-----

Unsigned icmp of gep nuw folds to unsigned icmp of offsets. Unsigned
icmp of gep nusw nuw folds to unsigned samesign icmp of offsets.

Proofs: https://alive2.llvm.org/ce/z/VEwQY8
2024-12-06 14:41:10 +01:00
Yingwei Zheng
59720dc703
[InstCombine] Fold icmp spred (X *nsw Z), (Y *nsw Z) -> icmp pred Z, 0 if scmp(X, Y) is known (#118726)
```
icmp spred (X *nsw Z), (Y *nsw Z) -> icmp swap(spred) Z, 0 if X s< Y
icmp spred (X *nsw Z), (Y *nsw Z) -> icmp spred       Z, 0 if X s> Y
```
Alive2: https://alive2.llvm.org/ce/z/F2D0GE
2024-12-05 19:59:31 +08:00
Vitaly Buka
fc201d6133
Revert "[InstCombine] Support gep nuw in icmp folds" (#118698)
Reverts llvm/llvm-project#118472

Breaks profile tests on i386
https://lab.llvm.org/buildbot/#/builders/66/builds/7009
2024-12-04 15:07:27 -08:00
Ramkumar Ramachandra
51a895aded
IR: introduce struct with CmpInst::Predicate and samesign (#116867)
Introduce llvm::CmpPredicate, an abstraction over a floating-point
predicate, and a pack of an integer predicate with samesign information,
in order to ease extending large portions of the codebase that take a
CmpInst::Predicate to respect the samesign flag.

We have chosen to demonstrate the utility of this new abstraction by
migrating parts of ValueTracking, InstructionSimplify, and InstCombine
from CmpInst::Predicate to llvm::CmpPredicate. There should be no
functional changes, as we don't perform any extra optimizations with
samesign in this patch, or use CmpPredicate::getMatching.

The design approach taken by this patch allows for unaudited callers of
APIs that take a llvm::CmpPredicate to silently drop the samesign
information; it does not pose a correctness issue, and allows us to
migrate the codebase piece-wise.
2024-12-03 13:31:04 +00:00
Nikita Popov
f33536468b
[InstCombine] Support gep nuw in icmp folds (#118472)
Unsigned icmp of gep nuw folds to unsigned icmp of offsets. Unsigned
icmp of gep nusw nuw folds to unsigned samesign icmp of offsets.

Proofs: https://alive2.llvm.org/ce/z/VEwQY8
2024-12-03 14:28:56 +01:00
Nikita Popov
bdc6faf775 [InstCombine] Support nusw in icmp of two geps with same base
Proof: https://alive2.llvm.org/ce/z/BYNQ7s
2024-12-03 11:51:14 +01:00
Nikita Popov
9c5a84b394 [InstCombine] Support nusw in icmp of gep with base
Proof: https://alive2.llvm.org/ce/z/omnQXt
2024-12-03 11:51:14 +01:00
Yingwei Zheng
c1ad064dd3
[InstCombine] Fold icmp spred (and X, highmask), C1 into icmp spred X, C2 (#118197)
Alive2: https://alive2.llvm.org/ce/z/Ffg64g
Closes https://github.com/llvm/llvm-project/issues/104772.
2024-12-03 16:19:12 +08:00
David Green
18abc7e0c5
[PatternMatch] Introduce m_c_Select (#114328)
This matches m_Select(m_Value(), L, R) or m_Select(m_Value(), R, L).
2024-11-25 13:47:23 +00:00
Jie Fu
aa746495af [InstCombine] Remove unused variable in InstCombineCompares.cpp (NFC)
/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp:3190:14:
 error: unused variable 'CmpBW' [-Werror,-Wunused-variable]
    unsigned CmpBW = Ty->getScalarSizeInBits();
             ^
1 error generated.
2024-11-21 21:04:44 +08:00
Yingwei Zheng
2e60048641
[InstCombine] Fold zext(X) + C2 pred C -> X + C3 pred C4 (#110511)
Motivating case from
9852d85ec9/drivers/gpu/drm/drm_edid.c (L5238-L5240):
```
define i1 @src(i8 noundef %v13) {
entry:
  %conv1 = zext i8 %v13 to i32
  %add = add nsw i32 %conv1, -4
  %cmp = icmp ult i32 %add, 3
  %cmp4 = icmp slt i8 %v13, 4
  %cond = select i1 %cmp4, i1 true, i1 %cmp
  ret i1 %cond
}

define i1 @tgt(i8 noundef %v13) {
entry:
  %cmp4 = icmp slt i8 %v13, 7
  ret i1 %cmp4
}
```
2024-11-21 20:47:24 +08:00
Nikita Popov
78f7ca0980
[InstCombine] Use KnownBits predicate helpers (#115874)
Inside foldICmpUsingKnownBits(), instead of rolling our own logic based
on min/max values, make use of ICmpInst::compare() working on KnownBits.
This gives better results for the equality predicates. In practice, the
improvement is only for pointers, because isKnownNonEqual() handles the
non-pointer case.

I've adjusted some tests to prevent the new fold from triggering, to
retain their original intent of testing constant expressions.
2024-11-14 10:13:50 +01:00
Lee Wei
6ad1dd3bdc
[InstCombine] Fold (sext(a) & c1) == c2 to (a & c3) == trunc(c2) (#112646)
Fixes https://github.com/llvm/llvm-project/issues/85830.

Updated Alive proof: https://alive2.llvm.org/ce/z/KnvoP5
2024-11-11 12:51:54 +01:00
Kazu Hirata
e5bf14e9ac
[InstCombine] Remove unused includes (NFC) (#114709)
Identified with misc-include-cleaner.
2024-11-03 08:06:29 -08:00
David Majnemer
902acde341 [InstCombine] Optimize away certain additions using modular arithmetic
We can turn:
```
  %add = add i8 %arg, C1
  %and = and i8 %add, C2
  %cmp = icmp eq i1 %and, C3
```

into:
```
  %and = and i8 %arg, C2
  %cmp = icmp eq i1 %and, (C3 - C1) & C2
```

This is only worth doing if the sequence is the sole user of the addition
operation.
2024-10-28 22:51:35 +00:00
Noah Goldstein
294726d738 Reapply "[InstCombine] Folding (icmp eq/ne (and X, -P2), INT_MIN)" (#111236)
The underlying issue with msan was fixed by #113200
2024-10-23 09:12:08 -05:00
Kazu Hirata
8819267747
[InstCombine] Simplify code with SmallMapVector::operator[] (NFC) (#113022) 2024-10-19 14:38:40 -07:00
Jay Foad
85c17e4092
[LLVM] Make more use of IRBuilder::CreateIntrinsic. NFC. (#112706)
Convert many instances of:
  Fn = Intrinsic::getOrInsertDeclaration(...);
  CreateCall(Fn, ...)
to the equivalent CreateIntrinsic call.
2024-10-17 16:20:43 +01:00
Yingwei Zheng
095d49da76
[InstCombine] Set samesign when converting signed predicates into unsigned (#112642)
Alive2: https://alive2.llvm.org/ce/z/6cqdt-
2024-10-17 20:43:48 +08:00
Yingwei Zheng
0936195311
[InstCombine] Drop samesign in InstCombine (#112480)
Closes https://github.com/llvm/llvm-project/issues/112476.
2024-10-16 19:13:52 +08:00
Rahul Joshi
fa789dffb1
[NFC] Rename Intrinsic::getDeclaration to getOrInsertDeclaration (#111752)
Rename the function to reflect its correct behavior and to be consistent
with `Module::getOrInsertFunction`. This is also in preparation of
adding a new `Intrinsic::getDeclaration` that will have behavior similar
to `Module::getFunction` (i.e, just lookup, no creation).
2024-10-11 05:26:03 -07:00
Kazu Hirata
2d8cd32ae5
[InstCombine] Avoid repeated hash lookups (NFC) (#111618) 2024-10-08 20:37:33 -07:00
Vitaly Buka
574266ce33
Revert "[InstCombine] Folding (icmp eq/ne (and X, -P2), INT_MIN)" (#111236)
Reverts #110880 because of exposed issue is Msan instrumentation
#111212.

This reverts commit a64643688526114b50c25b3eda8a57855bd2be87.
2024-10-04 23:20:40 -07:00
Nikita Popov
67d247a441
[InstCombine] Decompose more icmps into masks (#110836)
Extend decomposeBitTestICmp() to handle cases where the resulting
comparison is of the form `icmp (X & Mask) pred C` with non-zero
`C`. Add a flag to allow code to opt-in to this behavior and use it in
the "log op of icmp" fold infrastructure.

This addresses regressions from #97289.

Proofs: https://alive2.llvm.org/ce/z/hUhdbU
2024-10-04 10:17:23 +02:00
Noah Goldstein
a646436885 [InstCombine] Folding (icmp eq/ne (and X, -P2), INT_MIN)
Folds to `(icmp slt/sge X, (INT_MIN + P2))`

Proofs: https://alive2.llvm.org/ce/z/vpNFY5

Closes #110880
2024-10-03 13:05:08 -05:00
Nikita Popov
7de492f90d [InstCombine] Preserve nuw flag in indexed compare fold
If all the involved GEPs have the nuw flag, also preserve it on
the resulting adds and GEPs.
2024-10-02 16:03:47 +02:00
Yingwei Zheng
2a2c35a9a6
[InstCombine] Fold icmp spred (mul nsw X, Z), (mul nsw Y, Z) into icmp spred X, Y (#110630)
```
icmp spred (mul nsw X, Z), (mul nsw Y, Z) -> icmp spred X, Y iff Z > 0
icmp spred (mul nsw X, Z), (mul nsw Y, Z) -> icmp spred Y, X iff Z < 0
```
Alive2: https://alive2.llvm.org/ce/z/9fXFfn
2024-10-01 22:16:05 +08:00
Yingwei Zheng
1efd1227b2
[InstCombine] Fold icmp eq/ne (X *nw Z), (Y *nw Z) -> icmp eq/ne Z, 0 when X != Y (#110413)
Alive2: https://alive2.llvm.org/ce/z/9oDP6K
I found this pattern in
04e75858d7/casadi/core/repmat.cpp (L70-L78).
2024-09-30 10:21:20 +08:00
Nikita Popov
b8d1bae648
[CmpInstAnalysis] Return decomposed bit test as struct (NFC) (#109819)
decomposeBitTestICmp() currently returns the result via two out
parameters plus an in-place modification of Pred. This changes it to
return an optional struct instead.

The motivation here is twofold. First, I'd like to extend this code to
handle cases where the comparison is against a value other than zero,
which would mean yet another out parameter. Second, while doing that I
was badly bitten by the in-place modification, so I'd like to get rid of
it.
2024-09-25 10:14:15 +02:00
Marina Taylor
5cd0900ef6
[InstCombine] Compare icmp inttoptr, inttoptr values directly (#107012)
InstCombine already has some rules for `icmp ptrtoint, ptrtoint` to drop
the casts and compare the source values. This change adds the same for
the reverse case with `inttoptr`.
2024-09-24 09:39:07 +02:00
Yingwei Zheng
872932b7a9
[InstCombine] Generalize icmp (shl nuw C2, Y), C -> icmp Y, C3 (#104696)
The motivation of this patch is to fold more generalized patterns like
`icmp ult (shl nuw 16, X), 64 -> icmp ult X, 2`.

Alive2: https://alive2.llvm.org/ce/z/gyqjQH
2024-09-18 19:10:41 +08:00