Files
clang-p2996/llvm/test/Transforms/Attributor/ArgumentPromotion/array.ll
Johannes Doerfert c2281f1565 [Attributor] Introduce AAPointerInfo
This patch introduces AAPointerInfo which tracks the uses of a pointer
and places them in "bins" based on their offset from the base and access
size.

As with other AAs, any pointer can be tracked but it is up to the user
to make sense of the results. The user in this patch is AAValueSimplify
and AAPotentialValues which both utilize AAPointerInfo to determine the
value of a load. For now, this is restricted to loads of allocas and
internal globals. Through the use of AAPointerInfo and the "bins" we can
track struct members separately. The users also know that storing only
zeros (at unknown indices) will result in loading only 0 (from unknown
indices). Other than that, the users are flow and context insensitive
(for now).

To deal with the "bins" more easily, AAPointerInfo provides a
forallInterfearingAccesses that applies a callback on all accesses
that might interfere with a given load or store.

Differential Revision: https://reviews.llvm.org/D104432
2021-07-19 22:48:35 -05:00

102 lines
6.9 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
;
; FIXME: The GEP + BC + GEP solution we create is not great but correct.
declare void @use(i32* nocapture readonly %arg)
define void @caller() {
; IS________OPM-LABEL: define {{[^@]+}}@caller() {
; IS________OPM-NEXT: entry:
; IS________OPM-NEXT: [[LEFT:%.*]] = alloca [3 x i32], align 4
; IS________OPM-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [3 x i32], [3 x i32]* [[LEFT]], i64 0, i64 0
; IS________OPM-NEXT: call void @callee(i32* noalias nocapture noundef nonnull readonly align 4 dereferenceable(12) [[ARRAYDECAY]])
; IS________OPM-NEXT: ret void
;
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@caller() {
; IS__TUNIT_NPM-NEXT: entry:
; IS__TUNIT_NPM-NEXT: [[LEFT:%.*]] = alloca [3 x i32], align 4
; IS__TUNIT_NPM-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [3 x i32], [3 x i32]* [[LEFT]], i64 0, i64 0
; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[ARRAYDECAY]] to [3 x i32]*
; IS__TUNIT_NPM-NEXT: [[DOTCAST:%.*]] = bitcast [3 x i32]* [[TMP0]] to i32*
; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[DOTCAST]], align 4
; IS__TUNIT_NPM-NEXT: [[DOT0:%.*]] = getelementptr [3 x i32], [3 x i32]* [[TMP0]], i32 0
; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = bitcast [3 x i32]* [[DOT0]] to i8*
; IS__TUNIT_NPM-NEXT: [[DOT0_B4:%.*]] = getelementptr i8, i8* [[TMP2]], i32 4
; IS__TUNIT_NPM-NEXT: [[DOT0_B4_CAST:%.*]] = bitcast i8* [[DOT0_B4]] to i32*
; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[DOT0_B4_CAST]], align 4
; IS__TUNIT_NPM-NEXT: [[DOT01:%.*]] = getelementptr [3 x i32], [3 x i32]* [[TMP0]], i32 0
; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = bitcast [3 x i32]* [[DOT01]] to i8*
; IS__TUNIT_NPM-NEXT: [[DOT0_B8:%.*]] = getelementptr i8, i8* [[TMP4]], i32 8
; IS__TUNIT_NPM-NEXT: [[DOT0_B8_CAST:%.*]] = bitcast i8* [[DOT0_B8]] to i32*
; IS__TUNIT_NPM-NEXT: [[TMP5:%.*]] = load i32, i32* [[DOT0_B8_CAST]], align 4
; IS__TUNIT_NPM-NEXT: call void @callee(i32 [[TMP1]], i32 [[TMP3]], i32 [[TMP5]])
; IS__TUNIT_NPM-NEXT: ret void
;
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@caller() {
; IS__CGSCC_NPM-NEXT: entry:
; IS__CGSCC_NPM-NEXT: call void @callee(i32 undef, i32 undef, i32 undef)
; IS__CGSCC_NPM-NEXT: ret void
;
entry:
%left = alloca [3 x i32], align 4
%arraydecay = getelementptr inbounds [3 x i32], [3 x i32]* %left, i64 0, i64 0
call void @callee(i32* %arraydecay)
ret void
}
define internal void @callee(i32* noalias %arg) {
; IS________OPM-LABEL: define {{[^@]+}}@callee
; IS________OPM-SAME: (i32* noalias nocapture noundef nonnull readonly align 4 dereferenceable(12) [[ARG:%.*]]) {
; IS________OPM-NEXT: entry:
; IS________OPM-NEXT: call void @use(i32* noalias nocapture noundef nonnull readonly align 4 dereferenceable(12) [[ARG]])
; IS________OPM-NEXT: ret void
;
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callee
; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]]) {
; IS__TUNIT_NPM-NEXT: entry:
; IS__TUNIT_NPM-NEXT: [[ARG_PRIV:%.*]] = alloca [3 x i32], align 4
; IS__TUNIT_NPM-NEXT: [[ARG_PRIV_CAST:%.*]] = bitcast [3 x i32]* [[ARG_PRIV]] to i32*
; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[ARG_PRIV_CAST]], align 4
; IS__TUNIT_NPM-NEXT: [[ARG_PRIV_0:%.*]] = getelementptr [3 x i32], [3 x i32]* [[ARG_PRIV]], i32 0
; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = bitcast [3 x i32]* [[ARG_PRIV_0]] to i8*
; IS__TUNIT_NPM-NEXT: [[ARG_PRIV_0_B4:%.*]] = getelementptr i8, i8* [[TMP3]], i32 4
; IS__TUNIT_NPM-NEXT: [[ARG_PRIV_0_B4_CAST:%.*]] = bitcast i8* [[ARG_PRIV_0_B4]] to i32*
; IS__TUNIT_NPM-NEXT: store i32 [[TMP1]], i32* [[ARG_PRIV_0_B4_CAST]], align 4
; IS__TUNIT_NPM-NEXT: [[ARG_PRIV_01:%.*]] = getelementptr [3 x i32], [3 x i32]* [[ARG_PRIV]], i32 0
; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = bitcast [3 x i32]* [[ARG_PRIV_01]] to i8*
; IS__TUNIT_NPM-NEXT: [[ARG_PRIV_0_B8:%.*]] = getelementptr i8, i8* [[TMP4]], i32 8
; IS__TUNIT_NPM-NEXT: [[ARG_PRIV_0_B8_CAST:%.*]] = bitcast i8* [[ARG_PRIV_0_B8]] to i32*
; IS__TUNIT_NPM-NEXT: store i32 [[TMP2]], i32* [[ARG_PRIV_0_B8_CAST]], align 4
; IS__TUNIT_NPM-NEXT: [[TMP5:%.*]] = bitcast [3 x i32]* [[ARG_PRIV]] to i32*
; IS__TUNIT_NPM-NEXT: call void @use(i32* noalias nocapture noundef nonnull readonly align 4 dereferenceable(12) [[TMP5]])
; IS__TUNIT_NPM-NEXT: ret void
;
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@callee
; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]]) {
; IS__CGSCC_NPM-NEXT: entry:
; IS__CGSCC_NPM-NEXT: [[ARG_PRIV:%.*]] = alloca [3 x i32], align 4
; IS__CGSCC_NPM-NEXT: [[ARG_PRIV_CAST:%.*]] = bitcast [3 x i32]* [[ARG_PRIV]] to i32*
; IS__CGSCC_NPM-NEXT: store i32 undef, i32* [[ARG_PRIV_CAST]], align 4
; IS__CGSCC_NPM-NEXT: [[ARG_PRIV_0:%.*]] = getelementptr [3 x i32], [3 x i32]* [[ARG_PRIV]], i32 0
; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = bitcast [3 x i32]* [[ARG_PRIV_0]] to i8*
; IS__CGSCC_NPM-NEXT: [[ARG_PRIV_0_B4:%.*]] = getelementptr i8, i8* [[TMP3]], i32 4
; IS__CGSCC_NPM-NEXT: [[ARG_PRIV_0_B4_CAST:%.*]] = bitcast i8* [[ARG_PRIV_0_B4]] to i32*
; IS__CGSCC_NPM-NEXT: store i32 undef, i32* [[ARG_PRIV_0_B4_CAST]], align 4
; IS__CGSCC_NPM-NEXT: [[ARG_PRIV_01:%.*]] = getelementptr [3 x i32], [3 x i32]* [[ARG_PRIV]], i32 0
; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = bitcast [3 x i32]* [[ARG_PRIV_01]] to i8*
; IS__CGSCC_NPM-NEXT: [[ARG_PRIV_0_B8:%.*]] = getelementptr i8, i8* [[TMP4]], i32 8
; IS__CGSCC_NPM-NEXT: [[ARG_PRIV_0_B8_CAST:%.*]] = bitcast i8* [[ARG_PRIV_0_B8]] to i32*
; IS__CGSCC_NPM-NEXT: store i32 undef, i32* [[ARG_PRIV_0_B8_CAST]], align 4
; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = bitcast [3 x i32]* [[ARG_PRIV]] to i32*
; IS__CGSCC_NPM-NEXT: call void @use(i32* noalias nocapture noundef nonnull readonly align 4 dereferenceable(12) [[TMP5]])
; IS__CGSCC_NPM-NEXT: ret void
;
entry:
call void @use(i32* %arg)
ret void
}