Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 2824a07

Browse files
committed
[Bugfix] Fix ICE on constexpr vector splat.
In {CG,}ExprConstant.cpp, we weren't treating vector splats properly. This patch makes us treat splats more properly. Additionally, this patch adds a new cast kind which allows a bool->int cast to result in -1 or 0, instead of 1 or 0 (for true and false, respectively), so we can sanely model OpenCL bool->int casts in the AST. Differential Revision: http://reviews.llvm.org/D14877 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@257559 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 05d274c commit 2824a07

20 files changed

+193
-58
lines changed

Diff for: include/clang/AST/ASTContext.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -2283,9 +2283,13 @@ class ASTContext : public RefCountedBase<ASTContext> {
22832283
/// \brief Make an APSInt of the appropriate width and signedness for the
22842284
/// given \p Value and integer \p Type.
22852285
llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const {
2286-
llvm::APSInt Res(getIntWidth(Type),
2287-
!Type->isSignedIntegerOrEnumerationType());
2286+
// If Type is a signed integer type larger than 64 bits, we need to be sure
2287+
// to sign extend Res appropriately.
2288+
llvm::APSInt Res(64, !Type->isSignedIntegerOrEnumerationType());
22882289
Res = Value;
2290+
unsigned Width = getIntWidth(Type);
2291+
if (Width != Res.getBitWidth())
2292+
return Res.extOrTrunc(Width);
22892293
return Res;
22902294
}
22912295

Diff for: include/clang/AST/OperationKinds.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,11 @@ enum CastKind {
185185
/// CK_FloatingToBoolean - Floating point to boolean.
186186
/// (bool) f
187187
CK_FloatingToBoolean,
188-
188+
189+
// CK_BooleanToSignedIntegral - Convert a boolean to -1 or 0 for true and
190+
// false, respectively.
191+
CK_BooleanToSignedIntegral,
192+
189193
/// CK_FloatingCast - Casting between floating types of different size.
190194
/// (double) f
191195
/// (float) ld

Diff for: include/clang/Sema/Sema.h

+4
Original file line numberDiff line numberDiff line change
@@ -8589,6 +8589,10 @@ class Sema {
85898589
bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
85908590
CastKind &Kind);
85918591

8592+
/// \brief Prepare `SplattedExpr` for a vector splat operation, adding
8593+
/// implicit casts if necessary.
8594+
ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr);
8595+
85928596
// CheckExtVectorCast - check type constraints for extended vectors.
85938597
// Since vectors are an extension, there are no C standard reference for this.
85948598
// We allow casting between vectors and integer datatypes of the same size,

Diff for: lib/AST/Expr.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1553,6 +1553,7 @@ bool CastExpr::CastConsistency() const {
15531553
case CK_ToVoid:
15541554
case CK_VectorSplat:
15551555
case CK_IntegralCast:
1556+
case CK_BooleanToSignedIntegral:
15561557
case CK_IntegralToFloating:
15571558
case CK_FloatingToIntegral:
15581559
case CK_FloatingCast:
@@ -1646,6 +1647,8 @@ const char *CastExpr::getCastKindName() const {
16461647
return "VectorSplat";
16471648
case CK_IntegralCast:
16481649
return "IntegralCast";
1650+
case CK_BooleanToSignedIntegral:
1651+
return "BooleanToSignedIntegral";
16491652
case CK_IntegralToBoolean:
16501653
return "IntegralToBoolean";
16511654
case CK_IntegralToFloating:

Diff for: lib/AST/ExprConstant.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -7781,12 +7781,16 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
77817781
case CK_PointerToBoolean:
77827782
case CK_IntegralToBoolean:
77837783
case CK_FloatingToBoolean:
7784+
case CK_BooleanToSignedIntegral:
77847785
case CK_FloatingComplexToBoolean:
77857786
case CK_IntegralComplexToBoolean: {
77867787
bool BoolResult;
77877788
if (!EvaluateAsBooleanCondition(SubExpr, BoolResult, Info))
77887789
return false;
7789-
return Success(BoolResult, E);
7790+
uint64_t IntResult = BoolResult;
7791+
if (BoolResult && E->getCastKind() == CK_BooleanToSignedIntegral)
7792+
IntResult = (uint64_t)-1;
7793+
return Success(IntResult, E);
77907794
}
77917795

77927796
case CK_IntegralCast: {
@@ -8223,6 +8227,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
82238227
case CK_ToVoid:
82248228
case CK_VectorSplat:
82258229
case CK_IntegralCast:
8230+
case CK_BooleanToSignedIntegral:
82268231
case CK_IntegralToBoolean:
82278232
case CK_IntegralToFloating:
82288233
case CK_FloatingToIntegral:

Diff for: lib/CodeGen/CGExpr.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -3365,6 +3365,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
33653365
case CK_PointerToBoolean:
33663366
case CK_VectorSplat:
33673367
case CK_IntegralCast:
3368+
case CK_BooleanToSignedIntegral:
33683369
case CK_IntegralToBoolean:
33693370
case CK_IntegralToFloating:
33703371
case CK_FloatingToIntegral:

Diff for: lib/CodeGen/CGExprAgg.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
721721
case CK_ToVoid:
722722
case CK_VectorSplat:
723723
case CK_IntegralCast:
724+
case CK_BooleanToSignedIntegral:
724725
case CK_IntegralToBoolean:
725726
case CK_IntegralToFloating:
726727
case CK_FloatingToIntegral:

Diff for: lib/CodeGen/CGExprComplex.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
462462
case CK_ToVoid:
463463
case CK_VectorSplat:
464464
case CK_IntegralCast:
465+
case CK_BooleanToSignedIntegral:
465466
case CK_IntegralToBoolean:
466467
case CK_IntegralToFloating:
467468
case CK_FloatingToIntegral:

Diff for: lib/CodeGen/CGExprConstant.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ class ConstExprEmitter :
735735
case CK_PointerToBoolean:
736736
case CK_NullToPointer:
737737
case CK_IntegralCast:
738+
case CK_BooleanToSignedIntegral:
738739
case CK_IntegralToPointer:
739740
case CK_IntegralToBoolean:
740741
case CK_IntegralToFloating:

Diff for: lib/CodeGen/CGExprScalar.cpp

+11-14
Original file line numberDiff line numberDiff line change
@@ -811,14 +811,15 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
811811

812812
// A scalar can be splatted to an extended vector of the same element type
813813
if (DstType->isExtVectorType() && !SrcType->isVectorType()) {
814-
// Cast the scalar to element type
815-
QualType EltTy = DstType->getAs<ExtVectorType>()->getElementType();
816-
llvm::Value *Elt = EmitScalarConversion(
817-
Src, SrcType, EltTy, Loc, CGF.getContext().getLangOpts().OpenCL);
814+
// Sema should add casts to make sure that the source expression's type is
815+
// the same as the vector's element type (sans qualifiers)
816+
assert(DstType->castAs<ExtVectorType>()->getElementType().getTypePtr() ==
817+
SrcType.getTypePtr() &&
818+
"Splatted expr doesn't match with vector element type?");
818819

819820
// Splat the element across to all elements
820821
unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
821-
return Builder.CreateVectorSplat(NumElements, Elt, "splat");
822+
return Builder.CreateVectorSplat(NumElements, Src, "splat");
822823
}
823824

824825
// Allow bitcast from vector to integer/fp of the same size.
@@ -1541,15 +1542,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
15411542
}
15421543
case CK_VectorSplat: {
15431544
llvm::Type *DstTy = ConvertType(DestTy);
1544-
// Need an IgnoreImpCasts here as by default a boolean will be promoted to
1545-
// an int, which will not perform the sign extension, so if we know we are
1546-
// going to cast to a vector we have to strip the implicit cast off.
1547-
Value *Elt = Visit(const_cast<Expr*>(E->IgnoreImpCasts()));
1548-
Elt = EmitScalarConversion(Elt, E->IgnoreImpCasts()->getType(),
1549-
DestTy->getAs<VectorType>()->getElementType(),
1550-
CE->getExprLoc(),
1551-
CGF.getContext().getLangOpts().OpenCL);
1552-
1545+
Value *Elt = Visit(const_cast<Expr*>(E));
15531546
// Splat the element across to all elements
15541547
unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
15551548
return Builder.CreateVectorSplat(NumElements, Elt, "splat");
@@ -1561,6 +1554,10 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
15611554
case CK_FloatingCast:
15621555
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
15631556
CE->getExprLoc());
1557+
case CK_BooleanToSignedIntegral:
1558+
return EmitScalarConversion(Visit(E), E->getType(), DestTy,
1559+
CE->getExprLoc(),
1560+
/*TreatBooleanAsSigned=*/true);
15641561
case CK_IntegralToBoolean:
15651562
return EmitIntToBoolConversion(Visit(E));
15661563
case CK_PointerToBoolean:

Diff for: lib/Edit/RewriteObjCFoundationAPI.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,9 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
10771077
case CK_BuiltinFnToFnPtr:
10781078
case CK_ZeroToOCLEvent:
10791079
return false;
1080+
1081+
case CK_BooleanToSignedIntegral:
1082+
llvm_unreachable("OpenCL-specific cast in Objective-C?");
10801083
}
10811084
}
10821085

Diff for: lib/Sema/SemaCast.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -2105,6 +2105,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
21052105
&& (SrcExpr.get()->getType()->isIntegerType()
21062106
|| SrcExpr.get()->getType()->isFloatingType())) {
21072107
Kind = CK_VectorSplat;
2108+
SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get());
21082109
return;
21092110
}
21102111

