@@ -40,6 +40,238 @@ void InstCombiner::PHIArgMergedDebugLoc(Instruction *Inst, PHINode &PN) {
4040 }
4141}
4242
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+
43275// / If we have something like phi [add (a,b), add(a,c)] and if a/b/c and the
44276// / adds all have a single use, turn this into a phi and a single binop.
45277Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI (PHINode &PN) {
@@ -903,6 +1135,9 @@ Instruction *InstCombiner::visitPHINode(PHINode &PN) {
9031135 // this PHI only has a single use (a PHI), and if that PHI only has one use (a
9041136 // PHI)... break the cycle.
9051137 if (PN.hasOneUse ()) {
1138+ if (Instruction *Result = FoldIntegerTypedPHI (PN))
1139+ return Result;
1140+
9061141 Instruction *PHIUser = cast<Instruction>(PN.user_back ());
9071142 if (PHINode *PU = dyn_cast<PHINode>(PHIUser)) {
9081143 SmallPtrSet<PHINode*, 16 > PotentiallyDeadPHIs;
0 commit comments