1- // ===-- SPIRVLegalizePointerLoad .cpp ----------------------*- C++ -*-===//
1+ // ===-- SPIRVLegalizePointerCast .cpp ----------------------*- C++ -*-===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
1313// by logical SPIR-V.
1414//
1515// This pass relies on the assign_ptr_type intrinsic to deduce the type of the
16- // pointee. All occurrences of `ptrcast` must be replaced because the lead to
17- // invalid SPIR-V. Unhandled cases result in an error .
16+ // pointed values, must replace all occurences of `ptrcast`. This is why
17+ // unhandled cases are reported as unreachable: we MUST cover all cases .
1818//
1919// 1. Loading the first element of an array
2020//
5757using namespace llvm ;
5858
5959namespace llvm {
60- void initializeSPIRVLegalizePointerLoadPass (PassRegistry &);
60+ void initializeSPIRVLegalizePointerCastPass (PassRegistry &);
6161}
6262
63- class SPIRVLegalizePointerLoad : public FunctionPass {
64-
65- // Replace all uses of a |Old| with |New| updates the global registry type
66- // mappings.
67- void replaceAllUsesWith (Value *Old, Value *New) {
68- Old->replaceAllUsesWith (New);
69- GR->updateIfExistDeducedElementType (Old, New, /* deleteOld = */ true );
70- GR->updateIfExistAssignPtrTypeInstr (Old, New, /* deleteOld = */ true );
71- }
63+ class SPIRVLegalizePointerCast : public FunctionPass {
7264
7365 // Builds the `spv_assign_type` assigning |Ty| to |Value| at the current
7466 // builder position.
@@ -79,89 +71,54 @@ class SPIRVLegalizePointerLoad : public FunctionPass {
7971 GR->addAssignPtrTypeInstr (Arg, AssignCI);
8072 }
8173
82- // Loads a single scalar of type |To| from the vector pointed by |Source| of
83- // the type |From|. Returns the loaded value.
84- Value *loadScalarFromVector (IRBuilder<> &B, Value *Source,
85- FixedVectorType *From) {
86-
87- LoadInst *NewLoad = B.CreateLoad (From, Source);
88- buildAssignType (B, From, NewLoad);
89-
90- SmallVector<Value *, 2 > Args = {NewLoad, B.getInt64 (0 )};
91- SmallVector<Type *, 3 > Types = {From->getElementType (), Args[0 ]->getType (),
92- Args[1 ]->getType ()};
93- Value *Extracted =
94- B.CreateIntrinsic (Intrinsic::spv_extractelt, {Types}, {Args});
95- buildAssignType (B, Extracted->getType (), Extracted);
96- return Extracted;
97- }
98-
99- // Loads parts of the vector of type |From| from the pointer |Source| and
100- // create a new vector of type |To|. |To| must be a vector type, and element
101- // types of |To| and |From| must match. Returns the loaded value.
102- Value *loadVectorFromVector (IRBuilder<> &B, FixedVectorType *From,
103- FixedVectorType *To, Value *Source) {
74+ // Loads parts of the vector of type |SourceType| from the pointer |Source|
75+ // and create a new vector of type |TargetType|. |TargetType| must be a vector
76+ // type, and element types of |TargetType| and |SourceType| must match.
77+ // Returns the loaded value.
78+ Value *loadVectorFromVector (IRBuilder<> &B, FixedVectorType *SourceType,
79+ FixedVectorType *TargetType, Value *Source) {
10480 // We expect the codegen to avoid doing implicit bitcast from a load.
105- assert (To->getElementType () == From->getElementType ());
106- assert (To->getNumElements () < From->getNumElements ());
107-
108- LoadInst *NewLoad = B.CreateLoad (From, Source);
109- buildAssignType (B, From, NewLoad);
81+ assert (TargetType->getElementType () == SourceType->getElementType ());
82+ assert (TargetType->getNumElements () < SourceType->getNumElements ());
11083
111- auto ConstInt = ConstantInt::get (IntegerType::get (B.getContext (), 32 ), 0 );
112- ElementCount VecElemCount = ElementCount::getFixed (To->getNumElements ());
113- Value *Output = ConstantVector::getSplat (VecElemCount, ConstInt);
114- for (unsigned I = 0 ; I < To->getNumElements (); ++I) {
115- Value *Extracted = nullptr ;
116- {
117- SmallVector<Value *, 2 > Args = {NewLoad, B.getInt64 (I)};
118- SmallVector<Type *, 3 > Types = {To->getElementType (),
119- Args[0 ]->getType (), Args[1 ]->getType ()};
120- Extracted =
121- B.CreateIntrinsic (Intrinsic::spv_extractelt, {Types}, {Args});
122- buildAssignType (B, Extracted->getType (), Extracted);
123- }
124- assert (Extracted != nullptr );
84+ LoadInst *NewLoad = B.CreateLoad (SourceType, Source);
85+ buildAssignType (B, SourceType, NewLoad);
12586
126- {
127- SmallVector<Value *, 3 > Args = {Output, Extracted, B.getInt64 (I)};
128- SmallVector<Type *, 4 > Types = {Args[0 ]->getType (), Args[0 ]->getType (),
129- Args[1 ]->getType (), Args[2 ]->getType ()};
130- Output = B.CreateIntrinsic (Intrinsic::spv_insertelt, {Types}, {Args});
131- buildAssignType (B, Output->getType (), Output);
132- }
133- }
87+ SmallVector<int > Mask (/* Size= */ TargetType->getNumElements (),
88+ /* Value= */ 0 );
89+ Value *Output = B.CreateShuffleVector (NewLoad, NewLoad, Mask);
90+ buildAssignType (B, TargetType, Output);
13491 return Output;
13592 }
13693
137- // Loads the first value in an array pointed by |Source| of type |From|. Load
138- // flags will be copied from |BadLoad|, which should be the illegal load being
139- // legalized. Returns the loaded value.
140- Value *loadFirstValueFromArray (IRBuilder<> &B, ArrayType *From, Value *Source ,
141- LoadInst *BadLoad) {
94+ // Loads the first value in an aggregate pointed by |Source| of containing
95+ // elements of type |ElementType|. Load flags will be copied from |BadLoad|,
96+ // which should be the load being legalized. Returns the loaded value.
97+ Value *loadFirstValueFromAggregate (IRBuilder<> &B, Type *ElementType ,
98+ Value *Source, LoadInst *BadLoad) {
14299 SmallVector<Type *, 2 > Types = {BadLoad->getPointerOperandType (),
143100 BadLoad->getPointerOperandType ()};
144- SmallVector<Value *, 3 > Args{/* isInBounds= */ B.getInt1 (true ), Source,
145- B.getInt64 (0 ), B.getInt64 (0 )};
101+ SmallVector<Value *, 3 > Args{/* isInBounds= */ B.getInt1 (false ), Source,
102+ B.getInt32 (0 ), B.getInt32 (0 )};
146103 auto *GEP = B.CreateIntrinsic (Intrinsic::spv_gep, {Types}, {Args});
147- GR->buildAssignPtr (B, From-> getElementType () , GEP);
104+ GR->buildAssignPtr (B, ElementType , GEP);
148105
149106 const auto *TLI = TM->getSubtargetImpl ()->getTargetLowering ();
150107 MachineMemOperand::Flags Flags = TLI->getLoadMemOperandFlags (
151108 *BadLoad, BadLoad->getFunction ()->getDataLayout ());
152109 Instruction *LI = B.CreateIntrinsic (
153110 Intrinsic::spv_load, {BadLoad->getOperand (0 )->getType ()},
154111 {GEP, B.getInt16 (Flags), B.getInt8 (BadLoad->getAlign ().value ())});
155- buildAssignType (B, From-> getElementType () , LI);
112+ buildAssignType (B, ElementType , LI);
156113 return LI;
157114 }
158115
159- // Transforms an illegal partial load into a sequence we can lower to logical
160- // SPIR-V .
116+ // Replaces the load instruction to get rid of the ptrcast used as source
117+ // operand .
161118 void transformLoad (IRBuilder<> &B, LoadInst *LI, Value *CastedOperand,
162119 Value *OriginalOperand) {
163120 Type *FromTy = GR->findDeducedElementType (OriginalOperand);
164- Type *ToTy /* -fruity */ = GR->findDeducedElementType (CastedOperand);
121+ Type *ToTy = GR->findDeducedElementType (CastedOperand);
165122 Value *Output = nullptr ;
166123
167124 auto *SAT = dyn_cast<ArrayType>(FromTy);
@@ -174,12 +131,14 @@ class SPIRVLegalizePointerLoad : public FunctionPass {
174131 // Loading 1st element.
175132 // - float a = array[0];
176133 if (SAT && SAT->getElementType () == ToTy)
177- Output = loadFirstValueFromArray (B, SAT, OriginalOperand, LI);
134+ Output = loadFirstValueFromAggregate (B, SAT->getElementType (),
135+ OriginalOperand, LI);
178136 // Destination is the element type of Source, and source is a vector ->
179137 // Vector to scalar.
180138 // - float a = vector.x;
181139 else if (!DVT && SVT && SVT->getElementType () == ToTy) {
182- Output = loadScalarFromVector (B, OriginalOperand, SVT);
140+ Output = loadFirstValueFromAggregate (B, SVT->getElementType (),
141+ OriginalOperand, LI);
183142 }
184143 // Destination is a smaller vector than source.
185144 // - float3 v3 = vector4;
@@ -188,7 +147,7 @@ class SPIRVLegalizePointerLoad : public FunctionPass {
188147 else
189148 llvm_unreachable (" Unimplemented implicit down-cast from load." );
190149
191- replaceAllUsesWith (LI, Output);
150+ GR-> replaceAllUsesWith (LI, Output, /* DeleteOld= */ true );
192151 DeadInstructions.push_back (LI);
193152 }
194153
@@ -220,8 +179,8 @@ class SPIRVLegalizePointerLoad : public FunctionPass {
220179 }
221180
222181public:
223- SPIRVLegalizePointerLoad (SPIRVTargetMachine *TM) : FunctionPass(ID), TM(TM) {
224- initializeSPIRVLegalizePointerLoadPass (*PassRegistry::getPassRegistry ());
182+ SPIRVLegalizePointerCast (SPIRVTargetMachine *TM) : FunctionPass(ID), TM(TM) {
183+ initializeSPIRVLegalizePointerCastPass (*PassRegistry::getPassRegistry ());
225184 };
226185
227186 virtual bool runOnFunction (Function &F) override {
@@ -256,10 +215,10 @@ class SPIRVLegalizePointerLoad : public FunctionPass {
256215 static char ID;
257216};
258217
259- char SPIRVLegalizePointerLoad ::ID = 0 ;
260- INITIALIZE_PASS (SPIRVLegalizePointerLoad , " spirv-legalize-bitcast" ,
218+ char SPIRVLegalizePointerCast ::ID = 0 ;
219+ INITIALIZE_PASS (SPIRVLegalizePointerCast , " spirv-legalize-bitcast" ,
261220 " SPIRV legalize bitcast pass" , false , false )
262221
263- FunctionPass *llvm::createSPIRVLegalizePointerLoadPass (SPIRVTargetMachine *TM) {
264- return new SPIRVLegalizePointerLoad (TM);
222+ FunctionPass *llvm::createSPIRVLegalizePointerCastPass (SPIRVTargetMachine *TM) {
223+ return new SPIRVLegalizePointerCast (TM);
265224}
0 commit comments