llvm-project/clang/test/CodeGenCXX/auto-var-init-max-size.cpp
Jan Voung 0cf1e662b1
[clang] Skip auto-init on scalar vars that have a non-constant Init and no self-ref (#94642)
In that scalar case, the Init should initialize the auto var before use. The Init might use uninitialized memory from other sources (e.g., heap) but auto-init did not help us in that case because the auto-init would have been overwritten by the Init before use.

For non-scalars e.g., classes, the Init expr might be a ctor call that leaves uninitialized members, so we leave the auto-init there.

The motivation is to have less IR for the optimizer to later remove, which may not be until a fairly late pass (DSE) or may not get optimized in lower optimization levels like O1 (no DSE) or sometimes due to derefinement.
This is ~10% less left-over auto-init in O1 in a few examples checked.
2024-06-24 08:46:31 -04:00

102 lines
8.3 KiB
C++

// Pattern related max size tests: 1, 1024, 4096
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=pattern -ftrivial-auto-var-init-max-size=1 %s -emit-llvm -o - | FileCheck -check-prefix=PATTERN-COMMON -check-prefix=PATTERN-MAX-1 %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=pattern -ftrivial-auto-var-init-max-size=1024 %s -emit-llvm -o - | FileCheck -check-prefix=PATTERN-COMMON -check-prefix=PATTERN-MAX-1024 %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=pattern -ftrivial-auto-var-init-max-size=4096 %s -emit-llvm -o - | FileCheck -check-prefix=PATTERN-COMMON -check-prefix=PATTERN-MAX-4096 %s
//
// Zero related max size tests: 1, 1024, 4096
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=zero -ftrivial-auto-var-init-max-size=1 %s -emit-llvm -o - | FileCheck -check-prefix=ZERO-COMMON -check-prefix=ZERO-MAX-1 %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=zero -ftrivial-auto-var-init-max-size=1024 %s -emit-llvm -o - | FileCheck -check-prefix=ZERO-COMMON -check-prefix=ZERO-MAX-1024 %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ftrivial-auto-var-init=zero -ftrivial-auto-var-init-max-size=4096 %s -emit-llvm -o - | FileCheck -check-prefix=ZERO-COMMON -check-prefix=ZERO-MAX-4096 %s
struct Foo {
int x; // we should try to make sure X is initialized.
char buff[1024]; // this one is fine to skip
};
int foo(unsigned n) {
bool var_size_1;
long var_size_8_init = 123;
long var_size_8_noinit;
long var_size_8_init_later;
void *var_size_8p;
int var_size_1024[256];
Foo var_size_1028;
int var_size_4096[1024];
// VLA, non-constant size
int var_vla[n];
// builtin, non-constant size
var_size_8p = __builtin_alloca(sizeof(unsigned long long) * n);
var_size_8_init_later = 456;
// There are 10 variables: var_size_1, var_size_8_init, var_size_8_noinit,
// var_size_8_init_later, var_size_8p, var_size_1024,
// var_size_1028, var_size_4096, var_vla, and a builtin anonymous var ("%5").
// - Doesn't need auto-init: var_size_8_init
// - COMMON (auto-init regardless of the max size): "var_vla", and "%5"
// - Max size 1: "var_size_1"
// - Max size 1024: "var_size_1", "var_size_8_noinit", "var_size_8_init_later", "var_size_8p", "var_size_1024"
// - Max size 4096: "var_size_1", "var_size_8_noinit", "var_size_8_init_later", "var_size_8p", "var_size_1024",
// "var_size_1028", "var_size_4096"
//
// PATTERN-MAX-1: store i8 -86, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-1-NEXT: store i64 123, ptr %var_size_8_init, align 8
// PATTERN-MAX-1-NOT: store i64 -6148914691236517206, ptr %var_size_8_noinit, align 8, !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-1-NOT: store i64 -6148914691236517206, ptr %var_size_8_init_later, align 8, !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-1-NOT: store ptr inttoptr (i64 -6148914691236517206 to ptr), ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 16 %var_size_1024, i8 -86, i64 1024, i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 4 %var_size_1028, i8 -86, i64 1028, i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 -86, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-1024: store i8 -86, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-1024-NEXT: store i64 123, ptr %var_size_8_init, align 8
// PATTERN-MAX-1024: store i64 -6148914691236517206, ptr %var_size_8_noinit, align 8, !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-1024: store i64 -6148914691236517206, ptr %var_size_8_init_later, align 8, !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-1024: store ptr inttoptr (i64 -6148914691236517206 to ptr), ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-1024: call void @llvm.memset.p0.i64(ptr align 16 %var_size_1024, i8 -86, i64 1024, i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-1024-NOT: call void @llvm.memset.p0.i64(ptr align 4 %var_size_1028, i8 -86, i64 1028, i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-1024-NOT: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 -86, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-4096: store i8 -86, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-4096-NEXT: store i64 123, ptr %var_size_8_init, align 8
// PATTERN-MAX-4096: store i64 -6148914691236517206, ptr %var_size_8_noinit, align 8, !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-4096: store i64 -6148914691236517206, ptr %var_size_8_init_later, align 8, !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-4096: store ptr inttoptr (i64 -6148914691236517206 to ptr), ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-4096: call void @llvm.memset.p0.i64(ptr align 16 %var_size_1024, i8 -86, i64 1024, i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-4096: call void @llvm.memset.p0.i64(ptr align 4 %var_size_1028, i8 -86, i64 1028, i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-MAX-4096: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 -86, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-COMMON: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %vla.cur, ptr align 4 @__const._Z3fooj.var_vla, i64 4, i1 false), !annotation [[AUTO_INIT:!.+]]
// PATTERN-COMMON: call void @llvm.memset.p0.i64(ptr align 16 %5, i8 -86, i64 %mul, i1 false), !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1: store i8 0, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1-NEXT: store i64 123, ptr %var_size_8_init, align 8
// ZERO-MAX-1-NOT: store i64 0, ptr %var_size_8_noinit, align 8, !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1-NOT: store i64 0, ptr %var_size_8_init_later, align 8, !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1-NOT: store ptr null, ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 16 %var_size_1024, i8 0, i64 1024, i1 false), !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 4 %var_size_1028, i8 0, i64 1028, i1 false), !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1-NOT: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 0, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1024: store i8 0, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1024-NEXT: store i64 123, ptr %var_size_8_init, align 8
// ZERO-MAX-1024: store i64 0, ptr %var_size_8_noinit, align 8, !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1024: store i64 0, ptr %var_size_8_init_later, align 8, !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1024: store ptr null, ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1024: call void @llvm.memset.p0.i64(ptr align 16 %var_size_1024, i8 0, i64 1024, i1 false), !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1024-NOT: call void @llvm.memset.p0.i64(ptr align 4 %var_size_1028, i8 0, i64 1028, i1 false), !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-1024-NOT: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 0, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-4096: store i8 0, ptr %var_size_1, align 1, !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-4096-NEXT: store i64 123, ptr %var_size_8_init, align 8
// ZERO-MAX-4096: store i64 0, ptr %var_size_8_noinit, align 8, !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-4096: store i64 0, ptr %var_size_8_init_later, align 8, !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-4096: store ptr null, ptr %var_size_8p, align 8, !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-4096: call void @llvm.memset.p0.i64(ptr align 16 %var_size_1024, i8 0, i64 1024, i1 false), !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-4096: call void @llvm.memset.p0.i64(ptr align 4 %var_size_1028, i8 0, i64 1028, i1 false), !annotation [[AUTO_INIT:!.+]]
// ZERO-MAX-4096: call void @llvm.memset.p0.i64(ptr align 16 %var_size_4096, i8 0, i64 4096, i1 false), !annotation [[AUTO_INIT:!.+]]
// ZERO-COMMON: call void @llvm.memset.p0.i64(ptr align 16 %vla, i8 0, i64 %3, i1 false), !annotation [[AUTO_INIT:!.+]]
// ZERO-COMMON: call void @llvm.memset.p0.i64(ptr align 16 %5, i8 0, i64 %mul, i1 false), !annotation [[AUTO_INIT:!.+]]
return 0;
}