@@ -2801,26 +2801,56 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
28012801 LValue Dst) {
28022802 llvm::Value *SrcVal = Src.getScalarVal ();
28032803 Address DstAddr = Dst.getExtVectorAddress ();
2804+ const llvm::Constant *Elts = Dst.getExtVectorElts ();
28042805 if (DstAddr.getElementType ()->getScalarSizeInBits () >
28052806 SrcVal->getType ()->getScalarSizeInBits ())
28062807 SrcVal = Builder.CreateZExt (
28072808 SrcVal, convertTypeForLoadStore (Dst.getType (), SrcVal->getType ()));
28082809
2809- // HLSL allows storing to scalar values through ExtVector component LValues.
2810- // To support this we need to handle the case where the destination address is
2811- // a scalar.
2812- if (!DstAddr.getElementType ()->isVectorTy ()) {
2813- assert (!Dst.getType ()->isVectorType () &&
2814- " this should only occur for non-vector l-values" );
2815- Builder.CreateStore (SrcVal, DstAddr, Dst.isVolatileQualified ());
2810+ if (getLangOpts ().HLSL ) {
2811+ llvm::Type *DestAddrTy = DstAddr.getElementType ();
2812+ // HLSL allows storing to scalar values through ExtVector component LValues.
2813+ // To support this we need to handle the case where the destination address
2814+ // is a scalar.
2815+ if (!DestAddrTy->isVectorTy ()) {
2816+ assert (!Dst.getType ()->isVectorType () &&
2817+ " this should only occur for non-vector l-values" );
2818+ Builder.CreateStore (SrcVal, DstAddr, Dst.isVolatileQualified ());
2819+ return ;
2820+ }
2821+
2822+ // HLSL allows direct access to vector elements, so storing to individual
2823+ // elements of a vector through ExtVector is handled as separate store
2824+ // instructions.
2825+ // If we are updating multiple elements, Dst and Src are vectors; for
2826+ // a single element update they are scalars.
2827+ const VectorType *VTy = Dst.getType ()->getAs <VectorType>();
2828+ unsigned NumSrcElts = VTy ? VTy->getNumElements () : 1 ;
2829+ CharUnits ElemAlign = CharUnits::fromQuantity (
2830+ CGM.getDataLayout ().getPrefTypeAlign (DestAddrTy->getScalarType ()));
2831+ llvm::Value *Zero = llvm::ConstantInt::get (Int32Ty, 0 );
2832+
2833+ for (unsigned I = 0 ; I != NumSrcElts; ++I) {
2834+ llvm::Value *Val = VTy ? Builder.CreateExtractElement (
2835+ SrcVal, llvm::ConstantInt::get (Int32Ty, I))
2836+ : SrcVal;
2837+ unsigned FieldNo = getAccessedFieldNo (I, Elts);
2838+ Address DstElemAddr = Address::invalid ();
2839+ if (FieldNo == 0 )
2840+ DstElemAddr = DstAddr.withAlignment (ElemAlign);
2841+ else
2842+ DstElemAddr = Builder.CreateGEP (
2843+ DstAddr, {Zero, llvm::ConstantInt::get (Int32Ty, FieldNo)},
2844+ DestAddrTy, ElemAlign);
2845+ Builder.CreateStore (Val, DstElemAddr, Dst.isVolatileQualified ());
2846+ }
28162847 return ;
28172848 }
28182849
28192850 // This access turns into a read/modify/write of the vector. Load the input
28202851 // value now.
28212852 llvm::Value *Vec = Builder.CreateLoad (DstAddr, Dst.isVolatileQualified ());
28222853 llvm::Type *VecTy = Vec->getType ();
2823- const llvm::Constant *Elts = Dst.getExtVectorElts ();
28242854
28252855 if (const VectorType *VTy = Dst.getType ()->getAs <VectorType>()) {
28262856 unsigned NumSrcElts = VTy->getNumElements ();
0 commit comments