pengfei updated this revision to Diff 372254.
pengfei marked an inline comment as done.
pengfei added a comment.
Add more comments.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D109607/new/
https://reviews.llvm.org/D109607
Files:
clang/lib/CodeGen/TargetInfo.cpp
clang/test/CodeGen/X86/avx512fp16-abi.c
Index: clang/test/CodeGen/X86/avx512fp16-abi.c
===================================================================
--- clang/test/CodeGen/X86/avx512fp16-abi.c
+++ clang/test/CodeGen/X86/avx512fp16-abi.c
@@ -1,11 +1,12 @@
-// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -target-feature +avx512fp16 < %s | FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -target-feature +avx512fp16 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-C
+// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -target-feature +avx512fp16 -x c++ -std=c++11 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-CPP
struct half1 {
_Float16 a;
};
struct half1 h1(_Float16 a) {
- // CHECK: define{{.*}}half @h1
+ // CHECK: define{{.*}}half @
struct half1 x;
x.a = a;
return x;
@@ -17,7 +18,7 @@
};
struct half2 h2(_Float16 a, _Float16 b) {
- // CHECK: define{{.*}}<2 x half> @h2
+ // CHECK: define{{.*}}<2 x half> @
struct half2 x;
x.a = a;
x.b = b;
@@ -31,7 +32,7 @@
};
struct half3 h3(_Float16 a, _Float16 b, _Float16 c) {
- // CHECK: define{{.*}}<4 x half> @h3
+ // CHECK: define{{.*}}<4 x half> @
struct half3 x;
x.a = a;
x.b = b;
@@ -47,7 +48,7 @@
};
struct half4 h4(_Float16 a, _Float16 b, _Float16 c, _Float16 d) {
- // CHECK: define{{.*}}<4 x half> @h4
+ // CHECK: define{{.*}}<4 x half> @
struct half4 x;
x.a = a;
x.b = b;
@@ -62,7 +63,7 @@
};
struct floathalf fh(float a, _Float16 b) {
- // CHECK: define{{.*}}<4 x half> @fh
+ // CHECK: define{{.*}}<4 x half> @
struct floathalf x;
x.a = a;
x.b = b;
@@ -76,7 +77,7 @@
};
struct floathalf2 fh2(float a, _Float16 b, _Float16 c) {
- // CHECK: define{{.*}}<4 x half> @fh2
+ // CHECK: define{{.*}}<4 x half> @
struct floathalf2 x;
x.a = a;
x.b = b;
@@ -90,7 +91,7 @@
};
struct halffloat hf(_Float16 a, float b) {
- // CHECK: define{{.*}}<4 x half> @hf
+ // CHECK: define{{.*}}<4 x half> @
struct halffloat x;
x.a = a;
x.b = b;
@@ -104,7 +105,7 @@
};
struct half2float h2f(_Float16 a, _Float16 b, float c) {
- // CHECK: define{{.*}}<4 x half> @h2f
+ // CHECK: define{{.*}}<4 x half> @
struct half2float x;
x.a = a;
x.b = b;
@@ -120,7 +121,7 @@
};
struct floathalf3 fh3(float a, _Float16 b, _Float16 c, _Float16 d) {
- // CHECK: define{{.*}}{ <4 x half>, half } @fh3
+ // CHECK: define{{.*}}{ <4 x half>, half } @
struct floathalf3 x;
x.a = a;
x.b = b;
@@ -138,7 +139,7 @@
};
struct half5 h5(_Float16 a, _Float16 b, _Float16 c, _Float16 d, _Float16 e) {
- // CHECK: define{{.*}}{ <4 x half>, half } @h5
+ // CHECK: define{{.*}}{ <4 x half>, half } @
struct half5 x;
x.a = a;
x.b = b;
@@ -147,3 +148,27 @@
x.e = e;
return x;
}
+
+struct float2 {
+ struct {} s;
+ float a;
+ float b;
+};
+
+float pr51813(struct float2 s) {
+ // CHECK-C: define{{.*}} @pr51813(<2 x float>
+ // CHECK-CPP: define{{.*}} @_Z7pr518136float2(double {{.*}}, float
+ return s.a;
+}
+
+struct float3 {
+ float a;
+ struct {} s;
+ float b;
+};
+
+float pr51813_2(struct float3 s) {
+ // CHECK-C: define{{.*}} @pr51813_2(<2 x float>
+ // CHECK-CPP: define{{.*}} @_Z9pr51813_26float3(double {{.*}}, float
+ return s.a;
+}
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -3377,52 +3377,18 @@
return false;
}
-/// ContainsFloatAtOffset - Return true if the specified LLVM IR type has a
-/// float member at the specified offset. For example, {int,{float}} has a
-/// float at offset 4. It is conservatively correct for this routine to return
-/// false.
-static bool ContainsFloatAtOffset(llvm::Type *IRType, unsigned IROffset,
- const llvm::DataLayout &TD) {
- // Base case if we find a float.
- if (IROffset == 0 && IRType->isFloatTy())
- return true;
-
- // If this is a struct, recurse into the field at the specified offset.
- if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
- const llvm::StructLayout *SL = TD.getStructLayout(STy);
- unsigned Elt = SL->getElementContainingOffset(IROffset);
- IROffset -= SL->getElementOffset(Elt);
- return ContainsFloatAtOffset(STy->getElementType(Elt), IROffset, TD);
- }
-
- // If this is an array, recurse into the field at the specified offset.
- if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
- llvm::Type *EltTy = ATy->getElementType();
- unsigned EltSize = TD.getTypeAllocSize(EltTy);
- IROffset -= IROffset/EltSize*EltSize;
- return ContainsFloatAtOffset(EltTy, IROffset, TD);
- }
-
- return false;
-}
-
-/// ContainsHalfAtOffset - Return true if the specified LLVM IR type has a
-/// half member at the specified offset. For example, {int,{half}} has a
-/// half at offset 4. It is conservatively correct for this routine to return
-/// false.
-/// FIXME: Merge with ContainsFloatAtOffset
-static bool ContainsHalfAtOffset(llvm::Type *IRType, unsigned IROffset,
- const llvm::DataLayout &TD) {
- // Base case if we find a float.
- if (IROffset == 0 && IRType->isHalfTy())
- return true;
+/// getFPTypeAtOffset - Return a floating point type at the specified offset.
+static llvm::Type *getFPTypeAtOffset(llvm::Type *IRType, unsigned IROffset,
+ const llvm::DataLayout &TD) {
+ if (IROffset == 0 && IRType->isFloatingPointTy())
+ return IRType;
// If this is a struct, recurse into the field at the specified offset.
if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
const llvm::StructLayout *SL = TD.getStructLayout(STy);
unsigned Elt = SL->getElementContainingOffset(IROffset);
IROffset -= SL->getElementOffset(Elt);
- return ContainsHalfAtOffset(STy->getElementType(Elt), IROffset, TD);
+ return getFPTypeAtOffset(STy->getElementType(Elt), IROffset, TD);
}
// If this is an array, recurse into the field at the specified offset.
@@ -3430,10 +3396,10 @@
llvm::Type *EltTy = ATy->getElementType();
unsigned EltSize = TD.getTypeAllocSize(EltTy);
IROffset -= IROffset / EltSize * EltSize;
- return ContainsHalfAtOffset(EltTy, IROffset, TD);
+ return getFPTypeAtOffset(EltTy, IROffset, TD);
}
- return false;
+ return nullptr;
}
/// GetSSETypeAtOffset - Return a type that will be passed by the backend in the
@@ -3441,39 +3407,36 @@
llvm::Type *X86_64ABIInfo::
GetSSETypeAtOffset(llvm::Type *IRType, unsigned IROffset,
QualType SourceTy, unsigned SourceOffset) const {
- // If the high 32 bits are not used, we have three choices. Single half,
- // single float or two halfs.
- if (BitsContainNoUserData(SourceTy, SourceOffset * 8 + 32,
- SourceOffset * 8 + 64, getContext())) {
- if (ContainsFloatAtOffset(IRType, IROffset, getDataLayout()))
- return llvm::Type::getFloatTy(getVMContext());
- if (ContainsHalfAtOffset(IRType, IROffset + 2, getDataLayout()))
- return llvm::FixedVectorType::get(llvm::Type::getHalfTy(getVMContext()),
- 2);
-
- return llvm::Type::getHalfTy(getVMContext());
- }
-
- // We want to pass as <2 x float> if the LLVM IR type contains a float at
- // offset+0 and offset+4. Walk the LLVM IR type to find out if this is the
- // case.
- if (ContainsFloatAtOffset(IRType, IROffset, getDataLayout()) &&
- ContainsFloatAtOffset(IRType, IROffset + 4, getDataLayout()))
- return llvm::FixedVectorType::get(llvm::Type::getFloatTy(getVMContext()),
- 2);
-
- // We want to pass as <4 x half> if the LLVM IR type contains a half at
- // offset+0, +2, +4. Walk the LLVM IR type to find out if this is the case.
- if (ContainsHalfAtOffset(IRType, IROffset, getDataLayout()) &&
- ContainsHalfAtOffset(IRType, IROffset + 2, getDataLayout()) &&
- ContainsHalfAtOffset(IRType, IROffset + 4, getDataLayout()))
- return llvm::FixedVectorType::get(llvm::Type::getHalfTy(getVMContext()), 4);
-
- // We want to pass as <4 x half> if the LLVM IR type contains a mix of float
- // and half.
- // FIXME: Do we have a better representation for the mixed type?
- if (ContainsFloatAtOffset(IRType, IROffset, getDataLayout()) ||
- ContainsFloatAtOffset(IRType, IROffset + 4, getDataLayout()))
+ const llvm::DataLayout &TD = getDataLayout();
+ llvm::Type *T0 = getFPTypeAtOffset(IRType, IROffset, TD);
+ if (!T0 || T0->isDoubleTy())
+ return llvm::Type::getDoubleTy(getVMContext());
+
+ // Get the adjacent FP type.
+ llvm::Type *T1 =
+ getFPTypeAtOffset(IRType, IROffset + TD.getTypeAllocSize(T0), TD);
+ if (T1 == nullptr) {
+ // Check if IRType is a half + float.
+ if (T0->isHalfTy())
+ T1 = getFPTypeAtOffset(IRType, IROffset + 4, TD);
+ // If we can't get a second FP type, return a simple half or float.
+ // avx512fp16-abi.c:pr51813_2 shows it works to return float for
+ // {float, i8} too.
+ if (T1 == nullptr)
+ return T0;
+ }
+
+ if (T0->isFloatTy() && T1->isFloatTy())
+ return llvm::FixedVectorType::get(T0, 2);
+
+ if (T0->isHalfTy() && T1->isHalfTy()) {
+ llvm::Type *T2 = getFPTypeAtOffset(IRType, IROffset + 4, TD);
+ if (T2 == nullptr)
+ return llvm::FixedVectorType::get(T0, 2);
+ return llvm::FixedVectorType::get(T0, 4);
+ }
+
+ if (T0->isHalfTy() || T1->isHalfTy())
return llvm::FixedVectorType::get(llvm::Type::getHalfTy(getVMContext()), 4);
return llvm::Type::getDoubleTy(getVMContext());
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits