337 Commits

Author SHA1 Message Date
Florian Hahn
4233a15c9f
[FunctionAttrs] Handle zero writes in initializes inference.
ConstantRange's constructor asserts that the range not empty, except if
lower/upper are min or max values.

Check if the length is strictly positive instead of just non-negative so
std::nullopt is returned when the size is 0. If that's the case, the
access doesn't initialize anything.

This should fix a crash when building on macOS with ASan & UBsan after
https://github.com/llvm/llvm-project/pull/97373 /
https://github.com/llvm/llvm-project/pull/117104 landed:
https://green.lab.llvm.org/job/llvm.org/job/clang-stage2-cmake-RgSan/664/console
2025-01-18 20:01:07 +00:00
Heejin Ahn
5a90168fa3
[ValueTracking] Provide getUnderlyingObjectAggressive fallback (#123019)
This callsite assumes `getUnderlyingObjectAggressive` returns a non-null
pointer:

273a94b3d5/llvm/lib/Transforms/IPO/FunctionAttrs.cpp (L124)

But it can return null when there are cycles in the value chain so there
is no more `Worklist` item anymore to explore, in which case it just
returns `Object` at the end of the function without ever setting it:
9b5857a683/llvm/lib/Analysis/ValueTracking.cpp (L6866-L6867)
9b5857a683/llvm/lib/Analysis/ValueTracking.cpp (L6889)

`getUnderlyingObject` does not seem to return null either judging by
looking at its code and its callsites, so I think it is not likely to be
the author's intention that `getUnderlyingObjectAggressive` returns
null.

So this checks whether `Object` is null at the end, and if so, falls
back to the original first value.

---

The test case here was reduced by bugpoint and further reduced manually,
but I find it hard to reduce it further.

To trigger this bug, the memory operation should not be reachable from
the entry BB, because the `phi`s should form a cycle without introducing
another value from the entry. I tried a minimal `phi` cycle with three
BBs (entry BB + two BBs in a cycle), but it was skipped here:
273a94b3d5/llvm/lib/Transforms/IPO/FunctionAttrs.cpp (L121-L122)
To get the result that's not `ModRefInfo::NoModRef`, the length of `phi`
chain needed to be greater than the `MaxLookup` value set in this
function:

02403f4e45/llvm/lib/Analysis/BasicAliasAnalysis.cpp (L744)

But just lengthening the `phi` chain to 8 didn't trigger the same error
in `getUnderlyingObjectAggressive` because `getUnderlyingObject` here
passes through a single-chain `phi`s so not all `phi`s end up in
`Visited`:

9b5857a683/llvm/lib/Analysis/ValueTracking.cpp (L6863)

So I just submit here the smallest test case I managed to create.

---

Fixes #117308 and fixes #122166.
2025-01-15 11:53:51 -08:00
Nikita Popov
2d760a139e [FunctionAttrs] Add test for initializes + byval (NFC) 2025-01-14 15:30:39 +01:00
Alex MacLean
c6c864da3f
[FunctionAttrs] Treat byval calls as only reading ptrs (#122618)
Since byval arguments are passed via a hidden copy of the pointee, they
do not have the same semantics as normal pointer arguments. The callee
cannot capture or write to the pointer and the copy is a read of the
pointer.
2025-01-13 12:10:26 -08:00
Haopeng Liu
8daba2c13d
Skip negative length while inferring initializes attr (#120874)
Bail out negative length while inferring initializes attr. Otherwise it
causes an assertion error:
`Attribute 'initializes' does not support unordered ranges`
2024-12-22 19:01:52 -08:00
Haopeng Liu
4d6e69143d
Add the initializes attribute inference (#117104)
reland https://github.com/llvm/llvm-project/pull/97373 after fixing
clang tests.

Confirmed with "ninja check-llvm" and "ninja check-clang"
2024-11-20 19:15:23 -08:00
Mikhail Goncharov
f77126c549 Revert "[FunctionAttrs] Add the "initializes" attribute inference (#97373)"
This reverts commit 661c593850715881d2805a59e90e6d87d8b9fbb8.

Multiple buildbot failures, e.g. https://lab.llvm.org/buildbot/#/builders/108/builds/6096
2024-11-19 10:29:36 +01:00
Haopeng Liu
661c593850
[FunctionAttrs] Add the "initializes" attribute inference (#97373)
Add the "initializes" attribute inference.

This change is expected to have ~0.09% compile time regression, which
seems acceptable for interprocedural DSE.

https://llvm-compile-time-tracker.com/compare.php?from=9f10252c4ad7cffbbcf692fa9c953698f82ac4f5&to=56345c1cee4375eb5c28b8e7abf4803d20216b3b&stat=instructions%3Au
2024-11-18 21:36:05 -08:00
Lee Wei
1ca64c5fb7
[llvm] Remove br i1 undef from some regression tests [NFC] (#115691)
This PR aims to remove undefined behavior from tests under the directory
`llvm/transforms/CodegenPrepare, ConstantHoisting, Coroutines` etc.
2024-11-11 12:56:31 +00:00
Matt Arsenault
d74b1f029d
ValueTracking: Do not return nullptr from getUnderlyingObject (#115258)
Fixup for 29a5c054e6d56a912ed5ba3f84e8ca631872db8b. The failure case
should return the last value found.
2024-11-07 07:35:33 -08:00
Noah Goldstein
6b11573b8c Recommit "[FunctionAttrs] deduce attr cold on functions if all CG paths call a cold function"
Fixed up the uar test that was failing. It seems with the new `cold`
attribute the order of the functions is different. As far as I can
tell this is not a concern.

Closes #105559
2024-08-22 10:14:08 -07:00
Noah Goldstein
69a0af756b Revert "[FunctionAttrs] deduce attr cold on functions if all CG paths call a cold function"
This reverts commit b7eac8c6fea1ba3930d08011a0e5e3a262bfaece.

Causing a test failure. Not 100% sure the issue so to reverting to
unblock pipeline.
2024-08-20 22:10:30 -07:00
Noah Goldstein
b7eac8c6fe [FunctionAttrs] deduce attr cold on functions if all CG paths call a cold function
Closes #101298
2024-08-20 15:29:24 -07:00
Noah Goldstein
26b79f8707 [FunctionAttrs] Add tests for deducing attr cold on functions; NFC 2024-08-20 15:29:24 -07:00
Nikita Popov
472c79ca52
[IR] Check that arguments of naked function are not used (#104757)
Verify that the arguments of a naked function are not used. They can
only be referenced via registers/stack in inline asm, not as IR values.
Doing so will result in assertion failures in the backend.

There's probably more that we should verify, though I'm not completely
sure what the constraints are (would it be correct to require that naked
functions are exactly an inline asm call + unreachable, or is more
allowed?)

Fixes https://github.com/llvm/llvm-project/issues/104718.
2024-08-20 09:29:05 +02:00
DianQK
559be8e2b5
Reapply "[FunctionAttrs] Determine underlying object by getUnderlyingObjectAggressive (#100102)"
Added handling for `AllocaInst`.

This reverts commit 1ee686a55aa6365eff39bbd1dc2059b16be6c2f1.
2024-07-24 20:01:22 +08:00
Nikita Popov
1ee686a55a Revert "[FunctionAttrs] Determine underlying object by getUnderlyingObjectAggressive (#100102)"
This reverts commit a213edd32abff8d154dad96824689b98ec7b5a35.

Assertion failures on buildbots.
2024-07-23 14:57:25 +02:00
DianQK
a213edd32a
[FunctionAttrs] Determine underlying object by getUnderlyingObjectAggressive (#100102)
Thanks to #99509, we can fix
https://github.com/rust-lang/rust/issues/119573 too.
2024-07-23 20:50:25 +08:00
Nikita Popov
f64732195c [FunctionAttrs] Regenerate test checks (NFC) 2024-05-23 08:45:38 +02:00
Johannes Doerfert
5ec91b392d
[AttributorLight] Without liveness checks, look at all functions (#91004) 2024-05-23 07:28:07 +02:00
Nikita Popov
f34d30cdae
[FunctionAttrs] Fix incorrect nonnull inference for non-inbounds GEP (#91180)
For inbounds GEPs, if the source pointer is non-null, the result must
also be non-null. However, this does not hold for non-inbounds GEPs.
    
Fixes https://github.com/llvm/llvm-project/issues/91177.
2024-05-07 09:47:28 +09:00
Nikita Popov
a2ccd5d88f
[FunctionAttrs] Fix incorrect noundef inference with poison attrs (#89348)
Currently, when inferring noundef, we only check that the return value
is not undef/poison. However, we fail to account for the possibility
that a poison-generating return attribute will convert the value to
poison, and then violate the noundef attribute, resulting in immediate
UB.

For the relevant return attributes (align, nonnull and range), check
whether we can trivially re-prove the relevant property, otherwise do
not infer noundef.

This fixes the FunctionAttrs side of
https://github.com/llvm/llvm-project/issues/88026.
2024-04-23 14:26:12 +09:00
Nikita Popov
bd898d5e11 [FunctionAttrs] Add tests for incorrect noundef inference (#88026) 2024-04-19 14:55:50 +09:00
elhewaty
fa8dc36350
[IR] Fix crashes caused by #85592 (#87169)
This patch fixes the crash caused by the pull request:
https://github.com/llvm/llvm-project/pull/85592
2024-04-02 15:49:31 +08:00
Yingwei Zheng
7e405eb722
[FuncAttrs] Don't infer noundef for functions with sanitize_memory attribute (#76691)
MemorySanitizer assumes that the definition and declaration of a
function will be consistent. If we add `noundef` for some definitions,
it will break msan.

Fix buildbot failure caused by #76553.
2024-01-02 06:59:56 +08:00
Yingwei Zheng
1228becf7d
[FuncAttrs] Deduce noundef attributes for return values (#76553)
This patch deduces `noundef` attributes for return values.
IIUC, a function returns `noundef` values iff all of its return values
are guaranteed not to be `undef` or `poison`.
Definition of `noundef` from LangRef:
```
noundef
This attribute applies to parameters and return values. If the value representation contains any 
undefined or poison bits, the behavior is undefined. Note that this does not refer to padding 
introduced by the type’s storage representation.
```
Alive2: https://alive2.llvm.org/ce/z/g8Eis6

Compile-time impact: http://llvm-compile-time-tracker.com/compare.php?from=30dcc33c4ea3ab50397a7adbe85fe977d4a400bd&to=c5e8738d4bfbf1e97e3f455fded90b791f223d74&stat=instructions:u
|stage1-O3|stage1-ReleaseThinLTO|stage1-ReleaseLTO-g|stage1-O0-g|stage2-O3|stage2-O0-g|stage2-clang|
|--|--|--|--|--|--|--|
|+0.01%|+0.01%|-0.01%|+0.01%|+0.03%|-0.04%|+0.01%|

The motivation of this patch is to reduce the number of `freeze` insts
and enable more optimizations.
2023-12-31 20:44:48 +08:00
Yingwei Zheng
4358e6e0c5
[FuncAttrs] Infer norecurse for funcs with calls to nocallback callees (#76372)
This patch adds missing `norecurse` attrs to funcs that only call intrinsics with `nocallback` attrs.
Fixes the regression found in https://github.com/dtcxzyw/llvm-opt-benchmark/pull/45#discussion_r1436148743.
The function loses `norecurse` attr because it calls `@llvm.fabs.f64`, which is not marked as `norecurse`.

Since `norecurse` is not a default attribute of intrinsics and it is
ambiguous for intrinsics, I decided to use the existing `callback`
attributes.

> nocallback
This attribute indicates that the function is only allowed to jump back
into caller’s module by a return or an exception, and is not allowed to
jump back by invoking a callback function, a direct, possibly
transitive, external function call, use of longjmp, or other means. It
is a compiler hint that is used at module level to improve dataflow
analysis, dropped during linking, and has no effect on functions defined
in the current module.

See also https://llvm.org/docs/LangRef.html#function-attributes.
2023-12-27 03:16:43 +08:00
Nikita Popov
6b8ed78719 [IR] Add writable attribute
This adds a writable attribute, which in conjunction with
dereferenceable(N) states that a spurious store of N bytes is
introduced on function entry. This implies that this many bytes
are writable without trapping or introducing data races. See
https://llvm.org/docs/Atomics.html#optimization-outside-atomic for
why the second point is important.

This attribute can be added to sret arguments. I believe Rust will
also be able to use it for by-value (moved) arguments. Rust likely
won't be able to use it for &mut arguments (tree borrows does not
appear to allow spurious stores).

In this patch the new attribute is only used by LICM scalar promotion.
However, the actual motivation for this is to fix a correctness issue
in call slot optimization, which needs this attribute to avoid
optimization regressions.

Followup to the discussion on D157499.

Differential Revision: https://reviews.llvm.org/D158081
2023-11-01 10:46:31 +01:00
Krzysztof Drewniak
93f8e52d1f
[FunctionAttrs] Improve handling of alias-preserving intrinsic calls (#68453)
Fixes #68270

The function attribute analysis handles many instructions, like
addrspacecast, which do not themselves read or write memory but which
transform pointers into other values in the same alias set.

There are intrinsic functions, such as ptrmask or the AMDGPU-specific
make.buffer.rsrc, which also preserve membership in alias sets without
capturing. This commit adds the addrspacecast-like behavior to these
calls.
2023-10-24 11:16:54 -05:00
Nikita Popov
2ad41fa736 [FunctionAttrs] Regenerate test checks (NFC) 2023-10-20 09:59:32 +02:00
Nikita Popov
104c01eb31
[FunctionAttrs] Only check ArgMem effects when inferring argument attrs (#69571)
When inferring readonly/writeonly on arguments, if the argument is
passed to a call, we should only check the ArgMem effects implied by the
call -- we don't care whether the call reads/writes non-arg memory
(captured pointers are not relevant here, because they will abort the
analysis entirely).

This also fixes a regression that was introduced when moving to
MemoryEffects: The code was still checking the old WriteOnly attribute
on functions, which no longer exists.
2023-10-20 08:56:09 +02:00
Nikita Popov
9ea2fd2457 [FunctionAttrs] Add additional tests for writeonly (NFC)
Add tests with argmem variations.
2023-10-19 10:32:18 +02:00
Anton Korobeynikov
51d5d7bbae
Extend retcon.once coroutines lowering to optionally produce a normal result (#66333)
One of the main user of these kind of coroutines is swift. There yield-once (`retcon.once`) coroutines are used to temporary "expose" pointers to internal fields of various objects creating borrow scopes.

However, in some cases it might be useful also to allow these coroutines to produce a normal result, but there is no convenient way to represent this (as compared to switched-resume kind of coroutines where C++ `co_return`
is transformed to a member / callback call on promise object).

The extension is simple: we allow continuation function to have a non-void result and accept optional extra arguments via a special `llvm.coro.end.result` intrinsic that would essentially forward them as normal results.
2023-09-15 09:54:38 -07:00
Noah Goldstein
39e9862e6b [ValueTracking] Use predicates for incoming phi-edges to deduce non-zero
This is basically a copy and paste of the same logic we do in
`computeKnownBits` but adapts it for just `isKnownNonZero`.

Differential Revision: https://reviews.llvm.org/D157801
2023-08-22 10:59:02 -05:00
Nikita Popov
86f3dc83e1 [FunctionAttrs] Consider recursive argmem effects (PR63936)
When inspecting the function body, we can't simply ignore effects
of functions in the SCC entirely, because an argmem access of a
recursive call might result in an access to another location in
the callee.

Fix this by separately tracking memory effects that would occur if
the SCC accesses argmem, and then later add those.

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

Differential Revision: https://reviews.llvm.org/D155956
2023-08-14 14:39:54 +02:00
Nikita Popov
9d33c467b7 [FunctionAttrs] Fix argmemonly.ll test (NFC)
This test was incorrectly updated in D152081.
2023-08-09 11:13:19 +02:00
Florian Hahn
400fde9296
[Attributor] Add lightweight version for attribute deduction only.
This patch adds a lightweight instance of Attributor that only deduces
attributes.

This is just an initial version with the goal to have a version that
only focuses on attributes to replace the function-attrs pass.

The initial version has a few open issues pending until default
enablement, the main one probably being compile time. The main
additional functionality this will provide in general is propagating
attributes to call sites.

Open issues:

* compile time
  The current version increase O3 +2.67% and ThinLTO +6.18% when replacing FunctionAttr
   https://llvm-compile-time-tracker.com/compare.php?from=c4bb3e073548cf436d5fa0406e3ae75e94684dec&to=d992630a69c79a2587d736e6a88f448850413bd1&stat=instructions%3Au
   Both are with an additional change to preserve more analysis, like FunctionAttrs CGSCC run.

* some missed attribute inference

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D152081
2023-08-05 11:47:28 +01:00
Nikita Popov
4bb2234a5d [FunctionAttrs] Add tests for PR63936 (NFC) 2023-07-21 16:46:29 +02:00
Nikita Popov
f3d0613d85 [CaptureTracking] Don't consider comparison of inbounds GEP with nonnull non-capturing
This is required to bring CaptureTracking in line with the new
semantics from D154051, as gep inbounds p, 0 is now always non-poison.

There are many ways in which the inbounds special case could be
preserved: If the index is known non-zero, or there is an inbounds
chain down to an identified object, etc. However, I have opted to
drop the special case entirely, as it appears to be low value:
In cases where we can determine such things (e.g. the affected test
cases) we would end up removing the compare via isGEPKnownNonNull()
logic anyway.

Differential Revision: https://reviews.llvm.org/D154054
2023-07-06 16:48:43 +02:00
Nikita Popov
f5f5c4726c [FunctionAttrs] Regenerate test checks (NFC) 2023-06-29 09:59:16 +02:00
Noah Goldstein
3391bdc255 Revert "[FunctionAttrs] Propagate some func/arg/ret attributes from caller to callsite (WIP)"
Accidental commit/push!

This reverts commit 4fa971ff62c3c48c606b792c572c03bd4d5906ee.
2023-06-13 00:53:31 -05:00
Noah Goldstein
4fa971ff62 [FunctionAttrs] Propagate some func/arg/ret attributes from caller to callsite (WIP)
This is the consolidation of D151644 and D151943 moved from
InstCombine to FunctionAttrs. This is based on discussion in the above
patches as well as D152081 (Attributor). This patch was written in a
way so it can have an immediate impact in currently active passes
(FunctionAttrs), but should be easy to port elsewhere (Attributor or
Inliner) if that makes more sense later on.

Some function attributes imply the attribute for all/some instructions
in the function. These attributes can be safely propagated to
callsites within the function that are missing the attribute. This can
be useful when 1) analyzing individual instructions in a function
and 2) if the original caller is later inlined, as if the attributes are
not propagated, they will be lost.

This patch implements propagation in a new class/file
`InferCallsiteAttrs` which can hypothetically be included elsewhere.

At the moment this patch infers the following:

Function Attributes:
    - mustprogress
    - nofree
    - willreturn
    - All memory attributes (readnone, readonly, writeonly, argmem,
      etc...)
        - The memory attributes are only propagated IFF the set of
          pointers available to the callsite is the same as the set
          available outside the caller (i.e no local memory arguments
          from alloca or local malloc like functions).

Argument Attributes:
    - noundef
    - nonnull
    - nofree
    - readnone
    - readonly
    - writeonly
    - nocapture
        - nocapture is only propagated IFF the set of pointers
          available to the callsite is the same as the set available
          outside the caller and its guranteed that between the
          callsite and function return, the state of any capture
          pointers will not change (so the nocaptured gurantee of the
          caller has been met by the instruction preceding the
          callsite and will not changed).

Argument are only propagated to callsite arguments that are also function
arguments, but not derived values.

Return Attributes:
    - noundef
    - nonnull

Return attributes are only propagated if the callsite's return value
is used as the caller's return and execution is guranteed to pass from
callsite to return.

The compile time hit of this for -O3 and -O3+thinLTO is ~[.02, .37]%
regression. Proper LTO, however, has more significant regressions (up
to 3.92%):
https://llvm-compile-time-tracker.com/compare.php?from=94407e1bba9807193afde61c56b6125c0fc0b1d1&to=79feb6e78b818e33ec69abdc58c5f713d691554f&stat=instructions:u

Differential Revision: https://reviews.llvm.org/D152226
2023-06-13 00:47:43 -05:00
Nikita Popov
9fe78db4cd [FunctionAttrs] Fix nounwind inference for landingpads
Currently, FunctionAttrs treats landingpads as non-throwing, and
will infer nounwind for functions with landingpads (assuming they
can't unwind in some other way, e.g. via resum). There are two
problems with this:

* Non-cleanup landingpads with catch/filter clauses do not
  necessarily catch all exceptions. Unless there are catch ptr null
  or filter [0 x ptr] zeroinitializer clauses, we should assume
  that we may unwind past this landingpad. This seems like an
  outright bug.
* Cleanup landingpads are skipped during phase one unwinding, so
  we effectively need to support unwinding past them. Marking these
  nounwind is technically correct, but not compatible with how
  unwinding works in reality.

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

Differential Revision: https://reviews.llvm.org/D147694
2023-04-14 11:46:00 +02:00
Nikita Popov
e0639695d3 [FunctionAttrs] Add another nounwind test (NFC) 2023-04-13 09:56:01 +02:00
Nikita Popov
af960a772d [FunctionAttrs] Add cleanuppad test (NFC) 2023-04-11 16:30:33 +02:00
Nikita Popov
e3f5cbd9c0 [FunctionAttrs] Add more nounwind tests (NFC)
Test variations where catch/filter catch all exceptions.
2023-04-06 10:54:15 +02:00
Nikita Popov
709cafb10d [FunctionAttrs] Add additional nounwind inference tests (NFC)
For PR61945.
2023-04-06 10:41:40 +02:00
Bjorn Pettersson
3528e63d89 [test] Remove duplicate RUN lines in Transform tests 2022-12-08 11:47:16 +01:00
Roman Lebedev
091aabc181
[NFC] Port all FunctionAttrs tests to -passes= syntax 2022-12-08 02:38:43 +03:00
Nikita Popov
304f1d59ca [IR] Switch everything to use memory attribute
This switches everything to use the memory attribute proposed in
https://discourse.llvm.org/t/rfc-unify-memory-effect-attributes/65579.
The old argmemonly, inaccessiblememonly and inaccessiblemem_or_argmemonly
attributes are dropped. The readnone, readonly and writeonly attributes
are restricted to parameters only.

The old attributes are auto-upgraded both in bitcode and IR.
The bitcode upgrade is a policy requirement that has to be retained
indefinitely. The IR upgrade is mainly there so it's not necessary
to update all tests using memory attributes in this patch, which
is already large enough. We could drop that part after migrating
tests, or retain it longer term, to make it easier to import IR
from older LLVM versions.

High-level Function/CallBase APIs like doesNotAccessMemory() or
setDoesNotAccessMemory() are mapped transparently to the memory
attribute. Code that directly manipulates attributes (e.g. via
AttributeList) on the other hand needs to switch to working with
the memory attribute instead.

Differential Revision: https://reviews.llvm.org/D135780
2022-11-04 10:21:38 +01:00