@@ -120,19 +120,33 @@ static void createTypedBufferStore(IntrinsicInst *II, StoreInst *SI,
120120 SI->replaceAllUsesWith (Inst);
121121}
122122
123- static void createRawStore (IntrinsicInst *II, StoreInst *SI) {
123+ static void createRawStore (IntrinsicInst *II, StoreInst *SI,
124+ dxil::ResourceTypeInfo &RTI) {
124125 const DataLayout &DL = SI->getDataLayout ();
125126 IRBuilder<> Builder (SI);
126127
127128 Value *V = SI->getValueOperand ();
129+ assert (!V->getType ()->isAggregateType () &&
130+ " Resource store should be scalar or vector type" );
131+
132+ Value *Index = II->getOperand (1 );
128133 // The offset for the rawbuffer load and store ops is always in bytes.
129134 uint64_t AccessSize = 1 ;
130135 Value *Offset =
131136 traverseGEPOffsets (DL, Builder, SI->getPointerOperand (), AccessSize);
132- // TODO: break up larger types
133- auto *Inst = Builder.CreateIntrinsic (
134- Builder.getVoidTy (), Intrinsic::dx_resource_store_rawbuffer,
135- {II->getOperand (0 ), II->getOperand (1 ), Offset, V});
137+
138+ // For raw buffer (ie, HLSL's ByteAddressBuffer), we need to fold the access
139+ // entirely into the index.
140+ if (!RTI.isStruct ()) {
141+ auto *ConstantOffset = dyn_cast<ConstantInt>(Offset);
142+ if (!ConstantOffset || !ConstantOffset->isZero ())
143+ Index = Builder.CreateAdd (Index, Offset);
144+ Offset = llvm::PoisonValue::get (Builder.getInt32Ty ());
145+ }
146+
147+ auto *Inst = Builder.CreateIntrinsic (Builder.getVoidTy (),
148+ Intrinsic::dx_resource_store_rawbuffer,
149+ {II->getOperand (0 ), Index, Offset, V});
136150 SI->replaceAllUsesWith (Inst);
137151}
138152
@@ -143,7 +157,7 @@ static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI,
143157 return createTypedBufferStore (II, SI, RTI);
144158 case dxil::ResourceKind::RawBuffer:
145159 case dxil::ResourceKind::StructuredBuffer:
146- return createRawStore (II, SI);
160+ return createRawStore (II, SI, RTI );
147161 case dxil::ResourceKind::Texture1D:
148162 case dxil::ResourceKind::Texture2D:
149163 case dxil::ResourceKind::Texture2DMS:
@@ -198,20 +212,33 @@ static void createTypedBufferLoad(IntrinsicInst *II, LoadInst *LI,
198212 LI->replaceAllUsesWith (V);
199213}
200214
201- static void createRawLoad (IntrinsicInst *II, LoadInst *LI) {
215+ static void createRawLoad (IntrinsicInst *II, LoadInst *LI,
216+ dxil::ResourceTypeInfo &RTI) {
202217 const DataLayout &DL = LI->getDataLayout ();
203218 IRBuilder<> Builder (LI);
204219
205- // TODO: break up larger types
206220 Type *LoadType = StructType::get (LI->getType (), Builder.getInt1Ty ());
221+ assert (!LI->getType ()->isAggregateType () &&
222+ " Resource load should be scalar or vector type" );
207223
224+ Value *Index = II->getOperand (1 );
208225 // The offset for the rawbuffer load and store ops is always in bytes.
209226 uint64_t AccessSize = 1 ;
210227 Value *Offset =
211228 traverseGEPOffsets (DL, Builder, LI->getPointerOperand (), AccessSize);
229+
230+ // For raw buffer (ie, HLSL's ByteAddressBuffer), we need to fold the access
231+ // entirely into the index.
232+ if (!RTI.isStruct ()) {
233+ auto *ConstantOffset = dyn_cast<ConstantInt>(Offset);
234+ if (!ConstantOffset || !ConstantOffset->isZero ())
235+ Index = Builder.CreateAdd (Index, Offset);
236+ Offset = llvm::PoisonValue::get (Builder.getInt32Ty ());
237+ }
238+
212239 Value *V =
213240 Builder.CreateIntrinsic (LoadType, Intrinsic::dx_resource_load_rawbuffer,
214- {II->getOperand (0 ), II-> getOperand ( 1 ) , Offset});
241+ {II->getOperand (0 ), Index , Offset});
215242 V = Builder.CreateExtractValue (V, {0 });
216243
217244 LI->replaceAllUsesWith (V);
@@ -367,7 +394,7 @@ static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI,
367394 return createTypedBufferLoad (II, LI, RTI);
368395 case dxil::ResourceKind::RawBuffer:
369396 case dxil::ResourceKind::StructuredBuffer:
370- return createRawLoad (II, LI);
397+ return createRawLoad (II, LI, RTI );
371398 case dxil::ResourceKind::CBuffer:
372399 return createCBufferLoad (II, LI, RTI);
373400 case dxil::ResourceKind::Texture1D:
0 commit comments