From: Fariborz Jahanian Date: Tue, 19 Aug 2014 17:17:40 +0000 (+0000) Subject: ext_vector IRGen. Patch to allow indexing into X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6ae70574dec52358121f9d69983abd9673d20c2e;p=clang ext_vector IRGen. Patch to allow indexing into ext_vector_type's 'hi/lo' components when used as lvalue. rdar://18031917 pr20697 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@215991 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index c83cc0ad97..d632aba414 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1361,6 +1361,28 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV) { return RValue::get(Vec); } +/// @brief Generates lvalue for partial ext_vector access. +llvm::Value *CodeGenFunction::EmitExtVectorElementLValue(LValue LV) { + llvm::Value *VectorAddress = LV.getExtVectorAddr(); + const VectorType *ExprVT = LV.getType()->getAs(); + QualType EQT = ExprVT->getElementType(); + llvm::Type *VectorElementTy = CGM.getTypes().ConvertType(EQT); + llvm::Type *VectorElementPtrToTy = VectorElementTy->getPointerTo(); + + llvm::Value *CastToPointerElement = + Builder.CreateBitCast(VectorAddress, + VectorElementPtrToTy, "conv.ptr.element"); + + const llvm::Constant *Elts = LV.getExtVectorElts(); + unsigned ix = getAccessedFieldNo(0, Elts); + + llvm::Value *VectorBasePtrPlusIx = + Builder.CreateInBoundsGEP(CastToPointerElement, + llvm::ConstantInt::get(SizeTy, ix), "add.ptr"); + + return VectorBasePtrPlusIx; +} + /// @brief Load of global gamed gegisters are always calls to intrinsics. RValue CodeGenFunction::EmitLoadOfGlobalRegLValue(LValue LV) { assert((LV.getType()->isIntegerType() || LV.getType()->isPointerType()) && @@ -2323,7 +2345,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, // If the base is a vector type, then we are forming a vector element lvalue // with this subscript. - if (E->getBase()->getType()->isVectorType()) { + if (E->getBase()->getType()->isVectorType() && + !isa(E->getBase())) { // Emit the vector as an lvalue to get its address. LValue LHS = EmitLValue(E->getBase()); assert(LHS.isSimple() && "Can only subscript lvalue vectors here!"); @@ -2339,8 +2362,17 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, // size is a VLA or Objective-C interface. llvm::Value *Address = nullptr; CharUnits ArrayAlignment; - if (const VariableArrayType *vla = - getContext().getAsVariableArrayType(E->getType())) { + if (isa(E->getBase())) { + LValue LV = EmitLValue(E->getBase()); + Address = EmitExtVectorElementLValue(LV); + Address = Builder.CreateInBoundsGEP(Address, Idx, "arrayidx"); + const VectorType *ExprVT = LV.getType()->getAs(); + QualType EQT = ExprVT->getElementType(); + return MakeAddrLValue(Address, EQT, + getContext().getTypeAlignInChars(EQT)); + } + else if (const VariableArrayType *vla = + getContext().getAsVariableArrayType(E->getType())) { // The base must be a pointer, which is not an aggregate. Emit // it. It needs to be emitted first in case it's what captures // the VLA bounds. diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 61d98ab28e..88eedd5dd3 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -2096,6 +2096,8 @@ public: LValue EmitCastLValue(const CastExpr *E); LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e); + + llvm::Value *EmitExtVectorElementLValue(LValue V); RValue EmitRValueForField(LValue LV, const FieldDecl *FD, SourceLocation Loc); diff --git a/test/CodeGen/ext-vector-indexing.c b/test/CodeGen/ext-vector-indexing.c new file mode 100644 index 0000000000..28c0e1e9e2 --- /dev/null +++ b/test/CodeGen/ext-vector-indexing.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s + +typedef __attribute__(( ext_vector_type(4) )) float float4; +// CHECK: @test +void test() +{ + float4 va; + va.hi[0] = 3.0; +// CHECK: [[VA:%.*]] = alloca <4 x float> +// CHECK: [[CONV:%.*]] = bitcast <4 x float>* [[VA]] to float* +// CHECK: [[ADD:%.*]] = getelementptr inbounds float* [[CONV]], i64 2 +// CHECK: [[ARRIDX:%.*]] = getelementptr inbounds float* [[ADD]], i64 0 +// CHECK: store float 3.000000e+00, float* [[ARRIDX]] +}