@@ -116,6 +116,85 @@ class SPIRVLegalizePointerCast : public FunctionPass {
116116 return LI;
117117 }
118118
119+ // Loads elements from an array and constructs a vector.
120+ Value *loadVectorFromArray (IRBuilder<> &B, FixedVectorType *TargetType,
121+ ArrayType *SourceType, Value *Source) {
122+ // Ensure the element types of the array and vector are the same.
123+ assert (TargetType->getElementType () == SourceType->getElementType () &&
124+ " Element types of array and vector must be the same." );
125+
126+ // Load each element of the array.
127+ SmallVector<Value *, 4 > LoadedElements;
128+ for (unsigned i = 0 ; i < TargetType->getNumElements (); ++i) {
129+ // Create a GEP to access the i-th element of the array.
130+ SmallVector<Type *, 2 > Types = {Source->getType (), Source->getType ()};
131+ SmallVector<Value *, 4 > Args;
132+ Args.push_back (B.getInt1 (true ));
133+ Args.push_back (Source);
134+ Args.push_back (B.getInt32 (0 ));
135+ Args.push_back (ConstantInt::get (B.getInt32Ty (), i));
136+ auto *ElementPtr = B.CreateIntrinsic (Intrinsic::spv_gep, {Types}, {Args});
137+ GR->buildAssignPtr (B, TargetType->getElementType (), ElementPtr);
138+
139+ // Load the value from the element pointer.
140+ Value *Load = B.CreateLoad (TargetType->getElementType (), ElementPtr);
141+ buildAssignType (B, TargetType->getElementType (), Load);
142+ LoadedElements.push_back (Load);
143+ }
144+
145+ // Build the vector from the loaded elements.
146+ Value *NewVector = UndefValue::get (TargetType);
147+ buildAssignType (B, TargetType, NewVector);
148+
149+ for (unsigned i = 0 ; i < TargetType->getNumElements (); ++i) {
150+ Value *Index = B.getInt32 (i);
151+ SmallVector<Type *, 4 > Types = {TargetType, TargetType,
152+ TargetType->getElementType (),
153+ Index->getType ()};
154+ SmallVector<Value *> Args = {NewVector, LoadedElements[i], Index};
155+ NewVector = B.CreateIntrinsic (Intrinsic::spv_insertelt, {Types}, {Args});
156+ buildAssignType (B, TargetType, NewVector);
157+ }
158+ return NewVector;
159+ }
160+
161+ // Stores elements from a vector into an array.
162+ void storeArrayFromVector (IRBuilder<> &B, Value *SrcVector,
163+ Value *DstArrayPtr, ArrayType *ArrTy,
164+ Align Alignment) {
165+ auto *VecTy = cast<FixedVectorType>(SrcVector->getType ());
166+
167+ // Ensure the element types of the array and vector are the same.
168+ assert (VecTy->getElementType () == ArrTy->getElementType () &&
169+ " Element types of array and vector must be the same." );
170+
171+ for (unsigned i = 0 ; i < VecTy->getNumElements (); ++i) {
172+ // Create a GEP to access the i-th element of the array.
173+ SmallVector<Type *, 2 > Types = {DstArrayPtr->getType (),
174+ DstArrayPtr->getType ()};
175+ SmallVector<Value *, 4 > Args;
176+ Args.push_back (B.getInt1 (true ));
177+ Args.push_back (DstArrayPtr);
178+ Args.push_back (B.getInt32 (0 ));
179+ Args.push_back (ConstantInt::get (B.getInt32Ty (), i));
180+ auto *ElementPtr = B.CreateIntrinsic (Intrinsic::spv_gep, {Types}, {Args});
181+ GR->buildAssignPtr (B, ArrTy->getElementType (), ElementPtr);
182+
183+ // Extract the element from the vector and store it.
184+ Value *Index = B.getInt32 (i);
185+ SmallVector<Type *, 3 > EltTypes = {VecTy->getElementType (), VecTy,
186+ Index->getType ()};
187+ SmallVector<Value *, 2 > EltArgs = {SrcVector, Index};
188+ Value *Element =
189+ B.CreateIntrinsic (Intrinsic::spv_extractelt, {EltTypes}, {EltArgs});
190+ buildAssignType (B, VecTy->getElementType (), Element);
191+
192+ Types = {Element->getType (), ElementPtr->getType ()};
193+ Args = {Element, ElementPtr, B.getInt16 (2 ), B.getInt8 (Alignment.value ())};
194+ B.CreateIntrinsic (Intrinsic::spv_store, {Types}, {Args});
195+ }
196+ }
197+
119198 // Replaces the load instruction to get rid of the ptrcast used as source
120199 // operand.
121200 void transformLoad (IRBuilder<> &B, LoadInst *LI, Value *CastedOperand,
@@ -154,6 +233,8 @@ class SPIRVLegalizePointerCast : public FunctionPass {
154233 // - float v = s.m;
155234 else if (SST && SST->getTypeAtIndex (0u ) == ToTy)
156235 Output = loadFirstValueFromAggregate (B, ToTy, OriginalOperand, LI);
236+ else if (SAT && DVT && SAT->getElementType () == DVT->getElementType ())
237+ Output = loadVectorFromArray (B, DVT, SAT, OriginalOperand);
157238 else
158239 llvm_unreachable (" Unimplemented implicit down-cast from load." );
159240
@@ -288,6 +369,7 @@ class SPIRVLegalizePointerCast : public FunctionPass {
288369 auto *S_VT = dyn_cast<FixedVectorType>(FromTy);
289370 auto *D_ST = dyn_cast<StructType>(ToTy);
290371 auto *D_VT = dyn_cast<FixedVectorType>(ToTy);
372+ auto *D_AT = dyn_cast<ArrayType>(ToTy);
291373
292374 B.SetInsertPoint (BadStore);
293375 if (D_ST && isTypeFirstElementAggregate (FromTy, D_ST))
@@ -296,6 +378,8 @@ class SPIRVLegalizePointerCast : public FunctionPass {
296378 storeVectorFromVector (B, Src, Dst, Alignment);
297379 else if (D_VT && !S_VT && FromTy == D_VT->getElementType ())
298380 storeToFirstValueAggregate (B, Src, Dst, D_VT, Alignment);
381+ else if (D_AT && S_VT && S_VT->getElementType () == D_AT->getElementType ())
382+ storeArrayFromVector (B, Src, Dst, D_AT, Alignment);
299383 else
300384 llvm_unreachable (" Unsupported ptrcast use in store. Please fix." );
301385
0 commit comments