@@ -2339,6 +2340,7 @@ void CastOperation::CheckCStyleCast() {
23392340
if (DestVecTy->getVectorKind() == VectorType::AltiVecVector &&
23402341
(SrcType->isIntegerType() || SrcType->isFloatingType())) {
23412342
Kind = CK_VectorSplat;
2343+
SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get());
23422344
} else if (Self.CheckVectorCast(OpRange, DestType, SrcType, Kind)) {
23432345
SrcExpr = ExprError();
23442346
}

Diff for: lib/Sema/SemaChecking.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -6243,7 +6243,8 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
62436243

62446244
IntRange OutputTypeRange = IntRange::forValueOfType(C, GetExprType(CE));
62456245

6246-
bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast);
6246+
bool isIntegerCast = CE->getCastKind() == CK_IntegralCast ||
6247+
CE->getCastKind() == CK_BooleanToSignedIntegral;
62476248

62486249
// Assume that non-integer casts can span the full range of the type.
62496250
if (!isIntegerCast)

Diff for: lib/Sema/SemaExpr.cpp

+38-16
Original file line numberDiff line numberDiff line change
@@ -5602,6 +5602,39 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
56025602
return false;
56035603
}
56045604

5605+
ExprResult Sema::prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr) {
5606+
QualType DestElemTy = VectorTy->castAs<VectorType>()->getElementType();
5607+
5608+
if (DestElemTy == SplattedExpr->getType())
5609+
return SplattedExpr;
5610+
5611+
assert(DestElemTy->isFloatingType() ||
5612+
DestElemTy->isIntegralOrEnumerationType());
5613+
5614+
CastKind CK;
5615+
if (VectorTy->isExtVectorType() && SplattedExpr->getType()->isBooleanType()) {
5616+
// OpenCL requires that we convert `true` boolean expressions to -1, but
5617+
// only when splatting vectors.
5618+
if (DestElemTy->isFloatingType()) {
5619+
// To avoid having to have a CK_BooleanToSignedFloating cast kind, we cast
5620+
// in two steps: boolean to signed integral, then to floating.
5621+
ExprResult CastExprRes = ImpCastExprToType(SplattedExpr, Context.IntTy,
5622+
CK_BooleanToSignedIntegral);
5623+
SplattedExpr = CastExprRes.get();
5624+
CK = CK_IntegralToFloating;
5625+
} else {
5626+
CK = CK_BooleanToSignedIntegral;
5627+
}
5628+
} else {
5629+
ExprResult CastExprRes = SplattedExpr;
5630+
CK = PrepareScalarCast(CastExprRes, DestElemTy);
5631+
if (CastExprRes.isInvalid())
5632+
return ExprError();
5633+
SplattedExpr = CastExprRes.get();
5634+
}
5635+
return ImpCastExprToType(SplattedExpr, DestElemTy, CK);
5636+
}
5637+
56055638
ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
56065639
Expr *CastExpr, CastKind &Kind) {
56075640
assert(DestTy->isExtVectorType() && "Not an extended vector type!");
@@ -5632,15 +5665,8 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
56325665
diag::err_invalid_conversion_between_vector_and_scalar)
56335666
<< DestTy << SrcTy << R;
56345667

