blob: 22964a5f4548c8b50e16e684c9dff9b88fa36ca6 [file] [edit]
// RUN: %clang_cc1 -triple i386-pc-win32 -fenable-matrix -ffreestanding \
// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,HFA,X86
// RUN: %clang_cc1 -triple x86_64-pc-win32 -fenable-matrix -ffreestanding \
// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,HFA,X64
// RUN: %clang_cc1 -triple i386-pc-win32 -fenable-matrix -ffreestanding \
// RUN: -fclang-abi-compat=23 -emit-llvm -o - %s | FileCheck %s \
// RUN: --check-prefixes=CHECK,COMPAT23,X86,X86-COMPAT23
// RUN: %clang_cc1 -triple x86_64-pc-win32 -fenable-matrix -ffreestanding \
// RUN: -fclang-abi-compat=23 -emit-llvm -o - %s | FileCheck %s \
// RUN: --check-prefixes=CHECK,COMPAT23,X64,X64-COMPAT23
// x86/x86_64 __vectorcall HVA classification of Clang matrix types. Matrix
// types are flattened like arrays (T NxM -> N*M members of T). vectorcall
// also applies that check to the matrix type itself, so a bare f2x2 is an
// HVA of four floats (passed inreg) after the flattening change.
//
// -fclang-abi-compat=23 does not flatten matrices.
typedef float __attribute__((matrix_type(2, 2))) f2x2;
typedef float __attribute__((matrix_type(3, 3))) f3x3;
typedef double __attribute__((matrix_type(2, 2))) d2x2;
typedef int __attribute__((matrix_type(2, 2))) i2x2;
struct MatrixStruct {
f2x2 m;
};
struct ArrayStruct {
float arr[4];
};
struct LargeMatrixStruct {
f3x3 m;
};
struct DoubleMatrixStruct {
d2x2 m;
};
struct IntMatrixStruct {
i2x2 m;
};
struct OverAlignedMatrixStruct {
f2x2 m;
} __attribute__((aligned(32)));
void __vectorcall take_matrix(f2x2 m) {}
// HFA: define{{.*}} x86_vectorcallcc void @"\01take_matrix@@16"(<4 x float> inreg noundef %{{.*}})
// COMPAT23: define{{.*}} x86_vectorcallcc void @"\01take_matrix@@16"(<4 x float> noundef %{{.*}})
f2x2 __vectorcall return_matrix(void) {
f2x2 m;
return m;
}
// CHECK: define{{.*}} x86_vectorcallcc <4 x float> @"\01return_matrix@@0"()
// Four floats, no padding -> HVA passed inreg. Compat 23 uses byval (x86)
// or an indirect pointer (x64).
void __vectorcall take_matrix_struct(struct MatrixStruct s) {}
// HFA: define{{.*}} x86_vectorcallcc void @"\01take_matrix_struct@@16"(%struct.MatrixStruct inreg %{{.*}})
// X86-COMPAT23: define{{.*}} x86_vectorcallcc void @"\01take_matrix_struct@@16"(ptr noundef byval(%struct.MatrixStruct) align 4 %{{.*}})
// X64-COMPAT23: define{{.*}} x86_vectorcallcc void @"\01take_matrix_struct@@16"(ptr nofreeobj noundef align 4 dead_on_return dereferenceable(16) %{{.*}})
struct MatrixStruct __vectorcall return_matrix_struct(void) {
struct MatrixStruct s;
return s;
}
// HFA: define{{.*}} x86_vectorcallcc %struct.MatrixStruct @"\01return_matrix_struct@@0"()
// COMPAT23: define{{.*}} x86_vectorcallcc void @"\01return_matrix_struct@@0"(ptr {{.*}}sret(%struct.MatrixStruct)
// float[4] was already an HVA.
void __vectorcall take_array_struct(struct ArrayStruct s) {}
// CHECK: define{{.*}} x86_vectorcallcc void @"\01take_array_struct@@16"(%struct.ArrayStruct inreg %{{.*}})
struct ArrayStruct __vectorcall return_array_struct(void) {
struct ArrayStruct s;
return s;
}
// CHECK: define{{.*}} x86_vectorcallcc %struct.ArrayStruct @"\01return_array_struct@@0"()
// Four doubles -> HVA. Compat 23 is byval / indirect.
void __vectorcall take_double_matrix_struct(struct DoubleMatrixStruct s) {}
// HFA: define{{.*}} x86_vectorcallcc void @"\01take_double_matrix_struct@@32"(%struct.DoubleMatrixStruct inreg %{{.*}})
// X86-COMPAT23: define{{.*}} x86_vectorcallcc void @"\01take_double_matrix_struct@@32"(ptr noundef byval(%struct.DoubleMatrixStruct) align 4 %{{.*}})
// X64-COMPAT23: define{{.*}} x86_vectorcallcc void @"\01take_double_matrix_struct@@32"(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(32) %{{.*}})
struct DoubleMatrixStruct __vectorcall return_double_matrix_struct(void) {
struct DoubleMatrixStruct s;
return s;
}
// HFA: define{{.*}} x86_vectorcallcc %struct.DoubleMatrixStruct @"\01return_double_matrix_struct@@0"()
// COMPAT23: define{{.*}} x86_vectorcallcc void @"\01return_double_matrix_struct@@0"(ptr {{.*}}sret(%struct.DoubleMatrixStruct)
// Nine floats exceeds the 4-member HVA limit.
void __vectorcall take_large_matrix_struct(struct LargeMatrixStruct s) {}
// X86: define{{.*}} x86_vectorcallcc void @"\01take_large_matrix_struct@@36"(ptr noundef byval(%struct.LargeMatrixStruct) align 4 %{{.*}})
// X64: define{{.*}} x86_vectorcallcc void @"\01take_large_matrix_struct@@40"(ptr nofreeobj noundef align 4 dead_on_return dereferenceable(36) %{{.*}})
// int is not an HVA base type.
void __vectorcall take_int_matrix_struct(struct IntMatrixStruct s) {}
// X86: define{{.*}} x86_vectorcallcc void @"\01take_int_matrix_struct@@16"(ptr noundef byval(%struct.IntMatrixStruct) align 4 %{{.*}})
// X64: define{{.*}} x86_vectorcallcc void @"\01take_int_matrix_struct@@16"(ptr nofreeobj noundef align 4 dead_on_return dereferenceable(16) %{{.*}})
// Tail padding from aligned(32) disqualifies the HVA.
void __vectorcall take_overaligned_matrix_struct(
struct OverAlignedMatrixStruct s) {}
// X86: define{{.*}} x86_vectorcallcc void @"\01take_overaligned_matrix_struct@@32"(ptr inreg nofreeobj noundef align 32 dead_on_return dereferenceable(32) %{{.*}})
// X64: define{{.*}} x86_vectorcallcc void @"\01take_overaligned_matrix_struct@@32"(ptr nofreeobj noundef align 32 dead_on_return dereferenceable(32) %{{.*}})