@@ -116,6 +116,81 @@ 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+ Value *Source) {
122+ // Load each element of the array.
123+ SmallVector<Value *, 4 > LoadedElements;
124+ for (unsigned i = 0 ; i < TargetType->getNumElements (); ++i) {
125+ // Create a GEP to access the i-th element of the array.
126+ SmallVector<Type *, 2 > Types = {Source->getType (), Source->getType ()};
127+ SmallVector<Value *, 4 > Args;
128+ Args.push_back (B.getInt1 (false ));
129+ Args.push_back (Source);
130+ Args.push_back (B.getInt32 (0 ));
131+ Args.push_back (ConstantInt::get (B.getInt32Ty (), i));
132+ auto *ElementPtr = B.CreateIntrinsic (Intrinsic::spv_gep, {Types}, {Args});
133+ GR->buildAssignPtr (B, TargetType->getElementType (), ElementPtr);
134+
135+ // Load the value from the element pointer.
136+ Value *Load = B.CreateLoad (TargetType->getElementType (), ElementPtr);
137+ buildAssignType (B, TargetType->getElementType (), Load);
138+ LoadedElements.push_back (Load);
139+ }
140+
141+ // Build the vector from the loaded elements.
142+ Value *NewVector = PoisonValue::get (TargetType);
143+ buildAssignType (B, TargetType, NewVector);
144+
145+ for (unsigned i = 0 ; i < TargetType->getNumElements (); ++i) {
146+ Value *Index = B.getInt32 (i);
147+ SmallVector<Type *, 4 > Types = {TargetType, TargetType,
148+ TargetType->getElementType (),
149+ Index->getType ()};
150+ SmallVector<Value *> Args = {NewVector, LoadedElements[i], Index};
151+ NewVector = B.CreateIntrinsic (Intrinsic::spv_insertelt, {Types}, {Args});
152+ buildAssignType (B, TargetType, NewVector);
153+ }
154+ return NewVector;
155+ }
156+
157+ // Stores elements from a vector into an array.
158+ void storeArrayFromVector (IRBuilder<> &B, Value *SrcVector,
159+ Value *DstArrayPtr, ArrayType *ArrTy,
160+ Align Alignment) {
161+ auto *VecTy = cast<FixedVectorType>(SrcVector->getType ());
162+
163+ // Ensure the element types of the array and vector are the same.
164+ assert (VecTy->getElementType () == ArrTy->getElementType () &&
165+ " Element types of array and vector must be the same." );
166+
167+ for (unsigned i = 0 ; i < VecTy->getNumElements (); ++i) {
168+ // Create a GEP to access the i-th element of the array.
169+ SmallVector<Type *, 2 > Types = {DstArrayPtr->getType (),
170+ DstArrayPtr->getType ()};
171+ SmallVector<Value *, 4 > Args;
172+ Args.push_back (B.getInt1 (false ));
173+ Args.push_back (DstArrayPtr);
174+ Args.push_back (B.getInt32 (0 ));
175+ Args.push_back (ConstantInt::get (B.getInt32Ty (), i));
176+ auto *ElementPtr = B.CreateIntrinsic (Intrinsic::spv_gep, {Types}, {Args});
177+ GR->buildAssignPtr (B, ArrTy->getElementType (), ElementPtr);
178+
179+ // Extract the element from the vector and store it.
180+ Value *Index = B.getInt32 (i);
181+ SmallVector<Type *, 3 > EltTypes = {VecTy->getElementType (), VecTy,
182+ Index->getType ()};
183+ SmallVector<Value *, 2 > EltArgs = {SrcVector, Index};
184+ Value *Element =
185+ B.CreateIntrinsic (Intrinsic::spv_extractelt, {EltTypes}, {EltArgs});
186+ buildAssignType (B, VecTy->getElementType (), Element);
187+
188+ Types = {Element->getType (), ElementPtr->getType ()};
189+ Args = {Element, ElementPtr, B.getInt16 (2 ), B.getInt8 (Alignment.value ())};
190+ B.CreateIntrinsic (Intrinsic::spv_store, {Types}, {Args});
191+ }
192+ }
193+
119194 // Replaces the load instruction to get rid of the ptrcast used as source
120195 // operand.
121196 void transformLoad (IRBuilder<> &B, LoadInst *LI, Value *CastedOperand,
@@ -154,6 +229,8 @@ class SPIRVLegalizePointerCast : public FunctionPass {
154229 // - float v = s.m;
155230 else if (SST && SST->getTypeAtIndex (0u ) == ToTy)
156231 Output = loadFirstValueFromAggregate (B, ToTy, OriginalOperand, LI);
232+ else if (SAT && DVT && SAT->getElementType () == DVT->getElementType ())
233+ Output = loadVectorFromArray (B, DVT, OriginalOperand);
157234 else
158235 llvm_unreachable (" Unimplemented implicit down-cast from load." );
159236
@@ -288,6 +365,7 @@ class SPIRVLegalizePointerCast : public FunctionPass {
288365 auto *S_VT = dyn_cast<FixedVectorType>(FromTy);
289366 auto *D_ST = dyn_cast<StructType>(ToTy);
290367 auto *D_VT = dyn_cast<FixedVectorType>(ToTy);
368+ auto *D_AT = dyn_cast<ArrayType>(ToTy);
291369
292370 B.SetInsertPoint (BadStore);
293371 if (D_ST && isTypeFirstElementAggregate (FromTy, D_ST))
@@ -296,6 +374,8 @@ class SPIRVLegalizePointerCast : public FunctionPass {
296374 storeVectorFromVector (B, Src, Dst, Alignment);
297375 else if (D_VT && !S_VT && FromTy == D_VT->getElementType ())
298376 storeToFirstValueAggregate (B, Src, Dst, D_VT, Alignment);
377+ else if (D_AT && S_VT && S_VT->getElementType () == D_AT->getElementType ())
378+ storeArrayFromVector (B, Src, Dst, D_AT, Alignment);
299379 else
300380 llvm_unreachable (" Unsupported ptrcast use in store. Please fix." );
301381
0 commit comments