5635-
QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType();
5636-
ExprResult CastExprRes = CastExpr;
5637-
CastKind CK = PrepareScalarCast(CastExprRes, DestElemTy);
5638-
if (CastExprRes.isInvalid())
5639-
return ExprError();
5640-
CastExpr = ImpCastExprToType(CastExprRes.get(), DestElemTy, CK).get();
5641-
56425668
Kind = CK_VectorSplat;
5643-
return CastExpr;
5669+
return prepareVectorSplat(DestTy, CastExpr);
56445670
}
56455671

56465672
ExprResult
@@ -6979,13 +7005,9 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
69797005
if (RHSType->isExtVectorType())
69807006
return Incompatible;
69817007
if (RHSType->isArithmeticType()) {
6982-
// CK_VectorSplat does T -> vector T, so first cast to the
6983-
// element type.
6984-
QualType elType = cast<ExtVectorType>(LHSType)->getElementType();
6985-
if (elType != RHSType && ConvertRHS) {
6986-
Kind = PrepareScalarCast(RHS, elType);
6987-
RHS = ImpCastExprToType(RHS.get(), elType, Kind);
6988-
}
7008+
// CK_VectorSplat does T -> vector T, so first cast to the element type.
7009+
if (ConvertRHS)
7010+
RHS = prepareVectorSplat(LHSType, RHS.get());
69897011
Kind = CK_VectorSplat;
69907012
return Compatible;
69917013
}
@@ -8203,7 +8225,7 @@ static QualType checkOpenCLVectorShift(Sema &S,
82038225
if (RHS.isInvalid()) return QualType();
82048226

82058227
QualType LHSType = LHS.get()->getType();
8206-
const VectorType *LHSVecTy = LHSType->getAs<VectorType>();
8228+
const VectorType *LHSVecTy = LHSType->castAs<VectorType>();
82078229
QualType LHSEleType = LHSVecTy->getElementType();
82088230

82098231
// Note that RHS might not be a vector.

Diff for: lib/Sema/SemaExprCXX.cpp

+5-12
Original file line numberDiff line numberDiff line change
@@ -3353,20 +3353,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
33533353
VK_RValue, /*BasePath=*/nullptr, CCK).get();
33543354
break;
33553355

