Files
clang-p2996/clang/test/CodeGen/PowerPC/powerpc-c99complex.c
Nikita Popov 158d72d728 [Clang] Set writable and dead_on_unwind attributes on sret arguments (#77116)
Set the writable and dead_on_unwind attributes for sret arguments. These
indicate that the argument points to writable memory (and it's legal to
introduce spurious writes to it on entry to the function) and that the
argument memory will not be used if the call unwinds.

This enables additional MemCpyOpt/DSE/LICM optimizations.
2024-01-11 09:46:54 +01:00

45 lines
3.2 KiB
C

// RUN: %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOLDBL128
// RUN: %clang_cc1 -triple powerpc-unknown-aix -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOLDBL128
// RUN: %clang_cc1 -triple powerpc64-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-LDBL128
// RUN: %clang_cc1 -triple ppc64le-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-LDBL128
// RUN: %clang_cc1 -triple powerpc-unknown-linux -emit-llvm %s -o - | FileCheck %s --check-prefix=PPC32LNX
_Complex float foo1(_Complex float x) {
return x;
// CHECK-LABEL: define{{.*}} { float, float } @foo1(float noundef %x.{{.*}}, float noundef %x.{{.*}}) #0 {
// CHECK: ret { float, float }
// PPC32LNX-LABEL: define{{.*}} void @foo1(ptr dead_on_unwind noalias writable sret({ float, float }) align 4 %agg.result, ptr noundef byval({ float, float }) align 4 %x) #0 {
// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { float, float }, ptr %agg.result, i32 0, i32 0
// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { float, float }, ptr %agg.result, i32 0, i32 1
// PPC32LNX-NEXT: store float %{{.*}}, ptr [[RETREAL]], align 4
// PPC32LNX-NEXT: store float %{{.*}}, ptr [[RETIMAG]], align 4
}
_Complex double foo2(_Complex double x) {
return x;
// CHECK-LABEL: define{{.*}} { double, double } @foo2(double noundef %x.{{.*}}, double noundef %x.{{.*}}) #0 {
// CHECK: ret { double, double }
// PPC32LNX-LABEL: define{{.*}} void @foo2(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %agg.result, ptr noundef byval({ double, double }) align 8 %x) #0 {
// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { double, double }, ptr %agg.result, i32 0, i32 0
// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { double, double }, ptr %agg.result, i32 0, i32 1
// PPC32LNX-NEXT: store double %{{.*}}, ptr [[RETREAL]], align 8
// PPC32LNX-NEXT: store double %{{.*}}, ptr [[RETIMAG]], align 8
}
_Complex long double foo3(_Complex long double x) {
return x;
// CHECK-NOLDBL128-LABEL: define{{.*}} { double, double } @foo3(double noundef %x.{{.*}}, double noundef %x.{{.*}}) #0 {
// CHECK-NOLDBL128: ret { double, double }
// CHECK-LDBL128-LABEL: define{{.*}} { ppc_fp128, ppc_fp128 } @foo3(ppc_fp128 noundef %x.{{.*}}, ppc_fp128 noundef %x.{{.*}}) #0 {
// CHECK-LDBL128: ret { ppc_fp128, ppc_fp128 }
// PPC32LNX-LABEL: define{{.*}} void @foo3(ptr dead_on_unwind noalias writable sret({ ppc_fp128, ppc_fp128 }) align 16 %agg.result, ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 %x) #0 {
// PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 0
// PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 1
// PPC32LNX-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETREAL]], align 16
// PPC32LNX-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETIMAG]], align 16
}