CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
489 lines
19 KiB
C
489 lines
19 KiB
C
// RUN: %clang_cc1 -triple s390x-ibm-zos \
|
|
// RUN: -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKNOVEC
|
|
// RUN: %clang_cc1 -triple s390x-ibm-zos -target-feature +vector \
|
|
// RUN: -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKVEC
|
|
// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu z13 \
|
|
// RUN: -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKVEC
|
|
// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu arch11 \
|
|
// RUN: -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKVEC
|
|
// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu z14 \
|
|
// RUN: -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKVEC
|
|
// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu arch12 \
|
|
// RUN: -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKVEC
|
|
// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu z15 \
|
|
// RUN: -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKVEC
|
|
// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu arch13 \
|
|
// RUN: -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKVEC
|
|
|
|
// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu arch11 \
|
|
// RUN: -DTEST_VEC -fzvector -emit-llvm -no-enable-noundef-analysis \
|
|
// RUN: -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKVEC,CHECK-ZVEC
|
|
|
|
// Scalar types
|
|
|
|
signed char pass_schar(signed char arg) { return arg; }
|
|
// CHECK-LABEL: define signext i8 @pass_schar(i8 signext %{{.*}})
|
|
|
|
unsigned char pass_uchar(unsigned char arg) { return arg; }
|
|
// CHECK-LABEL: define zeroext i8 @pass_uchar(i8 zeroext %{{.*}})
|
|
|
|
short pass_short(short arg) { return arg; }
|
|
// CHECK-LABEL: define signext i16 @pass_short(i16 signext %{{.*}})
|
|
|
|
int pass_int(int arg) { return arg; }
|
|
// CHECK-LABEL: define signext i32 @pass_int(i32 signext %{{.*}})
|
|
|
|
long pass_long(long arg) { return arg; }
|
|
// CHECK-LABEL: define signext i64 @pass_long(i64 signext %{{.*}})
|
|
|
|
long long pass_longlong(long long arg) { return arg; }
|
|
// CHECK-LABEL: define i64 @pass_longlong(i64 %{{.*}})
|
|
|
|
float pass_float(float arg) { return arg; }
|
|
// CHECK-LABEL: define float @pass_float(float %{{.*}})
|
|
|
|
double pass_double(double arg) { return arg; }
|
|
// CHECK-LABEL: define double @pass_double(double %{{.*}})
|
|
|
|
long double pass_longdouble(long double arg) { return arg; }
|
|
// CHECK-LABEL: define fp128 @pass_longdouble(fp128 %{{.*}})
|
|
|
|
enum Color { Red, Blue };
|
|
enum Color pass_enum(enum Color arg) { return arg; }
|
|
// CHECK-LABEL: define zeroext i32 @pass_enum(i32 zeroext %{{.*}})
|
|
|
|
#ifdef TEST_VEC
|
|
vector unsigned int pass_vector(vector unsigned int arg) { return arg; };
|
|
// CHECK-ZVEC-LABEL: define <4 x i32> @pass_vector(<4 x i32> %{{.*}})
|
|
|
|
struct SingleVec { vector unsigned int v; };
|
|
struct SingleVec pass_SingleVec_agg(struct SingleVec arg) { return arg; };
|
|
// CHECK-ZVEC-LABEL: define inreg [2 x i64] @pass_SingleVec_agg([2 x i64] %{{.*}})
|
|
#endif
|
|
|
|
// Complex types
|
|
|
|
_Complex float pass_complex_float(_Complex float arg) { return arg; }
|
|
// CHECK-LABEL: define { float, float } @pass_complex_float({ float, float } %{{.*}})
|
|
|
|
_Complex double pass_complex_double(_Complex double arg) { return arg; }
|
|
// CHECK-LABEL: define { double, double } @pass_complex_double({ double, double } %{{.*}})
|
|
|
|
_Complex long double pass_complex_longdouble(_Complex long double arg) { return arg; }
|
|
// CHECK-LABEL: define { fp128, fp128 } @pass_complex_longdouble({ fp128, fp128 } %{{.*}})
|
|
|
|
// Verify that the following are complex-like types
|
|
struct complexlike_float { float re, im; };
|
|
struct complexlike_float pass_complexlike_float2(struct complexlike_float arg) { return arg; }
|
|
// CHECK-LABEL: define %struct.complexlike_float @pass_complexlike_float2({ float, float } %{{.*}})
|
|
|
|
struct complexlike_double { double re, im; };
|
|
struct complexlike_double pass_complexlike_double(struct complexlike_double arg) { return arg; }
|
|
// CHECK-LABEL: define %struct.complexlike_double @pass_complexlike_double({ double, double } %{{.*}})
|
|
|
|
struct complexlike_longdouble { long double re, im; };
|
|
struct complexlike_longdouble pass_complexlike_longdouble(struct complexlike_longdouble arg) { return arg; }
|
|
// CHECK-LABEL: define %struct.complexlike_longdouble @pass_complexlike_longdouble({ fp128, fp128 } %{{.*}})
|
|
|
|
struct single_element_float { float f; };
|
|
struct complexlike_struct {
|
|
struct single_element_float x;
|
|
struct single_element_float y;
|
|
};
|
|
struct complexlike_struct pass_complexlike_struct(struct complexlike_struct arg) { return arg; }
|
|
// CHECK-LABEL: define %struct.complexlike_struct @pass_complexlike_struct({ float, float } %{{.*}})
|
|
|
|
struct single_element_float_arr {
|
|
unsigned int :0;
|
|
float f[1];
|
|
};
|
|
struct complexlike_struct2 {
|
|
struct single_element_float_arr x;
|
|
struct single_element_float_arr y;
|
|
};
|
|
struct complexlike_struct2 pass_complexlike_struct2(struct complexlike_struct2 arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_complexlike_struct2(i64 %{{.*}})
|
|
|
|
struct float_and_empties {
|
|
struct S {} s;
|
|
int a[0];
|
|
float f;
|
|
};
|
|
struct complexlike_struct3 {
|
|
struct float_and_empties x;
|
|
struct float_and_empties y;
|
|
};
|
|
struct complexlike_struct3 pass_complexlike_struct3(struct complexlike_struct3 arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_complexlike_struct3(i64 %{{.*}})
|
|
|
|
union two_float_union { float a; float b; };
|
|
struct complexlike_struct_with_union {
|
|
float a;
|
|
union two_float_union b;
|
|
};
|
|
struct complexlike_struct_with_union pass_complexlike_struct_with_union(struct complexlike_struct_with_union arg) { return arg; }
|
|
// CHECK-LABEL: struct.complexlike_struct_with_union @pass_complexlike_struct_with_union({ float, float } %{{.*}})
|
|
|
|
// structures with one field as complex type are not considered complex types.
|
|
struct single_complex_struct {
|
|
_Complex float f;
|
|
};
|
|
struct single_complex_struct pass_single_complex_struct(struct single_complex_struct arg) {return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_single_complex_struct(i64 %{{.*}})
|
|
|
|
// Structures with extra padding are not considered complex types.
|
|
struct complexlike_float_padded1 {
|
|
float x __attribute__((aligned(8)));
|
|
float y __attribute__((aligned(8)));
|
|
};
|
|
struct complexlike_float_padded1 pass_complexlike_float_padded1(struct complexlike_float_padded1 arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [2 x i64] @pass_complexlike_float_padded1([2 x i64] %{{.*}})
|
|
|
|
struct complexlike_float_padded2 {
|
|
float x;
|
|
float y;
|
|
} __attribute__((aligned(16)));
|
|
struct complexlike_float_padded2 pass_complexlike_float_padded2(struct complexlike_float_padded2 arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [2 x i64] @pass_complexlike_float_padded2([2 x i64] %{{.*}})
|
|
|
|
|
|
struct single_padded_struct {
|
|
float f;
|
|
unsigned int :2;
|
|
};
|
|
struct complexlike_float_padded3 {
|
|
struct single_padded_struct x;
|
|
struct single_padded_struct y;
|
|
};
|
|
struct complexlike_float_padded3 pass_complexlike_float_padded3(struct complexlike_float_padded3 arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [2 x i64] @pass_complexlike_float_padded3([2 x i64] %{{.*}})
|
|
|
|
struct multi_element_float_arr { float f[2]; };
|
|
struct complexlike_struct4 {
|
|
struct multi_element_float_arr x;
|
|
struct multi_element_float_arr y;
|
|
};
|
|
struct complexlike_struct4 pass_complexlike_struct4(struct complexlike_struct4 arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [2 x i64] @pass_complexlike_struct4([2 x i64] %{{.*}})
|
|
|
|
typedef double align32_double __attribute__((aligned(32)));
|
|
struct complexlike_double_padded {
|
|
align32_double x;
|
|
double y;
|
|
};
|
|
struct complexlike_double_padded pass_complexlike_double_padded(struct complexlike_double_padded arg) { return arg; }
|
|
// CHECK-LABEL: define void @pass_complexlike_double_padded(ptr {{.*}} sret(%struct.complexlike_double_padded) align 32 %{{.*}}, [4 x i64] %{{.*}})
|
|
|
|
struct complexlike_double_padded2 {
|
|
__attribute__((aligned(256))) align32_double x; // attribute on both type and typedef
|
|
double y;
|
|
};
|
|
|
|
struct complexlike_double_padded2 pass_complexlike_double_padded2(struct complexlike_double_padded2 arg) { return arg; }
|
|
// CHECK-LABEL: define void @pass_complexlike_double_padded2(ptr {{.*}} sret(%struct.complexlike_double_padded2) align 256 %{{.*}}, [32 x i64] %{{.*}})
|
|
|
|
struct complexlike_double_padded3 {
|
|
__attribute__((aligned(32))) double x; // attribute on type only
|
|
double y;
|
|
};
|
|
struct complexlike_double_padded3 pass_complexlike_double_padded3(struct complexlike_double_padded3 arg) { return arg; }
|
|
// CHECK-LABEL: define void @pass_complexlike_double_padded3(ptr {{.*}} sret(%struct.complexlike_double_padded3) align 32 %{{.*}}, [4 x i64] %{{.*}})
|
|
|
|
|
|
// Aggregate types
|
|
|
|
struct agg_1byte { char a[1]; };
|
|
struct agg_1byte pass_agg_1byte(struct agg_1byte arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_agg_1byte(i64 %{{.*}})
|
|
|
|
struct agg_2byte { char a[2]; };
|
|
struct agg_2byte pass_agg_2byte(struct agg_2byte arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_agg_2byte(i64 %{{.*}})
|
|
|
|
struct agg_3byte { char a[3]; };
|
|
struct agg_3byte pass_agg_3byte(struct agg_3byte arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_agg_3byte(i64 %{{.*}})
|
|
|
|
struct agg_4byte { char a[4]; };
|
|
struct agg_4byte pass_agg_4byte(struct agg_4byte arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_agg_4byte(i64 %{{.*}})
|
|
|
|
struct agg_5byte { char a[5]; };
|
|
struct agg_5byte pass_agg_5byte(struct agg_5byte arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_agg_5byte(i64 %{{.*}})
|
|
|
|
struct agg_6byte { char a[6]; };
|
|
struct agg_6byte pass_agg_6byte(struct agg_6byte arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_agg_6byte(i64 %{{.*}})
|
|
|
|
struct agg_7byte { char a[7]; };
|
|
struct agg_7byte pass_agg_7byte(struct agg_7byte arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_agg_7byte(i64 %{{.*}})
|
|
|
|
struct agg_8byte { char a[8]; };
|
|
struct agg_8byte pass_agg_8byte(struct agg_8byte arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_agg_8byte(i64 %{{.*}})
|
|
|
|
struct agg_9byte { char a[9]; };
|
|
struct agg_9byte pass_agg_9byte(struct agg_9byte arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [2 x i64] @pass_agg_9byte([2 x i64] %{{.*}})
|
|
|
|
struct agg_16byte { char a[16]; };
|
|
struct agg_16byte pass_agg_16byte(struct agg_16byte arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [2 x i64] @pass_agg_16byte([2 x i64] %{{.*}})
|
|
|
|
struct agg_24byte { char a[24]; };
|
|
struct agg_24byte pass_agg_24byte(struct agg_24byte arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [3 x i64] @pass_agg_24byte([3 x i64] %{{.*}})
|
|
|
|
struct agg_25byte { char a[25]; };
|
|
struct agg_25byte pass_agg_25byte(struct agg_25byte arg) { return arg; }
|
|
// CHECK-LABEL: define void @pass_agg_25byte(ptr dead_on_unwind noalias writable sret{{.*}} align 1 %{{.*}}, [4 x i64] %{{.*}})
|
|
|
|
// Check that a float-like aggregate type is really passed as aggregate
|
|
struct agg_float { float a; };
|
|
struct agg_float pass_agg_float(struct agg_float arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_agg_float(i64 %{{.*}})
|
|
|
|
// Verify that the following are *not* float-like aggregate types
|
|
|
|
struct agg_nofloat2 { float a; int b; };
|
|
struct agg_nofloat2 pass_agg_nofloat2(struct agg_nofloat2 arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_agg_nofloat2(i64 %{{.*}})
|
|
|
|
struct agg_nofloat3 { float a; int : 0; };
|
|
struct agg_nofloat3 pass_agg_nofloat3(struct agg_nofloat3 arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_agg_nofloat3(i64 %{{.*}})
|
|
|
|
char * pass_pointer(char * arg) { return arg; }
|
|
// CHECK-LABEL: define ptr @pass_pointer(ptr %{{.*}})
|
|
|
|
typedef int vecint __attribute__ ((vector_size(16)));
|
|
vecint pass_vector_type(vecint arg) { return arg; }
|
|
// CHECKNOVEC-LABEL: define <4 x i32> @pass_vector_type(ptr dead_on_return %{{.*}})
|
|
// CHECKVEC-LABEL: define <4 x i32> @pass_vector_type(<4 x i32> %{{.*}})
|
|
|
|
// Union with just a single float element are treated as float inside a struct.
|
|
union u1 {
|
|
float m1, m2;
|
|
};
|
|
|
|
union u2 {
|
|
float m1;
|
|
union u1 m2;
|
|
};
|
|
|
|
union u3 {
|
|
float m1;
|
|
int m2;
|
|
};
|
|
|
|
struct complexlike_union1 {
|
|
float m1;
|
|
union u1 m2;
|
|
};
|
|
|
|
struct complexlike_union2 {
|
|
float m1;
|
|
union u2 m2;
|
|
};
|
|
|
|
struct complexlike_union3 {
|
|
union u1 m1;
|
|
union u2 m2;
|
|
};
|
|
|
|
struct normal_struct {
|
|
float m1;
|
|
union u3 m2;
|
|
};
|
|
|
|
struct complexlike_union1 pass_complexlike_union1(struct complexlike_union1 arg) { return arg; }
|
|
// CHECK-LABEL: define %struct.complexlike_union1 @pass_complexlike_union1({ float, float } %{{.*}})
|
|
|
|
struct complexlike_union2 pass_complexlike_union2(struct complexlike_union2 arg) { return arg; }
|
|
// CHECK-LABEL: define %struct.complexlike_union2 @pass_complexlike_union2({ float, float } %{{.*}})
|
|
|
|
struct complexlike_union3 pass_complexlike_union3(struct complexlike_union3 arg) { return arg; }
|
|
// CHECK-LABEL: define %struct.complexlike_union3 @pass_complexlike_union3({ float, float } %{{.*}})
|
|
|
|
union u1 pass_union1(union u1 arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_union1(i64 %{{.*}})
|
|
|
|
union u2 pass_union2(union u2 arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_union2(i64 %{{.*}})
|
|
|
|
struct normal_struct pass_normal_struct(struct normal_struct arg) { return arg; }
|
|
// CHECK-LABEL: define inreg [1 x i64] @pass_normal_struct(i64 %{{.*}})
|
|
|
|
// ============================================================================
|
|
// Complex-like struct using nested typedefs with alignment attributes
|
|
// applied at different typedef layers.
|
|
// ============================================================================
|
|
typedef double raw_double;
|
|
|
|
// ============================================================================
|
|
// Alignment at first typedef layer
|
|
// ============================================================================
|
|
typedef align32_double nested_A;
|
|
|
|
struct S_A {
|
|
nested_A re;
|
|
double im;
|
|
};
|
|
|
|
struct S_A pass_S_A(struct S_A arg) { return arg; }
|
|
// CHECK-LABEL: define void @pass_S_A(
|
|
// CHECK-SAME: ptr {{.*}} sret(%struct.S_A) align 32
|
|
// CHECK-SAME: [4 x i64]
|
|
// CHECK: ret void
|
|
|
|
// ============================================================================
|
|
// Alignment applied at middle typedef layer
|
|
// ============================================================================
|
|
typedef double raw_B;
|
|
typedef raw_B middle_B __attribute__((aligned(32)));
|
|
typedef middle_B nested_B;
|
|
|
|
struct S_B {
|
|
double im;
|
|
nested_B re;
|
|
};
|
|
|
|
struct S_B pass_S_B(struct S_B arg) { return arg; }
|
|
// CHECK-LABEL: define void @pass_S_B(
|
|
// CHECK-SAME: ptr {{.*}} sret(%struct.S_B) align 32
|
|
// CHECK-SAME: [8 x i64]
|
|
// CHECK: ret void
|
|
|
|
// ============================================================================
|
|
// Alignment applied only at deepest typedef
|
|
// ============================================================================
|
|
typedef float raw_C0;
|
|
typedef raw_C0 raw_C1;
|
|
typedef raw_C1 raw_C2;
|
|
typedef raw_C2 nested_C_final __attribute__((aligned(32)));
|
|
|
|
struct S_C {
|
|
nested_C_final re;
|
|
float im;
|
|
};
|
|
|
|
struct S_C pass_S_C(struct S_C arg) { return arg; }
|
|
// CHECK-LABEL: define void @pass_S_C(
|
|
// CHECK-SAME: ptr {{.*}} sret(%struct.S_C) align 32
|
|
// CHECK-SAME: [4 x i64]
|
|
// CHECK: ret void
|
|
|
|
// ============================================================================
|
|
// Alignment on an intermediate typedef in a deeper chain
|
|
// ============================================================================
|
|
typedef float raw_D0;
|
|
typedef raw_D0 nested_D1;
|
|
typedef nested_D1 nested_D2 __attribute__((aligned(32)));
|
|
typedef nested_D2 nested_D3;
|
|
typedef nested_D3 nested_D;
|
|
|
|
struct S_D {
|
|
float im;
|
|
nested_D re;
|
|
};
|
|
|
|
struct S_D pass_S_D(struct S_D arg) { return arg; }
|
|
// CHECK-LABEL: define void @pass_S_D(
|
|
// CHECK-SAME: ptr {{.*}} sret(%struct.S_D) align 32
|
|
// CHECK-SAME: [8 x i64]
|
|
// CHECK: ret void
|
|
|
|
// ============================================================================
|
|
// NO alignment anywhere in the typedef chain
|
|
// Should NOT get 32-byte ABI alignment.
|
|
// ============================================================================
|
|
typedef double nested_E1;
|
|
typedef nested_E1 nested_E2;
|
|
typedef nested_E2 nested_E;
|
|
|
|
struct S_E {
|
|
nested_E re;
|
|
double im;
|
|
};
|
|
|
|
struct S_E pass_S_E(struct S_E arg) { return arg; }
|
|
// CHECK-LABEL: define %struct.S_E @pass_S_E(
|
|
// CHECK-SAME:{ double, double } %{{.*}})
|
|
// CHECK: ret %struct.S_E
|
|
|
|
|
|
// ============================================================================
|
|
// Over-aligned second field introduces internal padding, so the record
|
|
// cannot be treated as a complex-like `{ double, double }` and must be
|
|
// returned indirectly with 16-byte alignment.
|
|
// ============================================================================
|
|
|
|
struct Bad1 {
|
|
double re;
|
|
double im __attribute__((aligned(16)));;
|
|
};
|
|
struct Bad1 pass_Bad1(struct Bad1 arg) { return arg; }
|
|
// CHECK-LABEL: define void @pass_Bad1(ptr dead_on_unwind noalias writable sret({{.*}}) align 16 %agg.result, [4 x i64] %{{.*}})
|
|
|
|
|
|
// ============================================================================
|
|
// Stronger over-alignment on the second field further increases the required
|
|
// alignment and argument size, forcing indirect return with 32-byte alignment.
|
|
// ============================================================================
|
|
|
|
struct Bad2 {
|
|
double re;
|
|
double im __attribute__((aligned(32)));;
|
|
};
|
|
struct Bad2 pass_Bad2(struct Bad2 arg) { return arg; }
|
|
// CHECK-LABEL: define void @pass_Bad2(ptr dead_on_unwind noalias writable sret(%{{.*}}) align 32 %agg.result, [8 x i64] %{{.*}})
|
|
|
|
// ============================================================================
|
|
// Over-alignment on the first field prevents complex classification, but the
|
|
// record still fits in registers and is returned directly as a plain aggregate.
|
|
// ============================================================================
|
|
struct Bad3 {
|
|
double re __attribute__((aligned(16)));
|
|
double im;
|
|
};
|
|
struct Bad3 pass_Bad3(struct Bad3 arg) { return arg; }
|
|
// CHECK-LABEL: define %struct.Bad3 @pass_Bad3({ double, double } %{{.*}})
|
|
|
|
|
|
// ============================================================================
|
|
// Strong over-alignment on the first field raises the required alignment of the
|
|
// whole record, forcing indirect return and disqualifying complex-like passing.
|
|
// ============================================================================
|
|
struct Bad4 {
|
|
double re __attribute__((aligned(32)));
|
|
double im;
|
|
};
|
|
struct Bad4 pass_Bad4(struct Bad4 arg) { return arg; }
|
|
// CHECK-LABEL: define void @pass_Bad4(ptr dead_on_unwind noalias writable sret(%{{.*}}) align 32 %agg.result, [4 x i64] %{{.*}})
|
|
|
|
|
|
// ==================================================================
|
|
// Verify that transparent unions are passed like their first member.
|
|
// ==================================================================
|
|
union tu_char { char a; } __attribute__((transparent_union));
|
|
union tu_char pass_tu_char(union tu_char arg) { return arg; }
|
|
// CHECK-LABEL: define{{.*}} i8 @pass_tu_char(i8 signext %{{.*}})
|
|
|
|
union tu_short { short a; } __attribute__((transparent_union));
|
|
union tu_short pass_tu_short(union tu_short arg) { return arg; }
|
|
// CHECK-LABEL: define{{.*}} i16 @pass_tu_short(i16 signext %{{.*}})
|
|
|
|
union tu_int { int a; } __attribute__((transparent_union));
|
|
union tu_int pass_tu_int(union tu_int arg) { return arg; }
|
|
// CHECK-LABEL: define{{.*}} i32 @pass_tu_int(i32 signext %{{.*}})
|
|
|
|
union tu_long { long a; } __attribute__((transparent_union));
|
|
union tu_long pass_tu_long(union tu_long arg) { return arg; }
|
|
// CHECK-LABEL: define{{.*}} i64 @pass_tu_long(i64 signext %{{.*}})
|
|
|
|
union tu_ptr { void *a; } __attribute__((transparent_union));
|
|
union tu_ptr pass_tu_ptr(union tu_ptr arg) { return arg; }
|
|
// CHECK-LABEL: define{{.*}} ptr @pass_tu_ptr(ptr %{{.*}})
|