forked from OSchip/llvm-project
parent
e5be1cd635
commit
b699c9bf57
|
@ -20,6 +20,7 @@
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
#include "llvm/Bitcode/Serialize.h"
|
#include "llvm/Bitcode/Serialize.h"
|
||||||
#include "llvm/Bitcode/Deserialize.h"
|
#include "llvm/Bitcode/Deserialize.h"
|
||||||
|
#include "llvm/Support/MathExtras.h"
|
||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
|
@ -284,8 +285,11 @@ ASTContext::getTypeInfo(const Type *T) {
|
||||||
std::pair<uint64_t, unsigned> EltInfo =
|
std::pair<uint64_t, unsigned> EltInfo =
|
||||||
getTypeInfo(cast<VectorType>(T)->getElementType());
|
getTypeInfo(cast<VectorType>(T)->getElementType());
|
||||||
Width = EltInfo.first*cast<VectorType>(T)->getNumElements();
|
Width = EltInfo.first*cast<VectorType>(T)->getNumElements();
|
||||||
// FIXME: This isn't right for unusual vectors
|
|
||||||
Align = Width;
|
Align = Width;
|
||||||
|
// If the alignment is not a power of 2, round up to the next power of 2.
|
||||||
|
// This happens for non-power-of-2 length vectors.
|
||||||
|
// FIXME: this should probably be a target property.
|
||||||
|
Align = 1 << llvm::Log2_32_Ceil(Align);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -631,6 +631,8 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
|
||||||
case X86::BI__builtin_ia32_vec_ext_v2di:
|
case X86::BI__builtin_ia32_vec_ext_v2di:
|
||||||
case X86::BI__builtin_ia32_vec_ext_v4sf:
|
case X86::BI__builtin_ia32_vec_ext_v4sf:
|
||||||
case X86::BI__builtin_ia32_vec_ext_v4si:
|
case X86::BI__builtin_ia32_vec_ext_v4si:
|
||||||
|
case X86::BI__builtin_ia32_vec_ext_v8hi:
|
||||||
|
case X86::BI__builtin_ia32_vec_ext_v4hi:
|
||||||
case X86::BI__builtin_ia32_vec_ext_v2df:
|
case X86::BI__builtin_ia32_vec_ext_v2df:
|
||||||
return Builder.CreateExtractElement(Ops[0], Ops[1], "result");
|
return Builder.CreateExtractElement(Ops[0], Ops[1], "result");
|
||||||
case X86::BI__builtin_ia32_cmpordss:
|
case X86::BI__builtin_ia32_cmpordss:
|
||||||
|
|
|
@ -309,8 +309,8 @@ RValue CodeGenFunction::EmitLoadOfKVCRefLValue(LValue LV,
|
||||||
return EmitObjCPropertyGet(LV.getKVCRefExpr());
|
return EmitObjCPropertyGet(LV.getKVCRefExpr());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a reference to a subset of the elements of a vector, either
|
// If this is a reference to a subset of the elements of a vector, create an
|
||||||
// shuffle the input or extract/insert them as appropriate.
|
// appropriate shufflevector.
|
||||||
RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV,
|
RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV,
|
||||||
QualType ExprType) {
|
QualType ExprType) {
|
||||||
llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddr(),
|
llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddr(),
|
||||||
|
@ -326,41 +326,21 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV,
|
||||||
llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx);
|
llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx);
|
||||||
return RValue::get(Builder.CreateExtractElement(Vec, Elt, "tmp"));
|
return RValue::get(Builder.CreateExtractElement(Vec, Elt, "tmp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the source and destination have the same number of elements, use a
|
// Always use shuffle vector to try to retain the original program structure
|
||||||
// vector shuffle instead of insert/extracts.
|
|
||||||
unsigned NumResultElts = ExprVT->getNumElements();
|
unsigned NumResultElts = ExprVT->getNumElements();
|
||||||
unsigned NumSourceElts =
|
|
||||||
cast<llvm::VectorType>(Vec->getType())->getNumElements();
|
|
||||||
|
|
||||||
if (NumResultElts == NumSourceElts) {
|
llvm::SmallVector<llvm::Constant*, 4> Mask;
|
||||||
llvm::SmallVector<llvm::Constant*, 4> Mask;
|
|
||||||
for (unsigned i = 0; i != NumResultElts; ++i) {
|
|
||||||
unsigned InIdx = getAccessedFieldNo(i, Elts);
|
|
||||||
Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx));
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
|
|
||||||
Vec = Builder.CreateShuffleVector(Vec,
|
|
||||||
llvm::UndefValue::get(Vec->getType()),
|
|
||||||
MaskV, "tmp");
|
|
||||||
return RValue::get(Vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start out with an undef of the result type.
|
|
||||||
llvm::Value *Result = llvm::UndefValue::get(ConvertType(ExprType));
|
|
||||||
|
|
||||||
// Extract/Insert each element of the result.
|
|
||||||
for (unsigned i = 0; i != NumResultElts; ++i) {
|
for (unsigned i = 0; i != NumResultElts; ++i) {
|
||||||
unsigned InIdx = getAccessedFieldNo(i, Elts);
|
unsigned InIdx = getAccessedFieldNo(i, Elts);
|
||||||
llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx);
|
Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx));
|
||||||
Elt = Builder.CreateExtractElement(Vec, Elt, "tmp");
|
|
||||||
|
|
||||||
llvm::Value *OutIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, i);
|
|
||||||
Result = Builder.CreateInsertElement(Result, Elt, OutIdx, "tmp");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return RValue::get(Result);
|
llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
|
||||||
|
Vec = Builder.CreateShuffleVector(Vec,
|
||||||
|
llvm::UndefValue::get(Vec->getType()),
|
||||||
|
MaskV, "tmp");
|
||||||
|
return RValue::get(Vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -548,15 +528,54 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
|
||||||
|
|
||||||
if (const VectorType *VTy = Ty->getAsVectorType()) {
|
if (const VectorType *VTy = Ty->getAsVectorType()) {
|
||||||
unsigned NumSrcElts = VTy->getNumElements();
|
unsigned NumSrcElts = VTy->getNumElements();
|
||||||
|
unsigned NumDstElts =
|
||||||
// Extract/Insert each element.
|
cast<llvm::VectorType>(Vec->getType())->getNumElements();
|
||||||
for (unsigned i = 0; i != NumSrcElts; ++i) {
|
if (NumDstElts == NumSrcElts) {
|
||||||
llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, i);
|
// Use shuffle vector is the src and destination are the same number
|
||||||
Elt = Builder.CreateExtractElement(SrcVal, Elt, "tmp");
|
// of elements
|
||||||
|
llvm::SmallVector<llvm::Constant*, 4> Mask;
|
||||||
unsigned Idx = getAccessedFieldNo(i, Elts);
|
for (unsigned i = 0; i != NumSrcElts; ++i) {
|
||||||
llvm::Value *OutIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, Idx);
|
unsigned InIdx = getAccessedFieldNo(i, Elts);
|
||||||
Vec = Builder.CreateInsertElement(Vec, Elt, OutIdx, "tmp");
|
Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx));
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
|
||||||
|
Vec = Builder.CreateShuffleVector(SrcVal,
|
||||||
|
llvm::UndefValue::get(Vec->getType()),
|
||||||
|
MaskV, "tmp");
|
||||||
|
}
|
||||||
|
else if (NumDstElts > NumSrcElts) {
|
||||||
|
// Extended the source vector to the same length and then shuffle it
|
||||||
|
// into the destination.
|
||||||
|
// FIXME: since we're shuffling with undef, can we just use the indices
|
||||||
|
// into that? This could be simpler.
|
||||||
|
llvm::SmallVector<llvm::Constant*, 4> ExtMask;
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i != NumSrcElts; ++i)
|
||||||
|
ExtMask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, i));
|
||||||
|
for (; i != NumDstElts; ++i)
|
||||||
|
ExtMask.push_back(llvm::UndefValue::get(llvm::Type::Int32Ty));
|
||||||
|
llvm::Value *ExtMaskV = llvm::ConstantVector::get(&ExtMask[0],
|
||||||
|
ExtMask.size());
|
||||||
|
llvm::Value *ExtSrcVal = Builder.CreateShuffleVector(SrcVal,
|
||||||
|
llvm::UndefValue::get(SrcVal->getType()),
|
||||||
|
ExtMaskV, "tmp");
|
||||||
|
// build identity
|
||||||
|
llvm::SmallVector<llvm::Constant*, 4> Mask;
|
||||||
|
for (unsigned i = 0; i != NumDstElts; ++i) {
|
||||||
|
Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, i));
|
||||||
|
}
|
||||||
|
// modify when what gets shuffled in
|
||||||
|
for (unsigned i = 0; i != NumSrcElts; ++i) {
|
||||||
|
unsigned Idx = getAccessedFieldNo(i, Elts);
|
||||||
|
Mask[Idx] =llvm::ConstantInt::get(llvm::Type::Int32Ty, i+NumDstElts);
|
||||||
|
}
|
||||||
|
llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
|
||||||
|
Vec = Builder.CreateShuffleVector(Vec, ExtSrcVal, MaskV, "tmp");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// We should never shorten the vector
|
||||||
|
assert(0 && "unexpected shorten vector length");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If the Src is a scalar (not a vector) it must be updating one element.
|
// If the Src is a scalar (not a vector) it must be updating one element.
|
||||||
|
|
|
@ -409,10 +409,26 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
|
||||||
}
|
}
|
||||||
|
|
||||||
// A scalar can be splatted to an extended vector of the same element type
|
// A scalar can be splatted to an extended vector of the same element type
|
||||||
if (DstType->isExtVectorType() && !isa<VectorType>(SrcType) &&
|
if (DstType->isExtVectorType() && !isa<VectorType>(SrcType)) {
|
||||||
cast<llvm::VectorType>(DstTy)->getElementType() == Src->getType())
|
// Cast the scalar to element type
|
||||||
return CGF.EmitVector(&Src, DstType->getAsVectorType()->getNumElements(),
|
QualType EltTy = DstType->getAsExtVectorType()->getElementType();
|
||||||
true);
|
llvm::Value *Elt = EmitScalarConversion(Src, SrcType, EltTy);
|
||||||
|
|
||||||
|
// Insert the element in element zero of an undef vector
|
||||||
|
llvm::Value *UnV = llvm::UndefValue::get(DstTy);
|
||||||
|
llvm::Value *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
|
||||||
|
UnV = Builder.CreateInsertElement(UnV, Elt, Idx, "tmp");
|
||||||
|
|
||||||
|
// Splat the element across to all elements
|
||||||
|
llvm::SmallVector<llvm::Constant*, 16> Args;
|
||||||
|
unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
|
||||||
|
for (unsigned i = 0; i < NumElements; i++)
|
||||||
|
Args.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0));
|
||||||
|
|
||||||
|
llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], NumElements);
|
||||||
|
llvm::Value *Yay = Builder.CreateShuffleVector(UnV, UnV, Mask, "splat");
|
||||||
|
return Yay;
|
||||||
|
}
|
||||||
|
|
||||||
// Allow bitcast from vector to integer/fp of the same size.
|
// Allow bitcast from vector to integer/fp of the same size.
|
||||||
if (isa<llvm::VectorType>(Src->getType()) ||
|
if (isa<llvm::VectorType>(Src->getType()) ||
|
||||||
|
|
|
@ -151,7 +151,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer)
|
||||||
|
|
||||||
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
|
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
|
||||||
/// If there is already an implicit cast, merge into the existing one.
|
/// If there is already an implicit cast, merge into the existing one.
|
||||||
/// If isLvalue, the result of the cast is an lvalue.
|
/// If isLvalue, the result of the cast is an lvalue.
|
||||||
void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, bool isLvalue) {
|
void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, bool isLvalue) {
|
||||||
QualType ExprTy = Context.getCanonicalType(Expr->getType());
|
QualType ExprTy = Context.getCanonicalType(Expr->getType());
|
||||||
QualType TypeTy = Context.getCanonicalType(Ty);
|
QualType TypeTy = Context.getCanonicalType(Ty);
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
// RUN: clang %s -emit-llvm -o - | not grep 'extractelement'
|
||||||
|
// RUN: clang %s -emit-llvm -o - | not grep 'insertelement'
|
||||||
|
// RUN: clang %s -emit-llvm -o - | grep 'shufflevector'
|
||||||
|
|
||||||
|
typedef __attribute__(( ext_vector_type(2) )) float float2;
|
||||||
|
typedef __attribute__(( ext_vector_type(4) )) float float4;
|
||||||
|
|
||||||
|
float2 test1(float4 V) {
|
||||||
|
return V.xy + V.wz;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 test2(float4 V) {
|
||||||
|
float2 W = V.ww;
|
||||||
|
return W.xyxy + W.yxyx;
|
||||||
|
}
|
Loading…
Reference in New Issue