[FunctionAttrs] Propagate some func/arg/ret attributes from caller to callsite (WIP)
authorNoah Goldstein <goldstein.w.n@gmail.com>
Tue, 13 Jun 2023 05:43:22 +0000 (00:43 -0500)
committerNoah Goldstein <goldstein.w.n@gmail.com>
Tue, 13 Jun 2023 05:47:43 +0000 (00:47 -0500)
commit4fa971ff62c3c48c606b792c572c03bd4d5906ee
tree71d5358c4690fea40ae90303e0f729321ebfb6c6
parent5e691a1c9b0ad22689d4a434ddf4fed940e58dec
[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
52 files changed:
clang/test/CodeGen/LoongArch/inline-asm-constraints.c
clang/test/CodeGen/LoongArch/inline-asm-operand-modifiers.c
clang/test/CodeGen/LoongArch/intrinsic-la32.c
clang/test/CodeGen/LoongArch/intrinsic-la64.c
clang/test/CodeGen/PowerPC/builtins-ppc-build-pair-mma.c
clang/test/CodeGen/PowerPC/builtins-ppc-pair-mma.c
clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReseve-StoreCond-64bit-only.c
clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReseve-StoreCond.c
clang/test/CodeGen/PowerPC/ppc64-inline-asm.c
clang/test/CodeGen/RISCV/riscv-inline-asm.c
clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/vwrite-csr.c
clang/test/CodeGen/X86/fma-builtins-constrained.c
clang/test/CodeGen/X86/ms-x86-intrinsics.c
clang/test/CodeGen/aarch64-bf16-ldst-intrinsics.c
clang/test/CodeGen/aarch64-ls64-inline-asm.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1sb.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1sh.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1sw.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1ub.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1uh.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1uw.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_stnt1.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_stnt1b.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_stnt1h.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_stnt1w.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilege.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilegt.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilerw-bfloat.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilerw.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilewr-bfloat.c
clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilewr.c
clang/test/CodeGen/aarch64_neon_sve_bridge_intrinsics/acle_neon_sve_bridge_dup_neonq.c
clang/test/CodeGen/aarch64_neon_sve_bridge_intrinsics/acle_neon_sve_bridge_get_neonq.c
clang/test/CodeGen/aarch64_neon_sve_bridge_intrinsics/acle_neon_sve_bridge_set_neonq.c
clang/test/CodeGen/attr-arm-sve-vector-bits-cast.c
clang/test/CodeGen/attr-riscv-rvv-vector-bits-call.c
clang/test/CodeGen/attr-riscv-rvv-vector-bits-cast.c
clang/test/CodeGen/msp430-builtins.c
clang/test/CodeGen/nofpclass.c
clang/test/Headers/wasm.c
llvm/include/llvm/Transforms/Utils/InferCallsiteAttrs.h [new file with mode: 0644]
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
llvm/lib/Transforms/Utils/CMakeLists.txt
llvm/lib/Transforms/Utils/InferCallsiteAttrs.cpp [new file with mode: 0644]
llvm/test/Other/cgscc-devirt-iteration.ll
llvm/test/Transforms/FunctionAttrs/nonnull.ll
llvm/test/Transforms/FunctionAttrs/readattrs.ll
llvm/test/Transforms/FunctionAttrs/willreturn-callsites.ll
llvm/test/Transforms/MergeFunc/mergefunc-preserve-debug-info.ll
llvm/test/Transforms/PhaseOrdering/X86/loop-idiom-vs-indvars.ll
llvm/test/Transforms/PhaseOrdering/memset-tail.ll