Skip to content

Commit d992606

Browse files
committed
[InstCombine] Fold phi ( inttoptr/ptrtoint x ) to phi (x)
The inttoptr/ptrtoint roundtrip optimization is not always correct. We are working towards removing this optimization and adding support to specific cases where this optimization works. In this patch, we focus on phi-node operands with inttoptr casts. We know that ptrtoint( inttoptr( ptrtoint x) ) is same as ptrtoint (x). So, we want to remove this roundtrip cast which goes through phi-node. Reviewed By: aqjune Differential Revision: https://reviews.llvm.org/D106289
1 parent 6180ce2 commit d992606

File tree

4 files changed

+205
-1
lines changed

4 files changed

+205
-1
lines changed

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/IR/IRBuilder.h"
2323
#include "llvm/IR/InstVisitor.h"
2424
#include "llvm/IR/PatternMatch.h"
25+
#include "llvm/IR/Value.h"
2526
#include "llvm/Support/Debug.h"
2627
#include "llvm/Support/KnownBits.h"
2728
#include "llvm/Transforms/InstCombine/InstCombineWorklist.h"
@@ -623,6 +624,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
623624
Instruction *foldPHIArgGEPIntoPHI(PHINode &PN);
624625
Instruction *foldPHIArgLoadIntoPHI(PHINode &PN);
625626
Instruction *foldPHIArgZextsIntoPHI(PHINode &PN);
627+
Instruction *foldPHIArgIntToPtrToPHI(PHINode &PN);
626628

627629
/// If an integer typed PHI has only one use which is an IntToPtr operation,
628630
/// replace the PHI with an existing pointer typed PHI if it exists. Otherwise

llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,29 @@ Instruction *InstCombinerImpl::foldIntegerTypedPHI(PHINode &PN) {
299299
IntToPtr->getOperand(0)->getType());
300300
}
301301

