summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/docs/LanguageExtensions.rst10
-rw-r--r--clang/include/clang/AST/Expr.h4
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp8
-rw-r--r--clang/lib/Sema/SemaChecking.cpp4
-rw-r--r--clang/test/CodeGen/builtinshufflevector2.c9
5 files changed, 27 insertions, 8 deletions
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index e8826b5b360..37a587ecb42 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 42c99bbee09..f641578bb31 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<Expr *> 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 9ab111c4935..b6bda284717 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -955,8 +955,12 @@ Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
SmallVector<llvm::Constant*, 32> 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 4e0e76b20dd..78995e3f43b 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 ac0e07a4190..4a7fc6261a0 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> <i32 0, i32 4, i32 1, i32 5>
// 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> <i32 0, i32 4, i32 undef, i32 5>
+// CHECK: store <4 x float> [[V]], <4 x float>* {{%.*}}
+ *A = __builtin_shufflevector( x, y, 0, 4, -1, 5 );
+}
OpenPOWER on IntegriCloud