blob: e64cef32e78ec70742b75d523c5ea5469d86cafb [file] [edit]
// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -O2 -target-cpu x86-64-v3 -o - | FileCheck %s
// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -O2 -target-cpu x86-64-v3 -fclang-abi-compat=20 -o - | FileCheck --check-prefix CLANG-20 %s
// RUN: %clang_cc1 %s -triple x86_64-sie-ps4 -emit-llvm -O2 -target-cpu x86-64-v3 -o - | FileCheck --check-prefix CLANG-20 %s
using UInt64x2 = unsigned long long __attribute__((__vector_size__(16), may_alias));
using UInt64x4 = unsigned long long __attribute__((__vector_size__(32), may_alias));
template<int id>
struct XMM1 {
UInt64x2 x;
};
struct XMM2 : XMM1<0>, XMM1<1> {
};
// CHECK: define{{.*}} @_Z3foov({{.*}} [[ARG:%.*]]){{.*}}
// CLANG-20: define{{.*}} <4 x double> @_Z3foov()
// CHECK: entry:
// CHECK-NEXT: store {{.*}}, ptr [[ARG]]{{.*}}
// CHECK-NEXT: [[TMP1:%.*]] = getelementptr {{.*}}, ptr [[ARG]]{{.*}}
// CHECK-NEXT: store {{.*}}, ptr [[TMP1]]{{.*}}
XMM2 foo() {
XMM2 result;
((XMM1<0>*)&result)->x = UInt64x2{1, 2};
((XMM1<1>*)&result)->x = UInt64x2{3, 4};
return result;
}
template<int id>
struct YMM1 {
UInt64x4 x;
};
struct YMM2 : YMM1<0>, YMM1<1> {
};
// CHECK: define{{.*}} @_Z3barv({{.*}} [[ARG:%.*]]){{.*}}
// CLANG-20: define{{.*}} <8 x double> @_Z3barv()
// CHECK: entry:
// CHECK-NEXT: store {{.*}}, ptr [[ARG]]{{.*}}
// CHECK-NEXT: [[TMP1:%.*]] = getelementptr {{.*}}, ptr [[ARG]]{{.*}}
// CHECK-NEXT: store {{.*}}, ptr [[TMP1]]{{.*}}
YMM2 bar() {
YMM2 result;
((YMM1<0>*)&result)->x = UInt64x4{1, 2, 3, 4};
((YMM1<1>*)&result)->x = UInt64x4{5, 6, 7, 8};
return result;
}
// Test that empty base classes do not prevent structs with a single wide
// vector member from being passed/returned in registers (issue #203760).
struct EmptyBase {};
struct YMMWithEmptyBase : EmptyBase {
UInt64x4 x;
};
// A struct with a single 256-bit vector and an empty base should use registers,
// matching the behavior with no base class.
// CHECK: define{{.*}} <4 x i64> @_Z18ymm_empty_base_retv()
// CLANG-20: define{{.*}} <4 x i64> @_Z18ymm_empty_base_retv()
YMMWithEmptyBase ymm_empty_base_ret() { return {}; }
// CHECK: define{{.*}} i64 @_Z19ymm_empty_base_pass16YMMWithEmptyBase(<4 x i64>
// CLANG-20: define{{.*}} i64 @_Z19ymm_empty_base_pass16YMMWithEmptyBase(<4 x i64>
unsigned long long ymm_empty_base_pass(YMMWithEmptyBase x) { return x.x[0]; }