302+
// Remove RoundTrip IntToPtr/PtrToInt Cast on PHI-Operand and
303+
// fold Phi-operand to bitcast.
304+
Instruction *InstCombinerImpl::foldPHIArgIntToPtrToPHI(PHINode &PN) {
305+
// convert ptr2int ( phi[ int2ptr(ptr2int(x))] ) --> ptr2int ( phi [ x ] )
306+
// Make sure all uses of phi are ptr2int.
307+
if (!all_of(PN.users(), [](User *U) { return isa<PtrToIntInst>(U); }))
308+
return nullptr;
309+
310+
// Iterating over all operands to check presence of target pointers for
311+
// optimization.
312+
bool OperandWithRoundTripCast = false;
313+
for (unsigned OpNum = 0; OpNum != PN.getNumIncomingValues(); ++OpNum) {
314+
if (auto *NewOp =
315+
simplifyIntToPtrRoundTripCast(PN.getIncomingValue(OpNum))) {
316+
PN.setIncomingValue(OpNum, NewOp);
317+
OperandWithRoundTripCast = true;
318+
}
319+
}
320+
if (!OperandWithRoundTripCast)
321+
return nullptr;
322+
return &PN;
323+
}
324+
302325
/// If we have something like phi [insertvalue(a,b,0), insertvalue(c,d,0)],
303326
/// turn this into a phi[a,c] and phi[b,d] and a single insertvalue.
304327
Instruction *
@@ -1306,6 +1329,9 @@ Instruction *InstCombinerImpl::visitPHINode(PHINode &PN) {
13061329
if (Instruction *Result = foldPHIArgZextsIntoPHI(PN))
13071330
return Result;
13081331

1332+
if (Instruction *Result = foldPHIArgIntToPtrToPHI(PN))
1333+
return Result;
1334+
13091335
// If all PHI operands are the same operation, pull them through the PHI,
13101336
// reducing code size.
13111337
if (isa<Instruction>(PN.getIncomingValue(0)) &&

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,8 @@ Value *InstCombinerImpl::simplifyIntToPtrRoundTripCast(Value *Val) {
359359
PtrToInt->getSrcTy()->getPointerAddressSpace() &&
360360
DL.getPointerTypeSizeInBits(PtrToInt->getSrcTy()) ==
361361
DL.getTypeSizeInBits(PtrToInt->getDestTy())) {
362-
return Builder.CreateBitCast(PtrToInt->getOperand(0), CastTy);
362+
return CastInst::CreateBitOrPointerCast(PtrToInt->getOperand(0), CastTy,
363+
"", PtrToInt);
363364
}
364365
}
365366
return nullptr;
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -instcombine -S -disable-i2p-p2i-opt < %s | FileCheck %s
3+
4+
target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64"
5+
target triple = "x86_64-unknown-linux-gnu"
6+
7+
; convert ptrtoint [ phi[ inttoptr (ptrtoint (x) ) ] ---> ptrtoint (phi[x])
8+
9+
define i64 @func(i32** %X, i32** %Y, i1 %cond) {
10+
; CHECK-LABEL: @func(
11+
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
12+
; CHECK: bb1:
13+
; CHECK-NEXT: br label [[EXIT:%.*]]
14+
; CHECK: bb2:
15+
; CHECK-NEXT: br label [[EXIT]]
16+
; CHECK: exit:
17+
; CHECK-NEXT: [[PHI_IN_IN:%.*]] = phi i32** [ [[X:%.*]], [[BB1]] ], [ [[Y:%.*]], [[BB2]] ]
18+
; CHECK-NEXT: [[PHI_IN:%.*]] = ptrtoint i32** [[PHI_IN_IN]] to i64
19+
; CHECK-NEXT: ret i64 [[PHI_IN]]
20+
;
21+
br i1 %cond, label %bb1, label %bb2
22+
23+
bb1:
24+
%X.i = ptrtoint i32** %X to i64
25+
%X.p = inttoptr i64 %X.i to i32*
26+
br label %exit
27+
28+
bb2:
29+
%Y.i = ptrtoint i32** %Y to i64
30+
%Y.p = inttoptr i64 %Y.i to i32*
31+
br label %exit
32+
33+
exit:
34+
%phi = phi i32* [%X.p, %bb1], [%Y.p, %bb2]
35+
%X.p.i = ptrtoint i32* %phi to i64
36+
ret i64 %X.p.i
37+
}
38+
39+
define i64 @func_single_operand(i32** %X, i32** %Y, i1 %cond) {
40+
; CHECK-LABEL: @func_single_operand(
41+
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[EXIT:%.*]]
42+
; CHECK: bb1:
43+
; CHECK-NEXT: br label [[EXIT]]
44+
; CHECK: exit:
45+
; CHECK-NEXT: [[PHI_IN:%.*]] = phi i32** [ [[X:%.*]], [[BB1]] ], [ [[Y:%.*]], [[TMP0:%.*]] ]
46+
; CHECK-NEXT: [[X_P_I:%.*]] = ptrtoint i32** [[PHI_IN]] to i64
47+
; CHECK-NEXT: ret i64 [[X_P_I]]
48+
;
49+
%Y.p = bitcast i32** %Y to i32*
50+
br i1 %cond, label %bb1, label %exit
51+
52+
bb1:
53+
%X.i = ptrtoint i32** %X to i64
54+
%X.p = inttoptr i64 %X.i to i32*
55+
br label %exit
56+
57+
exit:
58+
%phi = phi i32* [%X.p, %bb1], [%Y.p, %0]
59+
%X.p.i = ptrtoint i32* %phi to i64
60+
ret i64 %X.p.i
61+
}
62+
63+
define i64 @func_pointer_different_types(i16** %X, i32** %Y, i1 %cond) {
64+
; CHECK-LABEL: @func_pointer_different_types(
65+
; CHECK-NEXT: [[Y_P:%.*]] = bitcast i32** [[Y:%.*]] to i32*
66+
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[EXIT:%.*]]
67+
; CHECK: bb1:
68+
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i16** [[X:%.*]] to i32*
69+
; CHECK-NEXT: br label [[EXIT]]
70+
; CHECK: exit:
71+
; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ [[TMP1]], [[BB1]] ], [ [[Y_P]], [[TMP0:%.*]] ]
72+
; CHECK-NEXT: [[X_P_I:%.*]] = ptrtoint i32* [[PHI]] to i64
73+
; CHECK-NEXT: ret i64 [[X_P_I]]
74+
;
75+
%Y.p = bitcast i32** %Y to i32*
76+
br i1 %cond, label %bb1, label %exit
77+
78+
bb1:
79+
%X.i = ptrtoint i16** %X to i64
80+
%X.p = inttoptr i64 %X.i to i32*
81+
br label %exit
82+
83+
exit:
84+
%phi = phi i32* [%X.p, %bb1], [%Y.p, %0]
85+
%X.p.i = ptrtoint i32* %phi to i64
86+
ret i64 %X.p.i
87+
}
88+
89+
; Negative test - Wrong Integer type
90+
91+
define i64 @func_integer_type_too_small(i32** %X, i32** %Y, i1 %cond) {
92+
; CHECK-LABEL: @func_integer_type_too_small(
93+
; CHECK-NEXT: [[Y_P:%.*]] = bitcast i32** [[Y:%.*]] to i32*
94+
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[EXIT:%.*]]
95+
; CHECK: bb1:
96+
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint i32** [[X:%.*]] to i64
97+
; CHECK-NEXT: [[TMP2:%.*]] = and i64 [[TMP1]], 4294967295
98+
; CHECK-NEXT: [[X_P:%.*]] = inttoptr i64 [[TMP2]] to i32*
99+
; CHECK-NEXT: br label [[EXIT]]
100+
; CHECK: exit:
101+
; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ [[X_P]], [[BB1]] ], [ [[Y_P]], [[TMP0:%.*]] ]
102+
; CHECK-NEXT: [[X_P_I:%.*]] = ptrtoint i32* [[PHI]] to i64
103+
; CHECK-NEXT: ret i64 [[X_P_I]]
104+
;
105+
%Y.p = bitcast i32** %Y to i32*
106+
br i1 %cond, label %bb1, label %exit
107+
108+
bb1:
109+
%X.i = ptrtoint i32** %X to i32
110+
%X.p = inttoptr i32 %X.i to i32*
111+
br label %exit
112+
113+
exit:
114+
%phi = phi i32* [%X.p, %bb1], [%Y.p, %0]
115+
%X.p.i = ptrtoint i32* %phi to i64
116+
ret i64 %X.p.i
117+
}
118+
119+
; Negative test - phi not used in ptrtoint
120+
121+
define i32* @func_phi_not_use_in_ptr2int(i32** %X, i32** %Y, i1 %cond) {
122+
; CHECK-LABEL: @func_phi_not_use_in_ptr2int(
123+
; CHECK-NEXT: [[Y_P:%.*]] = bitcast i32** [[Y:%.*]] to i32*
124+
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[EXIT:%.*]]
125+
; CHECK: bb1:
126+
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint i32** [[X:%.*]] to i64
127+
; CHECK-NEXT: [[TMP2:%.*]] = and i64 [[TMP1]], 4294967295
128+
; CHECK-NEXT: [[X_P:%.*]] = inttoptr i64 [[TMP2]] to i32*
129+
; CHECK-NEXT: br label [[EXIT]]
130+
; CHECK: exit:
131+
; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ [[X_P]], [[BB1]] ], [ [[Y_P]], [[TMP0:%.*]] ]
132+
; CHECK-NEXT: ret i32* [[PHI]]
133+
;
134+
%Y.p = bitcast i32** %Y to i32*
135+
br i1 %cond, label %bb1, label %exit
136+
137+
bb1:
138+
%X.i = ptrtoint i32** %X to i32
139+
%X.p = inttoptr i32 %X.i to i32*
140+
br label %exit
141+
142+
exit:
143+
%phi = phi i32* [%X.p, %bb1], [%Y.p, %0]
144+
ret i32* %phi
145+
}
146+
147+
; Negative test - Pointers in different address spaces
148+
149+
define i64 @func_ptr_different_addrspace(i16 addrspace(2)* %X, i32** %Y, i1 %cond) {
150+
; CHECK-LABEL: @func_ptr_different_addrspace(
151+
; CHECK-NEXT: [[Y_P:%.*]] = bitcast i32** [[Y:%.*]] to i32*
152+
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[EXIT:%.*]]
153+
; CHECK: bb1:
154+
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint i16 addrspace(2)* [[X:%.*]] to i32
155+
; CHECK-NEXT: [[X_I:%.*]] = zext i32 [[TMP1]] to i64
156+
; CHECK-NEXT: [[X_P:%.*]] = inttoptr i64 [[X_I]] to i32*
157+
; CHECK-NEXT: br label [[EXIT]]
158+
; CHECK: exit:
159+
; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ [[X_P]], [[BB1]] ], [ [[Y_P]], [[TMP0:%.*]] ]
160+
; CHECK-NEXT: [[X_P_I:%.*]] = ptrtoint i32* [[PHI]] to i64
161+
; CHECK-NEXT: ret i64 [[X_P_I]]
162+
;
163+
%Y.p = bitcast i32** %Y to i32*
164+
br i1 %cond, label %bb1, label %exit
165+
166+
bb1:
167+
%X.i = ptrtoint i16 addrspace(2)* %X to i64
168+
%X.p = inttoptr i64 %X.i to i32*
169+
br label %exit
170+
171+
exit:
172+
%phi = phi i32* [%X.p, %bb1], [%Y.p, %0]
173+
%X.p.i = ptrtoint i32* %phi to i64
174+
ret i64 %X.p.i
175+
}

0 commit comments

Comments
 (0)