From 50ad5b7354187308b3cb7319ff387b3409c06af3 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 3 Aug 2013 17:40:38 +0000 Subject: [PATCH] Add support for passing -1 to __builtin_shufflevector to signify an undefined element value to match IR capabilities. llvm-svn: 187694 --- clang/docs/LanguageExtensions.rst | 10 +++++++--- clang/include/clang/AST/Expr.h | 4 ++-- clang/lib/CodeGen/CGExprScalar.cpp | 8 ++++++-- clang/lib/Sema/SemaChecking.cpp | 4 ++++ clang/test/CodeGen/builtinshufflevector2.c | 9 ++++++++- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index e8826b5..37a587e 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1455,8 +1455,8 @@ for the implementation of various target-specific header files like .. code-block:: c++ - // Identity operation - return 4-element vector V1. - __builtin_shufflevector(V1, V1, 0, 1, 2, 3) + // identity operation - return 4-element vector v1. + __builtin_shufflevector(v1, v1, 0, 1, 2, 3) // "Splat" element 0 of V1 into a 4-element result. __builtin_shufflevector(V1, V1, 0, 0, 0, 0) @@ -1470,6 +1470,9 @@ for the implementation of various target-specific header files like // Concatenate every other element of 8-element vectors V1 and V2. __builtin_shufflevector(V1, V2, 0, 2, 4, 6, 8, 10, 12, 14) + // Shuffle v1 with some elements being undefined + __builtin_shufflevector(v1, v1, 3, -1, 1, -1) + **Description**: The first two arguments to ``__builtin_shufflevector`` are vectors that have @@ -1478,7 +1481,8 @@ specify the elements indices of the first two vectors that should be extracted and returned in a new vector. These element indices are numbered sequentially starting with the first vector, continuing into the second vector. Thus, if ``vec1`` is a 4-element vector, index 5 would refer to the second element of -``vec2``. +``vec2``. An index of -1 can be used to indicate that the corresponding element +in the returned vector is a don't care and can be optimized by the backend. The result of ``__builtin_shufflevector`` is a vector with the same element type as ``vec1``/``vec2`` but that has an element count equal to the number of diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 42c99bb..f641578 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -3451,9 +3451,9 @@ public: void setExprs(ASTContext &C, ArrayRef Exprs); - unsigned getShuffleMaskIdx(ASTContext &Ctx, unsigned N) const { + llvm::APSInt getShuffleMaskIdx(ASTContext &Ctx, unsigned N) const { assert((N < NumExprs - 2) && "Shuffle idx out of range!"); - return getExpr(N+2)->EvaluateKnownConstInt(Ctx).getZExtValue(); + return getExpr(N+2)->EvaluateKnownConstInt(Ctx); } // Iterators diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 9ab111c..b6bda284 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -955,8 +955,12 @@ Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { SmallVector indices; for (unsigned i = 2; i < E->getNumSubExprs(); ++i) { - unsigned Idx = E->getShuffleMaskIdx(CGF.getContext(), i-2); - indices.push_back(Builder.getInt32(Idx)); + llvm::APSInt Idx = E->getShuffleMaskIdx(CGF.getContext(), i-2); + // Check for -1 and output it as undef in the IR. + if (Idx.isSigned() && Idx.isAllOnesValue()) + indices.push_back(llvm::UndefValue::get(CGF.Int32Ty)); + else + indices.push_back(Builder.getInt32(Idx.getZExtValue())); } Value *SV = llvm::ConstantVector::get(indices); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 4e0e76b..78995e3 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1786,6 +1786,10 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { diag::err_shufflevector_nonconstant_argument) << TheCall->getArg(i)->getSourceRange()); + // Allow -1 which will be translated to undef in the IR. + if (Result.isSigned() && Result.isAllOnesValue()) + continue; + if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) return ExprError(Diag(TheCall->getLocStart(), diag::err_shufflevector_argument_too_large) diff --git a/clang/test/CodeGen/builtinshufflevector2.c b/clang/test/CodeGen/builtinshufflevector2.c index ac0e07a..4a7fc62 100644 --- a/clang/test/CodeGen/builtinshufflevector2.c +++ b/clang/test/CodeGen/builtinshufflevector2.c @@ -28,8 +28,15 @@ void clang_shufflevector_v_v( float4* A, float4 x, uint4 mask ) { } // CHECK: define void @clang_shufflevector_v_v_c( -void clang_shufflevector_v_v_c( float4* A, float4 x, float4 y, uint4 mask ) { +void clang_shufflevector_v_v_c( float4* A, float4 x, float4 y) { // CHECK: [[V:%.*]] = shufflevector <4 x float> {{%.*}}, <4 x float> {{%.*}}, <4 x i32> // CHECK: store <4 x float> [[V]], <4 x float>* {{%.*}} *A = __builtin_shufflevector( x, y, 0, 4, 1, 5 ); } + +// CHECK: define void @clang_shufflevector_v_v_undef( +void clang_shufflevector_v_v_undef( float4* A, float4 x, float4 y) { +// CHECK: [[V:%.*]] = shufflevector <4 x float> {{%.*}}, <4 x float> {{%.*}}, <4 x i32> +// CHECK: store <4 x float> [[V]], <4 x float>* {{%.*}} + *A = __builtin_shufflevector( x, y, 0, 4, -1, 5 ); +} -- 2.7.4