Index: lib/CodeGen/CGExprScalar.cpp =================================================================== --- lib/CodeGen/CGExprScalar.cpp +++ lib/CodeGen/CGExprScalar.cpp @@ -151,6 +151,9 @@ Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc); + Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy, + SourceLocation Loc, bool TreatBooleanAsSigned); + /// Emit a conversion from the specified complex type to the specified /// destination type, where the destination type is an LLVM scalar type. Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src, @@ -733,6 +736,13 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, QualType DstType, SourceLocation Loc) { + return EmitScalarConversion(Src, SrcType, DstType, Loc, false); +} + +Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, + QualType DstType, + SourceLocation Loc, + bool TreatBooleanAsSigned) { SrcType = CGF.getContext().getCanonicalType(SrcType); DstType = CGF.getContext().getCanonicalType(DstType); if (SrcType == DstType) return Src; @@ -807,7 +817,8 @@ if (DstType->isExtVectorType() && !SrcType->isVectorType()) { // Cast the scalar to element type QualType EltTy = DstType->getAs()->getElementType(); - llvm::Value *Elt = EmitScalarConversion(Src, SrcType, EltTy, Loc); + llvm::Value *Elt = EmitScalarConversion( + Src, SrcType, EltTy, Loc, CGF.getContext().getLangOpts().OpenCL); // Splat the element across to all elements unsigned NumElements = cast(DstTy)->getNumElements(); @@ -847,6 +858,9 @@ if (isa(SrcTy)) { bool InputSigned = SrcType->isSignedIntegerOrEnumerationType(); + if (SrcType->isBooleanType() && TreatBooleanAsSigned) { + InputSigned = true; + } if (isa(DstTy)) Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv"); else if (InputSigned) @@ -1531,10 +1545,14 @@ } case CK_VectorSplat: { llvm::Type *DstTy = ConvertType(DestTy); - Value *Elt = Visit(const_cast(E)); - Elt = EmitScalarConversion(Elt, E->getType(), + // Need an IgnoreImpCasts here as by default a boolean will be promoted to + // an int, which will not perform the sign extension, so if we know we are + // going to cast to a vector we have to strip the implicit cast off. + Value *Elt = Visit(const_cast(E->IgnoreImpCasts())); + Elt = EmitScalarConversion(Elt, E->IgnoreImpCasts()->getType(), DestTy->getAs()->getElementType(), - CE->getExprLoc()); + CE->getExprLoc(), + CGF.getContext().getLangOpts().OpenCL); // Splat the element across to all elements unsigned NumElements = cast(DstTy)->getNumElements(); Index: test/CodeGenOpenCL/bool_cast.cl =================================================================== --- /dev/null +++ test/CodeGenOpenCL/bool_cast.cl @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -O0 | FileCheck %s + +typedef unsigned char uchar4 __attribute((ext_vector_type(4))); +typedef unsigned int int4 __attribute((ext_vector_type(4))); + +void kernel ker() { + bool t = true; + int4 vec4 = (int4)t; +// CHECK: {{%.*}} = load i8, i8* %t, align 1 +// CHECK: {{%.*}} = trunc i8 {{%.*}} to i1 +// CHECK: {{%.*}} = sext i1 {{%.*}} to i32 +// CHECK: {{%.*}} = insertelement <4 x i32> undef, i32 {{%.*}}, i32 0 +// CHECK: {{%.*}} = shufflevector <4 x i32> {{%.*}}, <4 x i32> undef, <4 x i32> zeroinitializer +// CHECK: store <4 x i32> {{%.*}}, <4 x i32>* %vec4, align 16 + int i = (int)t; +// CHECK: {{%.*}} = load i8, i8* %t, align 1 +// CHECK: {{%.*}} = trunc i8 {{%.*}} to i1 +// CHECK: {{%.*}} = zext i1 {{%.*}} to i32 +// CHECK: store i32 {{%.*}}, i32* %i, align 4 + + uchar4 vc; + vc = (uchar4)true; +// CHECK: store <4 x i8> , <4 x i8>* %vc, align 4 + unsigned char c; + c = (unsigned char)true; +// CHECK: store i8 1, i8* %c, align 1 +}