simoll updated this revision to Diff 285282.
simoll added a comment.
- Fixed type printing & added type printing test.
- Rebased.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D81083/new/
https://reviews.llvm.org/D81083
Files:
clang/docs/LanguageExtensions.rst
clang/include/clang/AST/Type.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/TypePrinter.cpp
clang/lib/CodeGen/CGDebugInfo.cpp
clang/lib/CodeGen/CGExpr.cpp
clang/lib/CodeGen/CGExprScalar.cpp
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/lib/CodeGen/CodeGenTypes.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaType.cpp
clang/test/AST/ast-print-vector-size-bool.c
clang/test/CodeGen/debug-info-vector-bool.c
clang/test/SemaCXX/constexpr-vectors.cpp
clang/test/SemaCXX/vector.cpp
Index: clang/test/SemaCXX/vector.cpp
===================================================================
--- clang/test/SemaCXX/vector.cpp
+++ clang/test/SemaCXX/vector.cpp
@@ -331,8 +331,7 @@
typedef __attribute__((ext_vector_type(4))) int vi4;
const int &reference_to_vec_element = vi4(1).x;
-// PR12649
-typedef bool bad __attribute__((__vector_size__(16))); // expected-error {{invalid vector element type 'bool'}}
+typedef bool good __attribute__((__vector_size__(16)));
namespace Templates {
template <typename Elt, unsigned long long Size>
@@ -350,9 +349,7 @@
void Init() {
const TemplateVectorType<float, 32>::type Works = {};
const TemplateVectorType<int, 32>::type Works2 = {};
- // expected-error@#1 {{invalid vector element type 'bool'}}
- // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<bool, 32>' requested here}}
- const TemplateVectorType<bool, 32>::type NoBool = {};
+ const TemplateVectorType<bool, 32>::type BoolWorks = {};
// expected-error@#1 {{invalid vector element type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values)}}
// expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<int __attribute__((ext_vector_type(4))), 32>' requested here}}
const TemplateVectorType<vi4, 32>::type NoComplex = {};
Index: clang/test/SemaCXX/constexpr-vectors.cpp
===================================================================
--- clang/test/SemaCXX/constexpr-vectors.cpp
+++ clang/test/SemaCXX/constexpr-vectors.cpp
@@ -204,35 +204,35 @@
constexpr auto w = FourCharsVecSize{1, 2, 3, 4} <
FourCharsVecSize{4, 3, 2, 1};
- // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 0>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 true, i1 true, i1 false, i1 false, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto x = FourCharsVecSize{1, 2, 3, 4} >
FourCharsVecSize{4, 3, 2, 1};
- // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 false, i1 false, i1 true, i1 true, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto y = FourCharsVecSize{1, 2, 3, 4} <=
FourCharsVecSize{4, 3, 3, 1};
- // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 0>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 true, i1 true, i1 true, i1 false, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto z = FourCharsVecSize{1, 2, 3, 4} >=
FourCharsVecSize{4, 3, 3, 1};
- // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 false, i1 false, i1 true, i1 true, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto A = FourCharsVecSize{1, 2, 3, 4} ==
FourCharsVecSize{4, 3, 3, 1};
- // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 0>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 false, i1 false, i1 true, i1 false, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto B = FourCharsVecSize{1, 2, 3, 4} !=
FourCharsVecSize{4, 3, 3, 1};
- // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 true, i1 true, i1 false, i1 true, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto C = FourCharsVecSize{1, 2, 3, 4} < 3;
- // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 0>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 true, i1 true, i1 false, i1 false, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto D = FourCharsVecSize{1, 2, 3, 4} > 3;
- // CHECK: store <4 x i8> <i8 0, i8 0, i8 0, i8 1>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 false, i1 false, i1 false, i1 true, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto E = FourCharsVecSize{1, 2, 3, 4} <= 3;
- // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 0>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 true, i1 true, i1 true, i1 false, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto F = FourCharsVecSize{1, 2, 3, 4} >= 3;
- // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 false, i1 false, i1 true, i1 true, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto G = FourCharsVecSize{1, 2, 3, 4} == 3;
- // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 0>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 false, i1 false, i1 true, i1 false, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto H = FourCharsVecSize{1, 2, 3, 4} != 3;
- // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 true, i1 true, i1 false, i1 true, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto I = FourCharsVecSize{1, 2, 3, 4} &
FourCharsVecSize{4, 3, 2, 1};
@@ -252,15 +252,15 @@
constexpr auto O = FourCharsVecSize{5, 0, 6, 0} &&
FourCharsVecSize{5, 5, 0, 0};
- // CHECK: store <4 x i8> <i8 1, i8 0, i8 0, i8 0>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 true, i1 false, i1 false, i1 false, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto P = FourCharsVecSize{5, 0, 6, 0} ||
FourCharsVecSize{5, 5, 0, 0};
- // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 0>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 true, i1 true, i1 true, i1 false, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto Q = FourCharsVecSize{5, 0, 6, 0} && 3;
- // CHECK: store <4 x i8> <i8 1, i8 0, i8 1, i8 0>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 true, i1 false, i1 true, i1 false, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto R = FourCharsVecSize{5, 0, 6, 0} || 3;
- // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 1>
+ // CHECK: store i8 bitcast (<8 x i1> <i1 true, i1 true, i1 true, i1 true, i1 undef, i1 undef, i1 undef, i1 undef> to i8)
constexpr auto T = CmpMul(a, b);
// CHECK: store <4 x i8> <i8 108, i8 18, i8 56, i8 72>
Index: clang/test/CodeGen/debug-info-vector-bool.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/debug-info-vector-bool.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
+typedef _Bool bool32 __attribute__((__vector_size__(4)));
+
+bool32 b;
+
+// Test that we get an char array type.
+// CHECK: !DICompositeType(tag: DW_TAG_array_type,
+// CHECK-SAME: baseType: ![[CHAR:[0-9]+]]
+// CHECK-SAME: size: 32
+// CHECK-SAME: DIFlagVector
+// CHECK: ![[CHAR]] = !DIBasicType(name: "char"
Index: clang/test/AST/ast-print-vector-size-bool.c
===================================================================
--- /dev/null
+++ clang/test/AST/ast-print-vector-size-bool.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -ast-print %s -o - | FileCheck %s
+
+// CHECK: typedef __attribute__((__vector_size__(32 * sizeof(_Bool)))) _Bool bool256;
+typedef _Bool bool256 __attribute__((vector_size(32)));
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -2465,10 +2465,10 @@
QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
SourceLocation AttrLoc) {
- // The base type must be integer (not Boolean or enumeration) or float, and
+ // The base type must be boolean or integer (not enumeration) or float, and
// can't already be a vector.
if (!CurType->isDependentType() &&
- (!CurType->isBuiltinType() || CurType->isBooleanType() ||
+ (!CurType->isBuiltinType() ||
(!CurType->isIntegerType() && !CurType->isRealFloatingType()))) {
Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType;
return QualType();
@@ -2518,7 +2518,8 @@
return QualType();
}
- return Context.getVectorType(CurType, VectorSizeBits / TypeSize,
+ uint64_t ElemSizeBits = CurType->isBooleanType() ? 1 : TypeSize;
+ return Context.getVectorType(CurType, VectorSizeBits / ElemSizeBits,
VectorType::GenericVector);
}
@@ -7563,13 +7564,13 @@
T = Context.getAdjustedType(T, Wrapped);
}
-/// HandleVectorSizeAttribute - this attribute is only applicable to integral
-/// and float scalars, although arrays, pointers, and function return values are
-/// allowed in conjunction with this construct. Aggregates with this attribute
-/// are invalid, even if they are of the same size as a corresponding scalar.
-/// The raw attribute should contain precisely 1 argument, the vector size for
-/// the variable, measured in bytes. If curType and rawAttr are well formed,
-/// this routine will return a new vector type.
+/// HandleVectorSizeAttribute - this attribute is only applicable to boolean,
+/// integral and float scalars, although arrays, pointers, and function return
+/// values are allowed in conjunction with this construct. Aggregates with this
+/// attribute are invalid, even if they are of the same size as a corresponding
+/// scalar. The raw attribute should contain precisely 1 argument, the vector
+/// size for the variable, measured in bytes. If curType and rawAttr are well
+/// formed, this routine will return a new vector type.
static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S) {
// Check the attribute arguments.
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -5946,7 +5946,8 @@
} else if (LHSVT || RHSVT) {
ResultType = CheckVectorOperands(
LHS, RHS, QuestionLoc, /*isCompAssign*/ false, /*AllowBothBool*/ true,
- /*AllowBoolConversions*/ false);
+ /*AllowBoolConversions*/ false,
+ /*AllowBoolOperator*/ false);
if (ResultType.isNull())
return {};
} else {
@@ -6264,9 +6265,10 @@
// Extension: conditional operator involving vector types.
if (LTy->isVectorType() || RTy->isVectorType())
- return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false,
- /*AllowBothBool*/true,
- /*AllowBoolConversions*/false);
+ return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/ false,
+ /*AllowBothBool*/ true,
+ /*AllowBoolConversions*/ false,
+ /*AllowBoolOperator*/ false);
// -- The second and third operands have arithmetic or enumeration type;
// the usual arithmetic conversions are performed to bring them to a
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -8013,9 +8013,10 @@
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType()) {
QualType VecResTy = S.CheckVectorOperands(LHS, RHS, QuestionLoc,
- /*isCompAssign*/false,
- /*AllowBothBool*/true,
- /*AllowBoolConversions*/false);
+ /*isCompAssign*/ false,
+ /*AllowBothBool*/ true,
+ /*AllowBoolConversions*/ false,
+ /*AllowBooleanOperator*/ false);
if (VecResTy.isNull()) return QualType();
// The result type must match the condition type as specified in
// OpenCL v1.1 s6.11.6.
@@ -8079,9 +8080,10 @@
// Now check the two expressions.
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType())
- return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false,
- /*AllowBothBool*/true,
- /*AllowBoolConversions*/false);
+ return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/ false,
+ /*AllowBothBool*/ true,
+ /*AllowBoolConversions*/ false,
+ /*AllowBooleanOperator*/ false);
QualType ResTy =
UsualArithmeticConversions(LHS, RHS, QuestionLoc, ACK_Conditional);
@@ -9772,10 +9774,17 @@
return false;
}
+static bool IsScalarOrVectorBool(QualType Ty) {
+ return Ty->isBooleanType() ||
+ (Ty->isVectorType() &&
+ Ty->getAs<VectorType>()->getElementType()->isBooleanType());
+}
+
QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, bool IsCompAssign,
bool AllowBothBool,
- bool AllowBoolConversions) {
+ bool AllowBoolConversions,
+ bool AllowBoolOperation) {
if (!IsCompAssign) {
LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
if (LHS.isInvalid())
@@ -9805,6 +9814,11 @@
RHSVecType && RHSVecType->getVectorKind() == VectorType::AltiVecBool)
return InvalidOperands(Loc, LHS, RHS);
+ // This operation may not be performed on boolean vectors.
+ if (!AllowBoolOperation && IsScalarOrVectorBool(LHSType) &&
+ IsScalarOrVectorBool(RHSType))
+ return InvalidOperands(Loc, LHS, RHS);
+
// If the vector types are identical, return.
if (Context.hasSameType(LHSType, RHSType))
return LHSType;
@@ -10052,8 +10066,9 @@
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType())
return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign,
- /*AllowBothBool*/getLangOpts().AltiVec,
- /*AllowBoolConversions*/false);
+ /*AllowBothBool*/ getLangOpts().AltiVec,
+ /*AllowBoolConversions*/ false,
+ /*AllowBooleanOperation*/ false);
if (!IsDiv && (LHS.get()->getType()->isConstantMatrixType() ||
RHS.get()->getType()->isConstantMatrixType()))
return CheckMatrixMultiplyOperands(LHS, RHS, Loc, IsCompAssign);
@@ -10082,8 +10097,9 @@
if (LHS.get()->getType()->hasIntegerRepresentation() &&
RHS.get()->getType()->hasIntegerRepresentation())
return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign,
- /*AllowBothBool*/getLangOpts().AltiVec,
- /*AllowBoolConversions*/false);
+ /*AllowBothBool*/ getLangOpts().AltiVec,
+ /*AllowBoolConversions*/ false,
+ /*AllowBooleanOperation*/ false);
return InvalidOperands(Loc, LHS, RHS);
}
@@ -10368,10 +10384,11 @@
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType()) {
- QualType compType = CheckVectorOperands(
- LHS, RHS, Loc, CompLHSTy,
- /*AllowBothBool*/getLangOpts().AltiVec,
- /*AllowBoolConversions*/getLangOpts().ZVector);
+ QualType compType =
+ CheckVectorOperands(LHS, RHS, Loc, CompLHSTy,
+ /*AllowBothBool*/ getLangOpts().AltiVec,
+ /*AllowBoolConversions*/ getLangOpts().ZVector,
+ /*AllowBooleanOperation*/ false);
if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
@@ -10468,10 +10485,11 @@
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType()) {
- QualType compType = CheckVectorOperands(
- LHS, RHS, Loc, CompLHSTy,
- /*AllowBothBool*/getLangOpts().AltiVec,
- /*AllowBoolConversions*/getLangOpts().ZVector);
+ QualType compType =
+ CheckVectorOperands(LHS, RHS, Loc, CompLHSTy,
+ /*AllowBothBool*/ getLangOpts().AltiVec,
+ /*AllowBoolConversions*/ getLangOpts().ZVector,
+ /*AllowBooleanOperation*/ false);
if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
@@ -11908,6 +11926,9 @@
else if (TypeSize == Context.getTypeSize(Context.ShortTy))
return Context.getVectorType(Context.ShortTy, VTy->getNumElements(),
VectorType::GenericVector);
+ else if (TypeSize == Context.getTypeSize(Context.BoolTy))
+ return Context.getVectorType(Context.BoolTy, VTy->getNumElements(),
+ VectorType::GenericVector);
assert(TypeSize == Context.getTypeSize(Context.CharTy) &&
"Unhandled vector element size in vector compare");
return Context.getVectorType(Context.CharTy, VTy->getNumElements(),
@@ -11928,9 +11949,11 @@
// Check to make sure we're operating on vectors of the same type and width,
// Allowing one side to be a scalar of element type.
- QualType vType = CheckVectorOperands(LHS, RHS, Loc, /*isCompAssign*/false,
- /*AllowBothBool*/true,
- /*AllowBoolConversions*/getLangOpts().ZVector);
+ QualType vType =
+ CheckVectorOperands(LHS, RHS, Loc, /*isCompAssign*/ false,
+ /*AllowBothBool*/ true,
+ /*AllowBoolConversions*/ getLangOpts().ZVector,
+ /*AllowBooleanOperation*/ false);
if (vType.isNull())
return vType;
@@ -12077,8 +12100,9 @@
// Ensure that either both operands are of the same vector type, or
// one operand is of a vector type and the other is of its element type.
QualType vType = CheckVectorOperands(LHS, RHS, Loc, false,
- /*AllowBothBool*/true,
- /*AllowBoolConversions*/false);
+ /*AllowBothBool*/ true,
+ /*AllowBoolConversions*/ false,
+ /*AllowBooleanOperation*/ false);
if (vType.isNull())
return InvalidOperands(Loc, LHS, RHS);
if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion < 120 &&
@@ -12171,6 +12195,20 @@
return CheckMatrixElementwiseOperands(LHS, RHS, Loc, IsCompAssign);
}
+static bool isLegalBoolVectorBinaryOp(BinaryOperatorKind Opc) {
+ switch (Opc) {
+ default:
+ return false;
+ case BO_And:
+ case BO_AndAssign:
+ case BO_Or:
+ case BO_OrAssign:
+ case BO_Xor:
+ case BO_XorAssign:
+ return true;
+ }
+}
+
inline QualType Sema::CheckBitwiseOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
BinaryOperatorKind Opc) {
@@ -12179,13 +12217,17 @@
bool IsCompAssign =
Opc == BO_AndAssign || Opc == BO_OrAssign || Opc == BO_XorAssign;
+ bool LegalBoolVecOperator = isLegalBoolVectorBinaryOp(Opc);
+
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType()) {
if (LHS.get()->getType()->hasIntegerRepresentation() &&
RHS.get()->getType()->hasIntegerRepresentation())
- return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign,
- /*AllowBothBool*/true,
- /*AllowBoolConversions*/getLangOpts().ZVector);
+ return CheckVectorOperands(
+ LHS, RHS, Loc, IsCompAssign,
+ /*AllowBothBool*/ true,
+ /*AllowBoolConversions*/ getLangOpts().ZVector,
+ /*AllowBooleanOperation*/ LegalBoolVecOperator);
return InvalidOperands(Loc, LHS, RHS);
}
Index: clang/lib/CodeGen/CodeGenTypes.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenTypes.cpp
+++ clang/lib/CodeGen/CodeGenTypes.cpp
@@ -91,6 +91,16 @@
llvm::Type *R = ConvertType(T);
+ // Check for the boolean vector case
+ auto *FixedVT = dyn_cast<llvm::FixedVectorType>(R);
+ if (T->isVectorType() && FixedVT &&
+ FixedVT->getElementType()->isIntegerTy(1)) {
+
+ // Pad to at least one byte.
+ uint64_t BytePadded = std::max<uint64_t>(FixedVT->getNumElements(), 8);
+ return llvm::IntegerType::get(FixedVT->getContext(), BytePadded);
+ }
+
// If this is a bool type, or an ExtIntType in a bitfield representation,
// map this integer to the target-specified size.
if ((ForBitField && T->isExtIntType()) ||
@@ -708,8 +718,10 @@
case Type::ExtVector:
case Type::Vector: {
const VectorType *VT = cast<VectorType>(Ty);
- ResultType = llvm::FixedVectorType::get(ConvertType(VT->getElementType()),
- VT->getNumElements());
+ llvm::Type *IRElemTy = VT->getElementType()->isBooleanType()
+ ? llvm::Type::getInt1Ty(getLLVMContext())
+ : ConvertType(VT->getElementType());
+ ResultType = llvm::FixedVectorType::get(IRElemTy, VT->getNumElements());
break;
}
case Type::ConstantMatrix: {
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -4460,6 +4460,11 @@
/// Set the codegen fast-math flags.
void SetFastMathFlags(FPOptions FPFeatures);
+ // Truncate or extend a boolean vector to the requested number of elements.
+ llvm::Value *emitBoolVecConversion(llvm::Value *SrcVec,
+ unsigned NumElementsDst,
+ const llvm::Twine &Name = "");
+
private:
llvm::MDNode *getRangeForLoadFromType(QualType Ty);
void EmitReturnOfRValue(RValue RV, QualType Ty);
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2494,3 +2494,22 @@
return llvm::DebugLoc();
}
+
+llvm::Value *CodeGenFunction::emitBoolVecConversion(llvm::Value *SrcVec,
+ unsigned NumElementsDst,
+ const llvm::Twine &Name) {
+ auto *SrcTy = cast<llvm::FixedVectorType>(SrcVec->getType());
+ unsigned NumElementsSrc = SrcTy->getNumElements();
+ if (NumElementsSrc == NumElementsDst) {
+ return SrcVec;
+ }
+
+ std::vector<int> ShuffleMask(NumElementsDst, -1);
+ for (unsigned MaskIdx = 0;
+ MaskIdx < std::min<>(NumElementsDst, NumElementsSrc); ++MaskIdx) {
+ ShuffleMask[MaskIdx] = MaskIdx;
+ }
+
+ return Builder.CreateShuffleVector(SrcVec, llvm::UndefValue::get(SrcTy),
+ ShuffleMask, Name);
+}
Index: clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- clang/lib/CodeGen/CGExprScalar.cpp
+++ clang/lib/CodeGen/CGExprScalar.cpp
@@ -2079,7 +2079,30 @@
}
}
- return Builder.CreateBitCast(Src, DstTy);
+ // SExt/Trunc Boolean vectors to fit the expected type
+ auto *VecSrcTy = dyn_cast<llvm::VectorType>(Src->getType());
+ auto *VecDstTy = dyn_cast<llvm::VectorType>(DstTy);
+ bool VectorElementCast =
+ VecSrcTy && VecDstTy &&
+ (VecSrcTy->getElementCount() == VecDstTy->getElementCount());
+ if (VecSrcTy && VecSrcTy->getElementType()->isIntegerTy(1)) {
+ // When casting with the same element count extend this to the native
+ // result size Otw, signextend to 'i8' as an intermediary
+ unsigned DstElemBits =
+ VectorElementCast ? DstTy->getScalarSizeInBits() : 8;
+
+ auto *PlainIntTy = llvm::VectorType::get(Builder.getIntNTy(DstElemBits),
+ VecSrcTy->getElementCount());
+ Src = Builder.CreateSExt(Src, PlainIntTy);
+ }
+ Src = Builder.CreateBitCast(Src, DstTy);
+ if (VectorElementCast && VecDstTy->getElementType()->isIntegerTy(1)) {
+ auto *PlainIntTy =
+ llvm::VectorType::get(Builder.getIntNTy(SrcTy->getScalarSizeInBits()),
+ VecSrcTy->getElementCount());
+ Src = Builder.CreateTrunc(Src, PlainIntTy);
+ }
+ return Src;
}
case CK_AddressSpaceConversion: {
Expr::EvalResult Result;
@@ -4639,6 +4662,14 @@
return Builder.CreateIntToPtr(Src, DstTy, Name);
}
+static bool IsGenericBoolVector(QualType Ty) {
+ const auto *ClangVecTy = dyn_cast<VectorType>(Ty);
+ if (!ClangVecTy)
+ return false;
+
+ return ClangVecTy->isVectorSizeBoolean();
+}
+
Value *ScalarExprEmitter::VisitAsTypeExpr(AsTypeExpr *E) {
Value *Src = CGF.EmitScalarExpr(E->getSrcExpr());
llvm::Type *DstTy = ConvertType(E->getType());
@@ -4649,6 +4680,11 @@
unsigned NumElementsDst = isa<llvm::VectorType>(DstTy) ?
cast<llvm::VectorType>(DstTy)->getNumElements() : 0;
+ // Use bit vector expansion for generic boolean vectors
+ if (IsGenericBoolVector(E->getType())) {
+ return CGF.emitBoolVecConversion(Src, NumElementsDst, "astype");
+ }
+
// Going from vec3 to non-vec3 is a special case and requires a shuffle
// vector to get a vec4, then a bitcast if the target type is different.
if (NumElementsSrc == 3 && NumElementsDst != 3) {
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -1680,27 +1680,45 @@
LValueBaseInfo BaseInfo,
TBAAAccessInfo TBAAInfo,
bool isNontemporal) {
- if (!CGM.getCodeGenOpts().PreserveVec3Type) {
- // For better performance, handle vector loads differently.
- if (Ty->isVectorType()) {
- const llvm::Type *EltTy = Addr.getElementType();
-
- const auto *VTy = cast<llvm::VectorType>(EltTy);
-
- // Handle vectors of size 3 like size 4 for better performance.
- if (VTy->getNumElements() == 3) {
-
- // Bitcast to vec4 type.
- auto *vec4Ty = llvm::FixedVectorType::get(VTy->getElementType(), 4);
- Address Cast = Builder.CreateElementBitCast(Addr, vec4Ty, "castToVec4");
- // Now load value.
- llvm::Value *V = Builder.CreateLoad(Cast, Volatile, "loadVec4");
-
- // Shuffle vector to get vec3.
- V = Builder.CreateShuffleVector(V, llvm::UndefValue::get(vec4Ty),
- ArrayRef<int>{0, 1, 2}, "extractVec");
- return EmitFromMemory(V, Ty);
- }
+ const auto *ClangVecTy = Ty->getAs<VectorType>();
+ if (ClangVecTy) {
+ // Boolean vectors use `iN` as storage type
+ if (ClangVecTy->isVectorSizeBoolean()) {
+ llvm::Type *ValTy = ConvertType(Ty);
+ unsigned ValNumElems =
+ cast<llvm::FixedVectorType>(ValTy)->getNumElements();
+ // Load the `iP` storage object (P is the padded vector size).
+ auto *RawIntV = Builder.CreateLoad(Addr, Volatile, "load_bits");
+ const auto *RawIntTy = RawIntV->getType();
+ assert(RawIntTy->isIntegerTy() && "compressed iN storage for bitvectors");
+ // Bitcast iP --> <P x i1>
+ auto *PaddedVecTy = llvm::FixedVectorType::get(
+ Builder.getInt1Ty(), RawIntTy->getPrimitiveSizeInBits());
+ llvm::Value *V = Builder.CreateBitCast(RawIntV, PaddedVecTy);
+ // Shuffle <P x i1> --> <N x i1> (N is the actual bit size)
+ V = emitBoolVecConversion(V, ValNumElems, "extractvec");
+
+ return EmitFromMemory(V, Ty);
+ }
+
+ // Handle vectors of size 3 like size 4 for better performance.
+ const llvm::Type *EltTy = Addr.getElementType();
+ const auto *IRVecTy = cast<llvm::VectorType>(EltTy);
+
+ if (!CGM.getCodeGenOpts().PreserveVec3Type &&
+ IRVecTy->getNumElements() == 3) {
+
+ // Bitcast to vec4 type.
+ llvm::VectorType *vec4Ty =
+ llvm::FixedVectorType::get(IRVecTy->getElementType(), 4);
+ Address Cast = Builder.CreateElementBitCast(Addr, vec4Ty, "castToVec4");
+ // Now load value.
+ llvm::Value *V = Builder.CreateLoad(Cast, Volatile, "loadVec4");
+
+ // Shuffle vector to get vec3.
+ V = Builder.CreateShuffleVector(V, llvm::UndefValue::get(vec4Ty),
+ ArrayRef<int>{0, 1, 2}, "extractVec");
+ return EmitFromMemory(V, Ty);
}
}
@@ -1744,6 +1762,13 @@
return Value;
}
+static bool isBooleanVector(QualType Ty) {
+ auto *VecTy = Ty->getAs<VectorType>();
+ if (!VecTy)
+ return false;
+ return VecTy->isVectorSizeBoolean();
+}
+
llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
// Bool has a different representation in memory than in registers.
if (hasBooleanRepresentation(Ty)) {
@@ -1751,6 +1776,17 @@
"wrong value rep of bool");
return Builder.CreateTrunc(Value, Builder.getInt1Ty(), "tobool");
}
+ if (isBooleanVector(Ty)) {
+ const auto *RawIntTy = Value->getType();
+ // Bitcast iP --> <P x i1>
+ auto *PaddedVecTy = llvm::FixedVectorType::get(
+ Builder.getInt1Ty(), RawIntTy->getPrimitiveSizeInBits());
+ auto *V = Builder.CreateBitCast(Value, PaddedVecTy);
+ // Shuffle <P x i1> --> <N x i1> (N is the actual bit size)
+ llvm::Type *ValTy = ConvertType(Ty);
+ unsigned ValNumElems = cast<llvm::FixedVectorType>(ValTy)->getNumElements();
+ return emitBoolVecConversion(V, ValNumElems, "extractvec");
+ }
return Value;
}
@@ -1796,18 +1832,27 @@
LValueBaseInfo BaseInfo,
TBAAAccessInfo TBAAInfo,
bool isInit, bool isNontemporal) {
- if (!CGM.getCodeGenOpts().PreserveVec3Type) {
- // Handle vectors differently to get better performance.
- if (Ty->isVectorType()) {
- llvm::Type *SrcTy = Value->getType();
- auto *VecTy = dyn_cast<llvm::VectorType>(SrcTy);
+ llvm::Type *SrcTy = Value->getType();
+ const auto *ClangVecTy = Ty->getAs<VectorType>();
+ if (ClangVecTy) {
+ auto *IRVecTy = dyn_cast<llvm::FixedVectorType>(SrcTy);
+ if (ClangVecTy->isVectorSizeBoolean()) {
+ auto *MemIntTy =
+ cast<llvm::IntegerType>(Addr.getType()->getPointerElementType());
+ // Expand to the memory bit width
+ unsigned MemNumElems = MemIntTy->getPrimitiveSizeInBits();
+ // <N x i1> --> <P x i1>
+ Value = emitBoolVecConversion(Value, MemNumElems, "insertvec");
+ // <P x i1> --> iP
+ Value = Builder.CreateBitCast(Value, MemIntTy);
+ } else if (!CGM.getCodeGenOpts().PreserveVec3Type) {
// Handle vec3 special.
- if (VecTy && VecTy->getNumElements() == 3) {
+ if (IRVecTy && IRVecTy->getNumElements() == 3) {
// Our source is a vec3, do a shuffle vector to make it a vec4.
- Value = Builder.CreateShuffleVector(Value, llvm::UndefValue::get(VecTy),
- ArrayRef<int>{0, 1, 2, -1},
- "extractVec");
- SrcTy = llvm::FixedVectorType::get(VecTy->getElementType(), 4);
+ Value = Builder.CreateShuffleVector(
+ Value, llvm::UndefValue::get(IRVecTy), ArrayRef<int>{0, 1, 2, -1},
+ "extractVec");
+ SrcTy = llvm::FixedVectorType::get(IRVecTy->getElementType(), 4);
}
if (Addr.getElementType() != SrcTy) {
Addr = Builder.CreateElementBitCast(Addr, SrcTy, "storetmp");
@@ -2029,8 +2074,19 @@
// Read/modify/write the vector, inserting the new element.
llvm::Value *Vec = Builder.CreateLoad(Dst.getVectorAddress(),
Dst.isVolatileQualified());
+ auto *IRStoreTy = dyn_cast<llvm::IntegerType>(Vec->getType());
+ if (IRStoreTy) {
+ auto *IRVecTy = llvm::FixedVectorType::get(
+ Builder.getInt1Ty(), IRStoreTy->getPrimitiveSizeInBits());
+ Vec = Builder.CreateBitCast(Vec, IRVecTy);
+ // iN --> <N x i1>
+ }
Vec = Builder.CreateInsertElement(Vec, Src.getScalarVal(),
Dst.getVectorIdx(), "vecins");
+ if (IRStoreTy) {
+ // <N x i1> --> <iN>
+ Vec = Builder.CreateBitCast(Vec, IRStoreTy);
+ }
Builder.CreateStore(Vec, Dst.getVectorAddress(),
Dst.isVolatileQualified());
return;
Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2743,6 +2743,23 @@
llvm::DIType *CGDebugInfo::CreateType(const VectorType *Ty,
llvm::DIFile *Unit) {
+ if (Ty->isVectorSizeBoolean()) {
+ // vector_size(N) are special because their real element type (bits of bit
+ // size) is not their Clang element type (_Bool of size byte). For now, we
+ // pretend the boolean vector were actually a vector of bytes (where each
+ // byte represents 8 bits of the actual vector).
+ // FIXME Debug info should actually represent this proper as a vector mask
+ // type.
+ auto &Ctx = CGM.getContext();
+ uint64_t Size = CGM.getContext().getTypeSize(Ty);
+ uint64_t NumVectorBytes = Size / Ctx.getCharWidth();
+
+ // construct the vector of 'unsigned char' type
+ QualType CharVecTy = Ctx.getVectorType(Ctx.CharTy, NumVectorBytes,
+ VectorType::GenericVector);
+ return CreateType(CharVecTy->getAs<VectorType>(), Unit);
+ }
+
llvm::DIType *ElementTy = getOrCreateType(Ty->getElementType(), Unit);
int64_t Count = Ty->getNumElements();
Index: clang/lib/AST/TypePrinter.cpp
===================================================================
--- clang/lib/AST/TypePrinter.cpp
+++ clang/lib/AST/TypePrinter.cpp
@@ -645,11 +645,12 @@
printBefore(T->getElementType(), OS);
break;
case VectorType::GenericVector: {
+ auto NumVectorElems = T->getNumElements();
+ auto ElemSizeMultiple =
+ T->isVectorSizeBoolean() ? NumVectorElems / 8 : NumVectorElems;
// FIXME: We prefer to print the size directly here, but have no way
// to get the size of the type.
- OS << "__attribute__((__vector_size__("
- << T->getNumElements()
- << " * sizeof(";
+ OS << "__attribute__((__vector_size__(" << ElemSizeMultiple << " * sizeof(";
print(T->getElementType(), OS, StringRef());
OS << ")))) ";
printBefore(T->getElementType(), OS);
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -1969,7 +1969,8 @@
case Type::Vector: {
const auto *VT = cast<VectorType>(T);
TypeInfo EltInfo = getTypeInfo(VT->getElementType());
- Width = EltInfo.Width * VT->getNumElements();
+ Width = VT->isVectorSizeBoolean() ? VT->getNumElements()
+ : EltInfo.Width * VT->getNumElements();
Align = Width;
// If the alignment is not a power of 2, round up to the next power of 2.
// This happens for non-power-of-2 length vectors.
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -11327,7 +11327,8 @@
/// type checking for vector binary operators.
QualType CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, bool IsCompAssign,
- bool AllowBothBool, bool AllowBoolConversion);
+ bool AllowBothBool, bool AllowBoolConversion,
+ bool AllowBoolOperation);
QualType GetSignedVectorType(QualType V);
QualType CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -3245,6 +3245,11 @@
return VectorKind(VectorTypeBits.VecKind);
}
+ bool isVectorSizeBoolean() const {
+ return (getVectorKind() == VectorKind::GenericVector) &&
+ getElementType()->isBooleanType();
+ }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getElementType(), getNumElements(),
getTypeClass(), getVectorKind());
Index: clang/docs/LanguageExtensions.rst
===================================================================
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -433,6 +433,68 @@
return v;
}
+GCC vector types are created using the ``vector_size(N)`` attribute. The
+argument ``N`` specifies the number of bytes that will be allocated for an
+object of this type. The size has to be multiple of the size of the vector
+element type. For example:
+
+.. code-block:: c++
+
+ // OK: This declares a vector type with four 'int' elements
+ typedef int int4 __attribute__((vector_size(4 * sizeof(int))));
+
+ // ERROR: '11' is not a multiple of sizeof(int)
+ typedef int int_impossible __attribute__((vector_size(11)));
+
+ int4 foo(int4 a) {
+ int4 v;
+ v = a;
+ return v;
+ }
+
+
+Boolean Vectors
+---------------
+
+Different than GCC, Clang also allows the attribute to be used with boolean
+element types. For example:
+
+.. code-block:: c++
+
+ // legal for Clang, error for GCC:
+ typedef bool bool8 __attribute__((vector_size(1)));
+ // Objects of bool8 type hold 8 bits, sizeof(bool8) == 1
+
+ typedef bool bool32 __attribute__((vector_size(4)));
+ // Objects of bool32 type hold 32 bits, sizeof(bool32) == 4
+
+ bool8 foo(bool8 a) {
+ bool8 v;
+ v = a;
+ return v;
+ }
+
+Boolean vectors are a Clang extension of the GCC vector type. Boolean vectors
+are intended, though not guaranteed, to map to vector mask registers. The
+semantics of boolean vectors differs from the GCC vector of integer or floating
+point type. This is mostly because bits are smaller than the smallest
+addressable unit in memory on most architectures. The size parameter of a
+boolean vector type is the number of bytes in the vector.
+
+The semantics of boolean vectors borrows from C bit-fields with the following
+differences:
+
+* Distinct boolean vectors are always distinct memory objects (there is no
+ packing).
+* Bitwise `~`, `|`, `&`, `^` and `~` are the only allowed operators on boolean
+ vectors.
+
+The memory representation of a boolean vector is the smallest fitting
+power-of-two integer. The alignment is the alignment of that integer type. This
+permits the use of these types in allocated arrays using the common
+``sizeof(Array)/sizeof(ElementType)`` pattern.
+
+
Vector Literals
---------------
@@ -484,6 +546,7 @@
reinterpret_cast yes no yes no
static_cast yes no yes no
const_cast no no no no
+address &v[i] no no no [#]_ no
============================== ======= ======= ============= =======
See also :ref:`langext-__builtin_shufflevector`, :ref:`langext-__builtin_convertvector`.
@@ -493,6 +556,9 @@
it's only available in C++ and uses normal bool conversions (that is, != 0).
If it's an extension (OpenCL) vector, it's only available in C and OpenCL C.
And it selects base on signedness of the condition operands (OpenCL v1.1 s6.3.9).
+.. [#] Clang does not allow the address of an element to be taken while GCC
+ allows this. This is intentional for vectors with a boolean element type and
+ not implemented otherwise.
Matrix Types
============
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits