@@ -51,6 +51,9 @@ struct PropagateJuliaAddrspaces : public FunctionPass, public InstVisitor<Propag
51
51
void visitLoadInst (LoadInst &LI);
52
52
void visitMemSetInst (MemSetInst &MI);
53
53
void visitMemTransferInst (MemTransferInst &MTI);
54
+
55
+ private:
56
+ void PoisonValues (std::vector<Value *> &Worklist);
54
57
};
55
58
56
59
bool PropagateJuliaAddrspaces::runOnFunction (Function &F) {
@@ -74,67 +77,137 @@ static bool isSpecialAS(unsigned AS) {
74
77
return AddressSpace::FirstSpecial <= AS && AS <= AddressSpace::LastSpecial;
75
78
}
76
79
80
+ void PropagateJuliaAddrspaces::PoisonValues (std::vector<Value *> &Worklist) {
81
+ while (!Worklist.empty ()) {
82
+ Value *CurrentV = Worklist.back ();
83
+ Worklist.pop_back ();
84
+ for (Value *User : CurrentV->users ()) {
85
+ if (Visited.count (User))
86
+ continue ;
87
+ Visited.insert (CurrentV);
88
+ Worklist.push_back (User);
89
+ }
90
+ }
91
+ }
92
+
77
93
Value *PropagateJuliaAddrspaces::LiftPointer (Value *V, Type *LocTy, Instruction *InsertPt) {
78
94
SmallVector<Value *, 4 > Stack;
79
- Value *CurrentV = V;
95
+ std::vector<Value *> Worklist;
96
+ std::set<Value *> LocalVisited;
97
+ Worklist.push_back (V);
80
98
// Follow pointer casts back, see if we're based on a pointer in
81
99
// an untracked address space, in which case we're allowed to drop
82
100
// intermediate addrspace casts.
83
- while (true ) {
84
- Stack.push_back (CurrentV);
85
- if (isa<BitCastInst>(CurrentV))
86
- CurrentV = cast<BitCastInst>(CurrentV)->getOperand (0 );
87
- else if (isa<AddrSpaceCastInst>(CurrentV)) {
88
- CurrentV = cast<AddrSpaceCastInst>(CurrentV)->getOperand (0 );
89
- if (!isSpecialAS (getValueAddrSpace (CurrentV)))
90
- break ;
101
+ while (!Worklist.empty ()) {
102
+ Value *CurrentV = Worklist.back ();
103
+ Worklist.pop_back ();
104
+ if (LocalVisited.count (CurrentV)) {
105
+ continue ;
91
106
}
92
- else if (isa<GetElementPtrInst>(CurrentV)) {
93
- if (LiftingMap.count (CurrentV)) {
94
- CurrentV = LiftingMap[CurrentV];
107
+ while (true ) {
108
+ if (auto *BCI = dyn_cast<BitCastInst>(CurrentV))
109
+ CurrentV = BCI->getOperand (0 );
110
+ else if (auto *ACI = dyn_cast<AddrSpaceCastInst>(CurrentV)) {
111
+ CurrentV = ACI->getOperand (0 );
112
+ if (!isSpecialAS (getValueAddrSpace (ACI)))
113
+ break ;
114
+ }
115
+ else if (auto *GEP = dyn_cast<GetElementPtrInst>(CurrentV)) {
116
+ if (LiftingMap.count (GEP)) {
117
+ CurrentV = LiftingMap[GEP];
118
+ break ;
119
+ } else if (Visited.count (GEP)) {
120
+ return nullptr ;
121
+ }
122
+ Stack.push_back (GEP);
123
+ LocalVisited.insert (GEP);
124
+ CurrentV = GEP->getOperand (0 );
125
+ } else if (auto *Phi = dyn_cast<PHINode>(CurrentV)) {
126
+ if (LiftingMap.count (Phi)) {
127
+ break ;
128
+ }
129
+ for (Value *Incoming : Phi->incoming_values ()) {
130
+ Worklist.push_back (Incoming);
131
+ }
132
+ Stack.push_back (Phi);
133
+ LocalVisited.insert (Phi);
134
+ break ;
135
+ } else {
136
+ // Ok, we've reached a leaf - check if it is eligible for lifting
137
+ if (!CurrentV->getType ()->isPointerTy () ||
138
+ isSpecialAS (getValueAddrSpace (CurrentV))) {
139
+ // If not, poison all (recursive) users of this value, to prevent
140
+ // looking at them again in future iterations.
141
+ Worklist.clear ();
142
+ Worklist.push_back (CurrentV);
143
+ Visited.insert (CurrentV);
144
+ PoisonValues (Worklist);
145
+ return nullptr ;
146
+ }
95
147
break ;
96
- } else if (Visited.count (CurrentV)) {
97
- return nullptr ;
98
148
}
99
- Visited.insert (CurrentV);
100
- CurrentV = cast<GetElementPtrInst>(CurrentV)->getOperand (0 );
101
- } else
102
- break ;
149
+ }
103
150
}
104
- if (!CurrentV->getType ()->isPointerTy ())
105
- return nullptr ;
106
- if (isSpecialAS (getValueAddrSpace (CurrentV)))
107
- return nullptr ;
108
- // Ok, we're allowed to change the address space of this load, go back and
109
- // reconstitute any GEPs in the new address space.
110
- for (Value *V : llvm::reverse (Stack)) {
111
- GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(V);
112
- if (!GEP)
113
- continue ;
114
- if (LiftingMap.count (GEP)) {
115
- CurrentV = LiftingMap[GEP];
151
+
152
+ // Go through and insert lifted versions of all instructions on the list.
153
+ std::vector<Value *> ToRevisit;
154
+ for (Value *V : Stack) {
155
+ if (LiftingMap.count (V))
116
156
continue ;
157
+ if (auto *GEP = dyn_cast<GetElementPtrInst>(V)) {
158
+ auto *NewGEP = cast<GetElementPtrInst>(GEP->clone ());
159
+ ToInsert.push_back (std::make_pair (NewGEP, GEP));
160
+ Type *NewRetTy = cast<PointerType>(GEP->getType ())->getElementType ()->getPointerTo (0 );
161
+ NewGEP->mutateType (NewRetTy);
162
+ LiftingMap[GEP] = NewGEP;
163
+ ToRevisit.push_back (NewGEP);
164
+ } else if (auto *Phi = dyn_cast<PHINode>(V)) {
165
+ auto *NewPhi = cast<PHINode>(Phi->clone ());
166
+ ToInsert.push_back (std::make_pair (NewPhi, Phi));
167
+ Type *NewRetTy = cast<PointerType>(Phi->getType ())->getElementType ()->getPointerTo (0 );
168
+ NewPhi->mutateType (NewRetTy);
169
+ LiftingMap[Phi] = NewPhi;
170
+ ToRevisit.push_back (NewPhi);
171
+ }
172
+ }
173
+
174
+ auto CollapseCastsAndLift = [&](Value *CurrentV, Instruction *InsertPt) {
175
+ Type *TargetType = cast<PointerType>(CurrentV->getType ())->getElementType ()->getPointerTo (0 );
176
+ while (!LiftingMap.count (CurrentV)) {
177
+ if (isa<BitCastInst>(CurrentV))
178
+ CurrentV = cast<BitCastInst>(CurrentV)->getOperand (0 );
179
+ else if (isa<AddrSpaceCastInst>(CurrentV))
180
+ CurrentV = cast<AddrSpaceCastInst>(CurrentV)->getOperand (0 );
181
+ else
182
+ break ;
117
183
}
118
- GetElementPtrInst *NewGEP = cast<GetElementPtrInst>(GEP->clone ());
119
- ToInsert.push_back (std::make_pair (NewGEP, GEP));
120
- Type *GEPTy = GEP->getSourceElementType ();
121
- Type *NewRetTy = cast<PointerType>(GEP->getType ())->getElementType ()->getPointerTo (getValueAddrSpace (CurrentV));
122
- NewGEP->mutateType (NewRetTy);
123
- if (cast<PointerType>(CurrentV->getType ())->getElementType () != GEPTy) {
124
- auto *BCI = new BitCastInst (CurrentV, GEPTy->getPointerTo ());
125
- ToInsert.push_back (std::make_pair (BCI, NewGEP));
184
+ if (LiftingMap.count (CurrentV))
185
+ CurrentV = LiftingMap[CurrentV];
186
+ if (CurrentV->getType () != TargetType) {
187
+ auto *BCI = new BitCastInst (CurrentV, TargetType);
188
+ ToInsert.push_back (std::make_pair (BCI, InsertPt));
126
189
CurrentV = BCI;
127
190
}
128
- NewGEP->setOperand (GetElementPtrInst::getPointerOperandIndex (), CurrentV);
129
- LiftingMap[GEP] = NewGEP;
130
- CurrentV = NewGEP;
131
- }
132
- if (LocTy && cast<PointerType>(CurrentV->getType ())->getElementType () != LocTy) {
133
- auto *BCI = new BitCastInst (CurrentV, LocTy->getPointerTo ());
134
- ToInsert.push_back (std::make_pair (BCI, InsertPt));
135
- CurrentV = BCI;
191
+ return CurrentV;
192
+ };
193
+
194
+ // Now go through and update the operands
195
+ for (Value *V : ToRevisit) {
196
+ if (GetElementPtrInst *NewGEP = dyn_cast<GetElementPtrInst>(V)) {
197
+ NewGEP->setOperand (GetElementPtrInst::getPointerOperandIndex (),
198
+ CollapseCastsAndLift (NewGEP->getOperand (GetElementPtrInst::getPointerOperandIndex ()),
199
+ NewGEP));
200
+ } else if (PHINode *NewPhi = dyn_cast<PHINode>(V)) {
201
+ for (size_t i = 0 ; i < NewPhi->getNumIncomingValues (); ++i) {
202
+ NewPhi->setIncomingValue (i, CollapseCastsAndLift (NewPhi->getIncomingValue (i),
203
+ NewPhi->getIncomingBlock (i)->getTerminator ()));
204
+ }
205
+ } else {
206
+ assert (false && " Shouldn't have reached here" );
207
+ }
136
208
}
137
- return CurrentV;
209
+
210
+ return CollapseCastsAndLift (V, cast<Instruction>(V));
138
211
}
139
212
140
213
void PropagateJuliaAddrspaces::visitLoadInst (LoadInst &LI) {
0 commit comments