3356-
case ICK_Vector_Splat:
3356+
case ICK_Vector_Splat: {
33573357
// Vector splat from any arithmetic type to a vector.
3358-
// Cast to the element type.
3359-
{
3360-
QualType elType = ToType->getAs<ExtVectorType>()->getElementType();
3361-
if (elType != From->getType()) {
3362-
ExprResult E = From;
3363-
From = ImpCastExprToType(From, elType,
3364-
PrepareScalarCast(E, elType)).get();
3365-
}
3366-
From = ImpCastExprToType(From, ToType, CK_VectorSplat,
3367-
VK_RValue, /*BasePath=*/nullptr, CCK).get();
3368-
}
3358+
Expr *Elem = prepareVectorSplat(ToType, From).get();
3359+
From = ImpCastExprToType(Elem, ToType, CK_VectorSplat, VK_RValue,
3360+
/*BasePath=*/nullptr, CCK).get();
33693361
break;
3362+
}
33703363

33713364
case ICK_Complex_Real:
33723365
// Case 1. x -> _Complex y

Diff for: lib/Sema/SemaOverload.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ static const Expr *IgnoreNarrowingConversion(const Expr *Converted) {
258258
case CK_IntegralCast:
259259
case CK_IntegralToBoolean:
260260
case CK_IntegralToFloating:
261+
case CK_BooleanToSignedIntegral:
261262
case CK_FloatingToIntegral:
262263
case CK_FloatingToBoolean:
263264
case CK_FloatingCast:

Diff for: lib/StaticAnalyzer/Core/ExprEngineC.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
316316
case CK_ArrayToPointerDecay:
317317
case CK_BitCast:
318318
case CK_AddressSpaceConversion:
319+
case CK_BooleanToSignedIntegral:
319320
case CK_NullToPointer:
320321
case CK_IntegralToPointer:
321322
case CK_PointerToIntegral:
@@ -344,6 +345,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
344345
// Delegate to SValBuilder to process.
345346
SVal V = state->getSVal(Ex, LCtx);
346347
V = svalBuilder.evalCast(V, T, ExTy);
348+
// Negate the result if we're treating the boolean as a signed i1
349+
if (CastE->getCastKind() == CK_BooleanToSignedIntegral)
350+
V = evalMinus(V);
347351
state = state->BindExpr(CastE, LCtx, V);
348352
Bldr.generateNode(CastE, Pred, state);
349353
continue;

Diff for: test/CodeGenCXX/builtins-systemz-zvector.cpp

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// REQUIRES: systemz-registered-target
2+
// RUN: %clang_cc1 -target-cpu z13 -triple s390x-linux-gnu \
3+
// RUN: -fzvector -fno-lax-vector-conversions -std=c++11 \
4+
// RUN: -Wall -Wno-unused -Werror -emit-llvm %s -o - | FileCheck %s
5+
6+
bool gb;
7+
8+
// There was an issue where we weren't properly converting constexprs to
9+
// vectors with elements of the appropriate width. (e.g.
10+
// (vector signed short)0 would be lowered as [4 x i32] in some cases)
11+
12+
// CHECK-LABEL: @_Z8testIntsDv4_i
13+
void testInts(vector int VI) {
14+
constexpr vector int CI1 = (vector int)0LL;
15+
// CHECK: icmp
16+
gb = (VI == CI1)[0];
17+
18+
// Likewise for float inits.
19+
constexpr vector int CI2 = (vector int)char(0);
20+
// CHECK: icmp
21+
gb = (VI == CI2)[0];
22+
23+
constexpr vector int CF1 = (vector int)0.0;
24+
// CHECK: icmp
25+
gb = (VI == CF1)[0];
26+
27+
constexpr vector int CF2 = (vector int)0.0f;
28+
// CHECK: icmp
29+
gb = (VI == CF2)[0];
30+
}
31+
32+
// CHECK-LABEL: @_Z10testFloatsDv2_d
33+
void testFloats(vector double VD) {
34+
constexpr vector double CI1 = (vector double)0LL;
35+
// CHECK: fcmp
36+
gb = (VD == CI1)[0];
37+
38+
// Likewise for float inits.
39+
constexpr vector double CI2 = (vector double)char(0);
40+
// CHECK: fcmp
41+
gb = (VD == CI2)[0];
42+
43+
constexpr vector double CF1 = (vector double)0.0;
44+
// CHECK: fcmp
45+
gb = (VD == CF1)[0];
46+
47+
constexpr vector double CF2 = (vector double)0.0f;
48+
// CHECK: fcmp
49+
gb = (VD == CF2)[0];
50+
}

0 commit comments

Comments
 (0)