@@ -40,6 +40,238 @@ void InstCombiner::PHIArgMergedDebugLoc(Instruction *Inst, PHINode &PN) {
40
40
}
41
41
}
42
42
43
+ // Replace Integer typed PHI PN if the PHI's value is used as a pointer value.
44
+ // If there is an existing pointer typed PHI that produces the same value as PN,
45
+ // replace PN and the IntToPtr operation with it. Otherwise, synthesize a new
46
+ // PHI node:
47
+ //
48
+ // Case-1:
49
+ // bb1:
50
+ // int_init = PtrToInt(ptr_init)
51
+ // br label %bb2
52
+ // bb2:
53
+ // int_val = PHI([int_init, %bb1], [int_val_inc, %bb2]
54
+ // ptr_val = PHI([ptr_init, %bb1], [ptr_val_inc, %bb2]
55
+ // ptr_val2 = IntToPtr(int_val)
56
+ // ...
57
+ // use(ptr_val2)
58
+ // ptr_val_inc = ...
59
+ // inc_val_inc = PtrToInt(ptr_val_inc)
60
+ //
61
+ // ==>
62
+ // bb1:
63
+ // br label %bb2
64
+ // bb2:
65
+ // ptr_val = PHI([ptr_init, %bb1], [ptr_val_inc, %bb2]
66
+ // ...
67
+ // use(ptr_val)
68
+ // ptr_val_inc = ...
69
+ //
70
+ // Case-2:
71
+ // bb1:
72
+ // int_ptr = BitCast(ptr_ptr)
73
+ // int_init = Load(int_ptr)
74
+ // br label %bb2
75
+ // bb2:
76
+ // int_val = PHI([int_init, %bb1], [int_val_inc, %bb2]
77
+ // ptr_val2 = IntToPtr(int_val)
78
+ // ...
79
+ // use(ptr_val2)
80
+ // ptr_val_inc = ...
81
+ // inc_val_inc = PtrToInt(ptr_val_inc)
82
+ // ==>
83
+ // bb1:
84
+ // ptr_init = Load(ptr_ptr)
85
+ // br label %bb2
86
+ // bb2:
87
+ // ptr_val = PHI([ptr_init, %bb1], [ptr_val_inc, %bb2]
88
+ // ...
89
+ // use(ptr_val)
90
+ // ptr_val_inc = ...
91
+ // ...
92
+ //
93
+ Instruction *InstCombiner::FoldIntegerTypedPHI (PHINode &PN) {
94
+ if (!PN.getType ()->isIntegerTy ())
95
+ return nullptr ;
96
+ if (!PN.hasOneUse ())
97
+ return nullptr ;
98
+
99
+ auto *IntToPtr = dyn_cast<IntToPtrInst>(PN.user_back ());
100
+ if (!IntToPtr)
101
+ return nullptr ;
102
+
103
+ // Check if the pointer is actually used as pointer:
104
+ auto HasPointerUse = [](Instruction *IIP) {
105
+ for (User *U : IIP->users ()) {
106
+ Value *Ptr = nullptr ;
107
+ if (LoadInst *LoadI = dyn_cast<LoadInst>(U)) {
108
+ Ptr = LoadI->getPointerOperand ();
109
+ } else if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
110
+ Ptr = SI->getPointerOperand ();
111
+ } else if (GetElementPtrInst *GI = dyn_cast<GetElementPtrInst>(U)) {
112
+ Ptr = GI->getPointerOperand ();
113
+ }
114
+
115
+ if (Ptr && Ptr == IIP)
116
+ return true ;
117
+ }
118
+ return false ;
119
+ };
120
+
121
+ if (!HasPointerUse (IntToPtr))
122
+ return nullptr ;
123
+
124
+ if (DL.getPointerSizeInBits (IntToPtr->getAddressSpace ()) !=
125
+ DL.getTypeSizeInBits (IntToPtr->getOperand (0 )->getType ()))
126
+ return nullptr ;
127
+
128
+ SmallVector<Value *, 4 > AvailablePtrVals;
129
+ for (unsigned i = 0 ; i != PN.getNumIncomingValues (); ++i) {
130
+ Value *Arg = PN.getIncomingValue (i);
131
+
132
+ // First look backward:
133
+ if (auto *PI = dyn_cast<PtrToIntInst>(Arg)) {
134
+ AvailablePtrVals.emplace_back (PI->getOperand (0 ));
135
+ continue ;
136
+ }
137
+
138
+ // Next look forward:
139
+ Value *ArgIntToPtr = nullptr ;
140
+ for (User *U : Arg->users ()) {
141
+ if (isa<IntToPtrInst>(U) && U->getType () == IntToPtr->getType () &&
142
+ (DT.dominates (cast<Instruction>(U), PN.getIncomingBlock (i)) ||
143
+ cast<Instruction>(U)->getParent () == PN.getIncomingBlock (i))) {
144
+ ArgIntToPtr = U;
145
+ break ;
146
+ }
147
+ }
148
+
149
+ if (ArgIntToPtr) {
150
+ AvailablePtrVals.emplace_back (ArgIntToPtr);
151
+ continue ;
152
+ }
153
+
154
+ // If Arg is defined by a PHI, allow it. This will also create
155
+ // more opportunities iteratively.
156
+ if (isa<PHINode>(Arg)) {
157
+ AvailablePtrVals.emplace_back (Arg);
158
+ continue ;
159
+ }
160
+
161
+ // For a single use integer load:
162
+ auto *LoadI = dyn_cast<LoadInst>(Arg);
163
+ if (!LoadI)
164
+ return nullptr ;
165
+
166
+ if (!LoadI->hasOneUse ())
167
+ return nullptr ;
168
+
169
+ // Push the integer typed Load instruction into the available
170
+ // value set, and fix it up later when the pointer typed PHI
171
+ // is synthesized.
172
+ AvailablePtrVals.emplace_back (LoadI);
173
+ }
174
+
175
+ // Now search for a matching PHI
176
+ auto *BB = PN.getParent ();
177
+ assert (AvailablePtrVals.size () == PN.getNumIncomingValues () &&
178
+ " Not enough available ptr typed incoming values" );
179
+ PHINode *MatchingPtrPHI = nullptr ;
180
+ for (auto II = BB->begin (), EI = BasicBlock::iterator (BB->getFirstNonPHI ());
181
+ II != EI; II++) {
182
+ PHINode *PtrPHI = dyn_cast<PHINode>(II);
183
+ if (!PtrPHI || PtrPHI == &PN || PtrPHI->getType () != IntToPtr->getType ())
184
+ continue ;
185
+ MatchingPtrPHI = PtrPHI;
186
+ for (unsigned i = 0 ; i != PtrPHI->getNumIncomingValues (); ++i) {
187
+ if (AvailablePtrVals[i] !=
188
+ PtrPHI->getIncomingValueForBlock (PN.getIncomingBlock (i))) {
189
+ MatchingPtrPHI = nullptr ;
190
+ break ;
191
+ }
192
+ }
193
+
194
+ if (MatchingPtrPHI)
195
+ break ;
196
+ }
197
+
198
+ if (MatchingPtrPHI) {
199
+ assert (MatchingPtrPHI->getType () == IntToPtr->getType () &&
200
+ " Phi's Type does not match with IntToPtr" );
201
+ // The PtrToCast + IntToPtr will be simplified later
202
+ return CastInst::CreateBitOrPointerCast (MatchingPtrPHI,
203
+ IntToPtr->getOperand (0 )->getType ());
204
+ }
205
+
206
+ // If it requires a conversion for every PHI operand, do not do it.
207
+ if (std::all_of (AvailablePtrVals.begin (), AvailablePtrVals.end (),
208
+ [&](Value *V) {
209
+ return (V->getType () != IntToPtr->getType ()) ||
210
+ isa<IntToPtrInst>(V);
211
+ }))
212
+ return nullptr ;
213
+
214
+ // If any of the operand that requires casting is a terminator
215
+ // instruction, do not do it.
216
+ if (std::any_of (AvailablePtrVals.begin (), AvailablePtrVals.end (),
217
+ [&](Value *V) {
218
+ return (V->getType () != IntToPtr->getType ()) &&
219
+ isa<TerminatorInst>(V);
220
+ }))
221
+ return nullptr ;
222
+
223
+ PHINode *NewPtrPHI = PHINode::Create (
224
+ IntToPtr->getType (), PN.getNumIncomingValues (), PN.getName () + " .ptr" );
225
+
226
+ InsertNewInstBefore (NewPtrPHI, PN);
227
+ SmallDenseMap<Value *, Instruction *> Casts;
228
+ for (unsigned i = 0 ; i != PN.getNumIncomingValues (); ++i) {
229
+ auto *IncomingBB = PN.getIncomingBlock (i);
230
+ auto *IncomingVal = AvailablePtrVals[i];
231
+
232
+ if (IncomingVal->getType () == IntToPtr->getType ()) {
233
+ NewPtrPHI->addIncoming (IncomingVal, IncomingBB);
234
+ continue ;
235
+ }
236
+
237
+ #ifndef NDEBUG
238
+ LoadInst *LoadI = dyn_cast<LoadInst>(IncomingVal);
239
+ assert ((isa<PHINode>(IncomingVal) ||
240
+ IncomingVal->getType ()->isPointerTy () ||
241
+ (LoadI && LoadI->hasOneUse ())) &&
242
+ " Can not replace LoadInst with multiple uses" );
243
+ #endif
244
+ // Need to insert a BitCast.
245
+ // For an integer Load instruction with a single use, the load + IntToPtr
246
+ // cast will be simplified into a pointer load:
247
+ // %v = load i64, i64* %a.ip, align 8
248
+ // %v.cast = inttoptr i64 %v to float **
249
+ // ==>
250
+ // %v.ptrp = bitcast i64 * %a.ip to float **
251
+ // %v.cast = load float *, float ** %v.ptrp, align 8
252
+ Instruction *&CI = Casts[IncomingVal];
253
+ if (!CI) {
254
+ CI = CastInst::CreateBitOrPointerCast (IncomingVal, IntToPtr->getType (),
255
+ IncomingVal->getName () + " .ptr" );
256
+ if (auto *IncomingI = dyn_cast<Instruction>(IncomingVal)) {
257
+ BasicBlock::iterator InsertPos (IncomingI);
258
+ InsertPos++;
259
+ if (isa<PHINode>(IncomingI))
260
+ InsertPos = IncomingI->getParent ()->getFirstInsertionPt ();
261
+ InsertNewInstBefore (CI, *InsertPos);
262
+ } else {
263
+ auto *InsertBB = &IncomingBB->getParent ()->getEntryBlock ();
264
+ InsertNewInstBefore (CI, *InsertBB->getFirstInsertionPt ());
265
+ }
266
+ }
267
+ NewPtrPHI->addIncoming (CI, IncomingBB);
268
+ }
269
+
270
+ // The PtrToCast + IntToPtr will be simplified later
271
+ return CastInst::CreateBitOrPointerCast (NewPtrPHI,
272
+ IntToPtr->getOperand (0 )->getType ());
273
+ }
274
+
43
275
// / If we have something like phi [add (a,b), add(a,c)] and if a/b/c and the
44
276
// / adds all have a single use, turn this into a phi and a single binop.
45
277
Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI (PHINode &PN) {
@@ -903,6 +1135,9 @@ Instruction *InstCombiner::visitPHINode(PHINode &PN) {
903
1135
// this PHI only has a single use (a PHI), and if that PHI only has one use (a
904
1136
// PHI)... break the cycle.
905
1137
if (PN.hasOneUse ()) {
1138
+ if (Instruction *Result = FoldIntegerTypedPHI (PN))
1139
+ return Result;
1140
+
906
1141
Instruction *PHIUser = cast<Instruction>(PN.user_back ());
907
1142
if (PHINode *PU = dyn_cast<PHINode>(PHIUser)) {
908
1143
SmallPtrSet<PHINode*, 16 > PotentiallyDeadPHIs;
0 commit comments