221 Commits

Author SHA1 Message Date
Florian Hahn
26ab444e88
[ConstraintElim] Make sure add-rec is for the current loop.
Update addInfoForInductions to also check if the add-rec is for the
current loop. Otherwise we might add incorrect facts or crash.

Fixes a miscompile & crash introduced by 00396e6a1a0b.
2023-11-08 14:07:28 +00:00
Yingwei Zheng
4acc357a37
[ConstraintElim] Add missing check to make sure the bound is loop-invariant (#70555)
This PR adds a missing check for
e6a1657fa3
to make sure the bound is loop-invariant.

Example:
```
define i32 @main() {
entry:
  br label %for.header

for.header:
  %ind1 = phi i64 [ %ind1.i, %for.latch ], [ 0, %entry ]
  %ind2 = phi i64 [ %ind2.i, %for.latch ], [ 5, %entry ]
  %rem = srem i64 %ind2, 4
  %cmp6 = icmp eq i64 %ind1, %rem
  br i1 %cmp6, label %exit1, label %for.latch

for.latch:
  %ind2.i = add i64 %ind2, 1
  %ind1.i = add i64 %ind1, 1
  %cond = icmp eq i64 %ind1.i, 8
  br i1 %cond, label %exit2, label %for.header

exit2:
  %cmp = icmp eq i64 %rem, 0
  %ret = zext i1 %cmp to i32
  ret i32 %ret

exit1:
  ret i32 0
}
```
We cannot infer `%ind1 <u %rem` from `icmp eq i64 %ind1, %rem` in the
loop since `%rem` is not a loop-invariant.

Fixes #70510.
2023-11-02 23:38:05 +08:00
Nikita Popov
1d43096e16
[ConstraintElim] Don't decompose values wider than 64 bits (#68803)
Our coefficients are 64-bits, so adding/multiplying them can wrap in
64-bits even if there would be no wrapping the full bit width.

The alternative would be to check for overflows during all adds/muls in
decomposition. I assume that we don't particularly care about handling
wide integers here, so I've opted to bail out.

Fixes https://github.com/llvm/llvm-project/issues/68751.
2023-10-16 12:03:49 +02:00
Florian Hahn
56a3e49a00
[ConstraintElim] Support decrementing inductions with step -1. (#68644)
Extend the logic in addInfoForInductions to support decrementing
inductions with a step of -1.

Fixes #64881.
2023-10-10 09:37:27 -07:00
Florian Hahn
00396e6a1a
[ConstraintElim] Support arbitrary incoming values for inductions (#68032)
Support arbitray incoming values for AddRecs by getting the loop
predecessor and checking if its SCEV matches the AddRec start.

This is done after the existing check, which can help to catch cases
where the expression gets simplified by SCEV to either an IR constant or
existing value which can be used instead.
2023-10-03 12:27:56 +01:00
Florian Hahn
98e016d997
[ConstraintElim] Handle trivial (ICMP_ULE, 0, B) in doesHold.
D152730 may add trivial pre-conditions of the form (ICMP_ULE, 0, B),
which won't be handled automatically by the constraint system, because
we don't add Var >= 0 for all variables in the unsigned system.

Handling the trivial condition explicitly here avoids having the
increase the number of rows in the system per variable.

https://alive2.llvm.org/ce/z/QC92ur

Depends on D152730.

Fixes #63125.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D158776
2023-09-27 12:11:28 +01:00
Florian Hahn
e6a1657fa3
[ConstraintElim] Add A < B if A is an increasing phi for A != B.
This patch adds additional logic to add additional facts for A != B, if
A is a monotonically increasing induction phi. The motivating use case
for this is removing checks when using iterators with hardened libc++,
e.g. https://godbolt.org/z/zhKEP37vG.

The patch pulls in SCEV to detect AddRecs. If possible, the patch adds
the following facts for a AddRec phi PN with StartValue as incoming
value from the loo preheader and B being an upper bound for PN from a
condition in the loop header.

 * (ICMP_UGE, PN, StartValue)
 * (ICMP_ULT, PN, B) [if (ICMP_ULE, StartValue, B)]

The patch also adds an optional precondition to FactOrCheck (the new
DoesHold field) , which can be used to only add a fact if the
precondition holds at the point the fact is added to the constraint
system.

Depends on D151799.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D152730
2023-09-27 11:00:28 +01:00
Antonio Frighetto
241848b9b1 [ConstraintElimination] Extend unsigned-to-signed fact transfer
Minor addition of transferring unsigned facts to signed comparisons.

Proofs: https://alive2.llvm.org/ce/z/nqqzHb
2023-09-23 08:54:19 +00:00
Florian Hahn
39d7f700ce
[ConstraintElim] Support adding facts from switch terminators. (#67061)
After 4a5bcbd5602, switch instructions can now be handled in a
straight-forward manner by adding (ICMP_EQ, ConditionVal, CaseVal) for
te successor blocks per case.
2023-09-22 11:18:42 +01:00
Florian Hahn
4a5bcbd560
[ConstraintElim] Store conditional facts as (Predicate, Op0, Op1).
This allows to add facts even if no corresponding ICmp instruction
exists in the IR.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D158837
2023-08-30 10:54:28 +01:00
Florian Hahn
e6260ec49c
[ConstraintElim] Use enum class to differentiate fact/check types (NFC).
Use an enum to clarify the type of fact or check in FactOrCheck, as
suggested in D158837.
2023-08-29 14:23:24 +01:00
Erik Desjardins
66ec5df3a7 [ConstraintElim] fix crash with large constants in mul nsw
Another case of https://github.com/llvm/llvm-project/issues/55085.

The added test would trip an assertion due to calling `getSExtValue()` on a value that doesn't fit in int64_t.

Differential Revision: https://reviews.llvm.org/D158810
2023-08-25 13:20:02 -04:00
Florian Hahn
13ffde316a
[ConstraintElim] Remove dead compares after simplification.
Remove compares after replacing all uses. Cleaning dead compares can
enable additional simplifications when adjusting the position of the
pass slightly. In particular, it seems like the additional dead
instructions may prevent SimplifyCFG performing some folds.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D158760
2023-08-24 22:12:57 +01:00
Yingwei Zheng
92a11eb32c
[ConstraintElim] Add facts implied by MinMaxIntrinsic
Fixes https://github.com/llvm/llvm-project/issues/63896 and https://github.com/rust-lang/rust/issues/113757.
This patch adds facts implied by llvm.smin/smax/umin/umax intrinsics.

Reviewed By: fhahn

Differential Revision: https://reviews.llvm.org/D155412
2023-07-24 15:03:34 +08:00
Yingwei Zheng
cce5324994
[ConstraintElim] Store the triple Pred + LHS + RHS in ReproducerEntry instead of CmpInst + Not
This patch represents a condition with `Pred + LHS + RHS` in ReproducerEntry instead of `CmpInst + Not`.
It avoids creating temporary ICmpInsts in D155412.

Reviewed By: nikic, fhahn

Differential Revision: https://reviews.llvm.org/D155782
2023-07-20 23:21:36 +08:00
Antonio Frighetto
a2ba4e8075 [ConstraintElimination] Handle solving-only ICMP_NE predicates
Simplification of non-equality predicates for solving constraint
systems is now supported by checking the validity of related
inequalities and equalities.

Differential Revision: https://reviews.llvm.org/D152684
2023-06-29 21:22:48 +02:00
Florian Hahn
1689c357ae
[ConstraintElim] Allow and check preconditions in doesHold.
Delegate checking of the constraint & its preconditions to the existing
::isValid. This reduces duplication and allows additional optimizations
together with D152730.
2023-06-29 09:17:37 +01:00
Florian Hahn
0ad6879a62
[ConstraintElim] Try to use first cmp to prove second cmp for ANDs.
This patch extends the existing logic to handle cases where we have
branch conditions of the form (AND icmp, icmp) where the first icmp
implies the second. This can improve results in some cases, e.g. if
SimplifyCFG folded conditions from multiple branches to an AND.

The implementation handles this by adding a new type of check
(AndImpliedCheck), which are queued before conditional facts for the same
block.

When encountering AndImpliedChecks during solving, the first condition
is optimistically added to the constraint system, then we check if the
second icmp can be simplified, and finally the newly added entries are
removed.

The reason for doing things this way is to avoid clashes with signed
<-> unsigned condition transfer, which require us to re-order facts to
increase effectiveness.

Reviewed By: nikic, antoniofrighetto

Differential Revision: https://reviews.llvm.org/D151799
2023-06-28 13:19:41 +01:00
Florian Hahn
4b47711ae2
[ConstraintElim] Move condition check logic to helper function (NFC).
This allows easier re-use of the checking logic. Split off from D151799.
2023-06-28 13:02:12 +01:00
Florian Hahn
e6aa29eddd
[ConstraintElim] Move FactOrCheck and State definitions to top. (NFC)
This will enable follow-up refactoring to use the State directly in the
constraint system, reducing the need to pass lots of arguments around.
2023-06-28 09:40:54 +01:00
Florian Hahn
6c25c58a4d
[ConstraintElim] Track and simplify conditions at use.
This patch updates ConstraintElimination to track uses of conditions in
the worklist. This allows simplifying conditions using the context that
holds directly at the condition, instead of where the condition is
defined.

This allows us to catch more cases in practice: there are multiple
code-size changes for CTMark while compile-time remains unchanged:
https://llvm-compile-time-tracker.com/compare.php?from=4b020cca9363bebab4643f89cfa92ab2fcc7976c&to=7a6e84b8f029713c137814cd46eec775d24a54a1&stat=instructions:u

This should help to simplify D151799.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D153660
2023-06-27 17:27:49 +01:00
Antonio Frighetto
1774c14816 [ConstraintElimination] Handle ICMP_EQ predicates
Simplification of equality predicates is now supported by
transferring equalities into inequalities. This is achieved
by separately checking that both `isConditionImplied(A >= B)`
and `isConditionImplied(A <= B)` hold.

Differential Revision: https://reviews.llvm.org/D152067
2023-06-11 15:22:31 +02:00
Antonio Frighetto
420cf63ead [ConstraintElimination] Refactor checkAndReplaceCondition (NFC)
Handling `true` and `false` constant replacements is now abstracted
out into a single lambda function `ReplaceCmpWithConstant`, so as to
reduce code duplication.
2023-06-05 16:54:58 +02:00
Florian Hahn
6bcbb3af05
[ConstraintElim] Move logic to remove stack entry to helper (NFC).
Preparation for follow-up patch that uses the logic in a separate place.
2023-05-31 14:22:45 +01:00
Florian Hahn
78bb06b127
[ConstraintElim] Port mul nuw for unsigned to mul nsw to signed.
Add handling for `mul nsw` for signed systems based on the logic for
`mul nuw` for unsigned.
2023-04-25 20:36:09 +01:00
Florian Hahn
0a0181dc20
[ConstraintElim] Fix integer overflow in ConstraintSystem::negate.
This fixes another integer overflow that was exposed by a variant of the
test case from #62226.
2023-04-21 16:09:46 +01:00
Florian Hahn
626f6ee7f8
[ConstraintElim] Fix integer overflow in getConstraint.
Use SubOverflow to avoid signed integer overflow when combining
coefficients.

Fixes #62226.
2023-04-20 16:14:06 +01:00
Zain Jaffal
721ecc9d41 [ConstraintElimination] Transfer info from sgt %a, %b to ugt %a, %b if %b > 0
Differential Revision: https://reviews.llvm.org/D148326
2023-04-17 09:27:33 +01:00
Zain Jaffal
1d23d60c8d [ConstraintElimination] Add function arguments to constraint system before solving
If there is an optimisation opportunity and the function argument hasn’t been added to constraint
system through previous facts we fail to optimise it.

It might be a good idea to start the constraint system with all the function arguments added to the system

Reviewed By: fhahn

Differential Revision: https://reviews.llvm.org/D144879
2023-04-03 14:16:49 +01:00
Florian Hahn
02885ef3e4
[ConstraintElim] Use GEPOperator instead of GetElementPtrInst.
The logic in ConstraintElimination should trivially apply to GEP
constant expressions as well, so update code to deal with GEPOperator
instead.
2023-03-24 19:16:08 +00:00
Kazu Hirata
c8f9555c4d [Transforms] Use *{Set,Map}::contains (NFC) 2023-03-14 00:24:30 -07:00
Vitaly Buka
bb01b9919f [ConstraintElimination] Fix UB after D145677 2023-03-09 18:18:29 -08:00
Zain Jaffal
7faa8c6ec6 [ConstraintElimination] Fix undefined behaviour in shl decomposition
Add checks to prevent decomposing constants bigger than 64.
relates to https://github.com/llvm/llvm-project/issues/61127

Reviewed By: fhahn

Differential Revision: https://reviews.llvm.org/D145677
2023-03-09 18:17:27 +00:00
Zain Jaffal
2b62774b65
[ConstraintElimination] Decompose or instruction if the constant operand < 2^known_zero_bits of the first operand.
The or operation can be represented as an add instruction.

Reviewed By: fhahn

Differential Revision: https://reviews.llvm.org/D142546
2023-03-07 14:11:35 +00:00
Nikita Popov
ffe8f47d72 [IR] Add operator<< overload for CmpInst::Predicate (NFC)
I regularly try and fail to use this while debugging.
2023-03-07 15:10:56 +01:00
Zain Jaffal
07f93d8c2c Recommit "[ConstraintElimination] Change debug output to display variable names."
This reverts commit 02ae7e72b3f00969eeb579a2b4346082827f0b35.

include Value.h in ConstraintSystem.h
2023-02-15 16:38:35 +00:00
Nikita Popov
02ae7e72b3 Revert "Recommit "[ConstraintElimination] Change debug output to display variable names.""
This reverts commit 2a2a6bfcfe8e62886542cb673ac8df349cf26499.

This causes build failures:

    /home/npopov/repos/llvm-project/llvm/lib/Analysis/ConstraintSystem.cpp: In member function ‘llvm::SmallVector<std::__cxx11::basic_string<char> > llvm::ConstraintSystem::getVarNamesList() const’:
    /home/npopov/repos/llvm-project/llvm/lib/Analysis/ConstraintSystem.cpp:118:10: error: invalid use of incomplete type ‘class llvm::Value’
      118 |     if (V->getName().empty())
          |          ^~
    In file included from /home/npopov/repos/llvm-project/llvm/lib/Analysis/ConstraintSystem.cpp:9:
    /home/npopov/repos/llvm-project/llvm/include/llvm/Analysis/ConstraintSystem.h:21:7: note: forward declaration of ‘class llvm::Value’
       21 | class Value;
          |       ^~~~~
    /home/npopov/repos/llvm-project/llvm/lib/Analysis/ConstraintSystem.cpp:119:22: error: invalid use of incomplete type ‘class llvm::Value’
      119 |       OperandName = V->getNameOrAsOperand();
          |                      ^~
    /home/npopov/repos/llvm-project/llvm/include/llvm/Analysis/ConstraintSystem.h:21:7: note: forward declaration of ‘class llvm::Value’
       21 | class Value;
          |       ^~~~~
    /home/npopov/repos/llvm-project/llvm/lib/Analysis/ConstraintSystem.cpp:121:41: error: invalid use of incomplete type ‘class llvm::Value’
      121 |       OperandName = std::string("%") + V->getName().str();
          |                                         ^~
    /home/npopov/repos/llvm-project/llvm/include/llvm/Analysis/ConstraintSystem.h:21:7: note: forward declaration of ‘class llvm::Value’
       21 | class Value;
          |       ^~~~~
2023-02-15 16:36:44 +01:00
Zain Jaffal
2a2a6bfcfe Recommit "[ConstraintElimination] Change debug output to display variable names."
This reverts commit 62d0e1a8541f93dfbf66d982f66da32676df2df7.

remove `dumpWithNames` function
2023-02-15 15:23:53 +00:00
Zain Jaffal
62d0e1a854 Revert "[ConstraintElimination] Change debug output to display variable names."
This reverts commit 869c87ad10e87db7c032c3464338ab9d50916510.

`dumpWithNames` function should be removed
2023-02-15 15:21:46 +00:00
Zain Jaffal
869c87ad10 [ConstraintElimination] Change debug output to display variable names.
Previously when constraint system outputs the rows in the system the variables used are x1,2...n making it hard to infer which ones they relate to in the IR

Reviewed By: fhahn

Differential Revision: https://reviews.llvm.org/D142618
2023-02-15 15:07:48 +00:00
Florian Hahn
f044217392
[ConstraintElim] Add reproducer remarks.
This patch adds an optimization remark for each performed optimization
containing a module that can be used to reproduce the transformation.

The reproducer function contains a series of @llvm.assume calls, one for
each condition currently in scope. For each condition, the operand
instruction are cloned until we reach operands that have an entry in the
constraint system. Those will then be added as function arguments.

The reproducer functions are minimal, that is, they only contain the
conditions required for a given simplification. The resulting IR is very
compact and can be used to verify each transformation individually.

It also provides a python script to extract the IR from the remarks and
create LLVM IR files from it.

Reviewed By: paquette

Differential Revision: https://reviews.llvm.org/D143323
2023-02-14 15:15:57 +00:00
Zain Jaffal
a9d6a86b21 Recommit "[ConstraintElimination] Move Value2Index map to ConstraintSystem (NFC)"
This reverts commit 665ee0cd57f92a112cf8e929d00768e282fb205a.

Fix comments and formatting style.
2023-02-08 14:52:43 +00:00
Zain Jaffal
665ee0cd57 Revert "[ConstraintElimination] Move Value2Index map to ConstraintSystem (NFC)"
This reverts commit 40ffe9c167395256b43846733ab69eec17eead78.

Reverted because some comments where missed in the review https://reviews.llvm.org/D142647
2023-02-08 11:29:59 +00:00
Zain Jaffal
40ffe9c167 [ConstraintElimination] Move Value2Index map to ConstraintSystem (NFC)
Differential Revision: https://reviews.llvm.org/D142647
2023-02-08 11:15:31 +00:00
Florian Hahn
23ce9383ca
[ConstraintElim] Add option to limit number of rows tracked in system.
Once the constraint system grows too large in terms of number of rows,
queries can become very slow. This patch adds a new option to limit the
number of rows tracked.

The python script below can be used to generate worst-case IR with a
chain of conditional branches with N branches.

With this limit, we get the following runtimes:
* python3 generate.py 100:   0.1s
* python3 generate.py 1000:  2s
* python3 generate.py 10000: 4s

Without the limit, the case with 1000 chained conditions takes 20+
seconds.

generate.py:
    import sys

    N = int(sys.argv[1])

    args = []
    checks = []

    for i in range(0, N):
        args.append('i32 %l{}'.format(i))
        checks.append("""
    bb{0}:
      %c{0} = icmp uge i32 %l{0}, 100
      br i1 %c{0}, label %bb{1}, label %exit
    """.format(i, i+1))

    print("""
    define i1 @foo({0}) {{
    {1}

    bb{2}:
      %c{2} = icmp uge i32 %l0, 100
      ret i1 %c{2}

    exit:
      ret i1 false
    }}
    """.format(' ,'.join(args), '\n'.join(checks), N))

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D140926
2023-01-04 13:59:23 +00:00
Florian Hahn
f8d008d19f
[ConstraintElim] Remove legacy pass implementation.
The pass is exclusively used with the new pass manager now, so remove
the legacy PM implementation.
2023-01-04 11:21:12 +00:00
Florian Hahn
8fa81cfad4
[ConstraintElim] Address comments from D137840.
Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D139482
2022-12-07 14:12:53 +00:00
Florian Hahn
9eda78107c
[ConstraintElim] Fix sort order to not comparing insts in different bbs.
Update the sort order to make sure that comesBefore is never used from
conditional facts, which are instructions but may use DFS numbers from
different blocks.

This fixes a crash in the added test on some platforms.
2022-12-06 23:47:24 +00:00
Florian Hahn
6887cfb982
[ConstraintElim] Queue facts and checks directly.
This allows interleaving facts and checks in a single block. In
particular this enables using facts from assumes for conditions in the
same block that come after the assume.

This could be extended to only try to simplify checks at the point where
a condition is used.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D138452
2022-12-05 16:44:20 +00:00
Florian Hahn
6b940588a0
[ConstraintElim] Update comment after recent changes.
Update the comment to reflect the current code.
2022-12-05 12:19:09 +00:00