Skip to content

Commit b02e783

Browse files
author
Anastasia Stulova
committed
[OpenCL] Fix casting a true boolean to an integer vector.
OpenCL v1.1 s6.2.2: for the boolean value true, every bit in the result vector should be set. This change treats the i1 value as signed for the purposes of performing the cast to integer, and therefore sign extend into the result. Patch by Neil Hickey! http://reviews.llvm.org/D13349 llvm-svn: 249301
1 parent 199e523 commit b02e783

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ class ScalarExprEmitter
151151
Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
152152
SourceLocation Loc);
153153

154+
Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
155+
SourceLocation Loc, bool TreatBooleanAsSigned);
156+
154157
/// Emit a conversion from the specified complex type to the specified
155158
/// destination type, where the destination type is an LLVM scalar type.
156159
Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
@@ -733,6 +736,13 @@ void ScalarExprEmitter::EmitFloatConversionCheck(
733736
Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
734737
QualType DstType,
735738
SourceLocation Loc) {
739+
return EmitScalarConversion(Src, SrcType, DstType, Loc, false);
740+
}
741+
742+
Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
743+
QualType DstType,
744+
SourceLocation Loc,
745+
bool TreatBooleanAsSigned) {
736746
SrcType = CGF.getContext().getCanonicalType(SrcType);
737747
DstType = CGF.getContext().getCanonicalType(DstType);
738748
if (SrcType == DstType) return Src;
@@ -807,7 +817,8 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
807817
if (DstType->isExtVectorType() && !SrcType->isVectorType()) {
808818
// Cast the scalar to element type
809819
QualType EltTy = DstType->getAs<ExtVectorType>()->getElementType();
810-
llvm::Value *Elt = EmitScalarConversion(Src, SrcType, EltTy, Loc);
820+
llvm::Value *Elt = EmitScalarConversion(
821+
Src, SrcType, EltTy, Loc, CGF.getContext().getLangOpts().OpenCL);
811822

812823
// Splat the element across to all elements
813824
unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
@@ -847,6 +858,9 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
847858

848859
if (isa<llvm::IntegerType>(SrcTy)) {
849860
bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
861+
if (SrcType->isBooleanType() && TreatBooleanAsSigned) {
862+
InputSigned = true;
863+
}
850864
if (isa<llvm::IntegerType>(DstTy))
851865
Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
852866
else if (InputSigned)
@@ -1531,10 +1545,14 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
15311545
}
15321546
case CK_VectorSplat: {
15331547
llvm::Type *DstTy = ConvertType(DestTy);
1534-
Value *Elt = Visit(const_cast<Expr*>(E));
1535-
Elt = EmitScalarConversion(Elt, E->getType(),
1548+
// Need an IgnoreImpCasts here as by default a boolean will be promoted to
1549+
// an int, which will not perform the sign extension, so if we know we are
1550+
// going to cast to a vector we have to strip the implicit cast off.
1551+
Value *Elt = Visit(const_cast<Expr*>(E->IgnoreImpCasts()));
1552+
Elt = EmitScalarConversion(Elt, E->IgnoreImpCasts()->getType(),
15361553
DestTy->getAs<VectorType>()->getElementType(),
1537-
CE->getExprLoc());
1554+
CE->getExprLoc(),
1555+
CGF.getContext().getLangOpts().OpenCL);
15381556

15391557
// Splat the element across to all elements
15401558
unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();

clang/test/CodeGenOpenCL/bool_cast.cl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %clang_cc1 %s -emit-llvm -o - -O0 | FileCheck %s
2+
3+
typedef unsigned char uchar4 __attribute((ext_vector_type(4)));
4+
typedef unsigned int int4 __attribute((ext_vector_type(4)));
5+
6+
void kernel ker() {
7+
bool t = true;
8+
int4 vec4 = (int4)t;
9+
// CHECK: {{%.*}} = load i8, i8* %t, align 1
10+
// CHECK: {{%.*}} = trunc i8 {{%.*}} to i1
11+
// CHECK: {{%.*}} = sext i1 {{%.*}} to i32
12+
// CHECK: {{%.*}} = insertelement <4 x i32> undef, i32 {{%.*}}, i32 0
13+
// CHECK: {{%.*}} = shufflevector <4 x i32> {{%.*}}, <4 x i32> undef, <4 x i32> zeroinitializer
14+
// CHECK: store <4 x i32> {{%.*}}, <4 x i32>* %vec4, align 16
15+
int i = (int)t;
16+
// CHECK: {{%.*}} = load i8, i8* %t, align 1
17+
// CHECK: {{%.*}} = trunc i8 {{%.*}} to i1
18+
// CHECK: {{%.*}} = zext i1 {{%.*}} to i32
19+
// CHECK: store i32 {{%.*}}, i32* %i, align 4
20+
21+
uchar4 vc;
22+
vc = (uchar4)true;
23+
// CHECK: store <4 x i8> <i8 -1, i8 -1, i8 -1, i8 -1>, <4 x i8>* %vc, align 4
24+
unsigned char c;
25+
c = (unsigned char)true;
26+
// CHECK: store i8 1, i8* %c, align 1
27+
}

0 commit comments

Comments
 (0)