Skip to content

Commit a80305d

Browse files
fhahngithub-actions[bot]
authored andcommitted
Automerge: [InstComb] Allow more user for (add (ptrtoint %B), %O) to GEP transform. (#153566)
Generalize the logic from llvm/llvm-project#153421 to support additional cases where the pointer is only used as integer. Alive2 Proof: https://alive2.llvm.org/ce/z/po58pP This enables vectorizing std::find for some cases, if additional assumptions are provided: https://godbolt.org/z/94oq3576E Depends on llvm/llvm-project#15342. PR: llvm/llvm-project#153566
2 parents 0ee9165 + 8bc038d commit a80305d

File tree

3 files changed

+117
-34
lines changed

3 files changed

+117
-34
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,15 +2073,23 @@ Instruction *InstCombinerImpl::visitIntToPtr(IntToPtrInst &CI) {
20732073
}
20742074

20752075
// Replace (inttoptr (add (ptrtoint %Base), %Offset)) with
2076-
// (getelementptr i8, %Base, %Offset) if all users are ICmps.
2076+
// (getelementptr i8, %Base, %Offset) if the pointer is only used as integer
2077+
// value.
20772078
Value *Base;
20782079
Value *Offset;
2080+
auto UsesPointerAsInt = [](User *U) {
2081+
if (isa<ICmpInst, PtrToIntInst>(U))
2082+
return true;
2083+
if (auto *P = dyn_cast<PHINode>(U))
2084+
return P->hasOneUse() && isa<ICmpInst, PtrToIntInst>(*P->user_begin());
2085+
return false;
2086+
};
20792087
if (match(CI.getOperand(0),
20802088
m_OneUse(m_c_Add(m_PtrToIntSameSize(DL, m_Value(Base)),
20812089
m_Value(Offset)))) &&
20822090
CI.getType()->getPointerAddressSpace() ==
20832091
Base->getType()->getPointerAddressSpace() &&
2084-
all_of(CI.users(), IsaPred<ICmpInst>)) {
2092+
all_of(CI.users(), UsesPointerAsInt)) {
20852093
return GetElementPtrInst::Create(Builder.getInt8Ty(), Base, Offset);
20862094
}
20872095

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -passes=instcombine -S %s | FileCheck %s
3+
4+
define i64 @inttoptr_used_by_phi_with_ptrtoint(i1 %c, ptr %src, ptr %p2) {
5+
; CHECK-LABEL: define i64 @inttoptr_used_by_phi_with_ptrtoint(
6+
; CHECK-SAME: i1 [[C:%.*]], ptr [[SRC:%.*]], ptr [[P2:%.*]]) {
7+
; CHECK-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[ELSE:.*]]
8+
; CHECK: [[THEN]]:
9+
; CHECK-NEXT: [[P:%.*]] = getelementptr i8, ptr [[SRC]], i64 10
10+
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64
11+
; CHECK-NEXT: br label %[[EXIT:.*]]
12+
; CHECK: [[ELSE]]:
13+
; CHECK-NEXT: br label %[[EXIT]]
14+
; CHECK: [[EXIT]]:
15+
; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[TMP1]], %[[THEN]] ], [ 0, %[[ELSE]] ]
16+
; CHECK-NEXT: ret i64 [[PHI]]
17+
;
18+
%i = ptrtoint ptr %src to i64
19+
%a = add i64 %i, 10
20+
%p = inttoptr i64 %a to ptr
21+
br i1 %c, label %then, label %else
22+
23+
then:
24+
br label %exit
25+
26+
else:
27+
br label %exit
28+
29+
exit:
30+
%phi = phi ptr [ %p, %then ], [ null, %else ]
31+
%i.2 = ptrtoint ptr %phi to i64
32+
ret i64 %i.2
33+
}
34+
35+
declare void @foo(ptr)
36+
37+
define i64 @inttoptr_used_by_phi_with_other_users(i1 %c, ptr %src, ptr %p2) {
38+
; CHECK-LABEL: define i64 @inttoptr_used_by_phi_with_other_users(
39+
; CHECK-SAME: i1 [[C:%.*]], ptr [[SRC:%.*]], ptr [[P2:%.*]]) {
40+
; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[SRC]] to i64
41+
; CHECK-NEXT: [[A:%.*]] = add i64 [[I]], 10
42+
; CHECK-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[ELSE:.*]]
43+
; CHECK: [[THEN]]:
44+
; CHECK-NEXT: br label %[[EXIT:.*]]
45+
; CHECK: [[ELSE]]:
46+
; CHECK-NEXT: br label %[[EXIT]]
47+
; CHECK: [[EXIT]]:
48+
; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[A]], %[[THEN]] ], [ 0, %[[ELSE]] ]
49+
; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[A]] to ptr
50+
; CHECK-NEXT: call void @foo(ptr [[P]])
51+
; CHECK-NEXT: ret i64 [[PHI]]
52+
;
53+
%i = ptrtoint ptr %src to i64
54+
%a = add i64 %i, 10
55+
%p = inttoptr i64 %a to ptr
56+
br i1 %c, label %then, label %else
57+
58+
then:
59+
br label %exit
60+
61+
else:
62+
br label %exit
63+
64+
exit:
65+
%phi = phi ptr [ %p, %then ], [ null, %else ]
66+
call void @foo(ptr %p)
67+
%i.2 = ptrtoint ptr %phi to i64
68+
ret i64 %i.2
69+
}

llvm/test/Transforms/PhaseOrdering/AArch64/std-find.ll

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,34 @@ define i64 @std_find_i16_constant_offset_with_assumptions(ptr %first.coerce, i16
99
; CHECK-NEXT: [[ENTRY:.*]]:
1010
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[FIRST_COERCE]], i64 2) ]
1111
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[FIRST_COERCE]], i64 256) ]
12-
; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[FIRST_COERCE]] to i64
13-
; CHECK-NEXT: [[COERCE_VAL_PI_I:%.*]] = add i64 [[TMP0]], 256
14-
; CHECK-NEXT: [[COERCE_VAL_IP:%.*]] = inttoptr i64 [[COERCE_VAL_PI_I]] to ptr
15-
; CHECK-NEXT: [[CMP_NOT6_I_I:%.*]] = icmp eq ptr [[FIRST_COERCE]], [[COERCE_VAL_IP]]
16-
; CHECK-NEXT: br i1 [[CMP_NOT6_I_I]], label %[[RETURN:.*]], label %[[LOOP_HEADER:.*]]
17-
; CHECK: [[LOOP_HEADER]]:
18-
; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[FIRST_COERCE]], %[[ENTRY]] ]
19-
; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[PTR_IV]], align 2
20-
; CHECK-NEXT: [[CMP2_I_I:%.*]] = icmp eq i16 [[TMP1]], [[S]]
21-
; CHECK-NEXT: br i1 [[CMP2_I_I]], label %[[RETURN_LOOPEXIT:.*]], label %[[LOOP_LATCH]]
22-
; CHECK: [[LOOP_LATCH]]:
23-
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 2
24-
; CHECK-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[COERCE_VAL_IP]]
25-
; CHECK-NEXT: br i1 [[CMP_NOT_I_I]], label %[[RETURN_LOOPEXIT]], label %[[LOOP_HEADER]]
26-
; CHECK: [[RETURN_LOOPEXIT]]:
27-
; CHECK-NEXT: [[MERGE_PH:%.*]] = phi ptr [ [[COERCE_VAL_IP]], %[[LOOP_LATCH]] ], [ [[PTR_IV]], %[[LOOP_HEADER]] ]
28-
; CHECK-NEXT: [[DOTPRE:%.*]] = ptrtoint ptr [[MERGE_PH]] to i64
12+
; CHECK-NEXT: [[COERCE_VAL_IP:%.*]] = getelementptr i8, ptr [[FIRST_COERCE]], i64 256
13+
; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <8 x i16> poison, i16 [[S]], i64 0
14+
; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <8 x i16> [[BROADCAST_SPLATINSERT]], <8 x i16> poison, <8 x i32> zeroinitializer
15+
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
16+
; CHECK: [[VECTOR_BODY]]:
17+
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
18+
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 1
19+
; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[FIRST_COERCE]], i64 [[OFFSET_IDX]]
20+
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, ptr [[NEXT_GEP]], align 2
21+
; CHECK-NEXT: [[TMP0:%.*]] = icmp eq <8 x i16> [[WIDE_LOAD]], [[BROADCAST_SPLAT]]
22+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8
23+
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i1> [[TMP0]] to i8
24+
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 0
25+
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[INDEX_NEXT]], 128
26+
; CHECK-NEXT: [[TMP4:%.*]] = or i1 [[TMP2]], [[TMP3]]
27+
; CHECK-NEXT: br i1 [[TMP4]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
28+
; CHECK: [[MIDDLE_SPLIT]]:
29+
; CHECK-NEXT: br i1 [[TMP2]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[RETURN:.*]]
30+
; CHECK: [[VECTOR_EARLY_EXIT]]:
31+
; CHECK-NEXT: [[TMP5:%.*]] = tail call i64 @llvm.experimental.cttz.elts.i64.v8i1(<8 x i1> [[TMP0]], i1 true)
32+
; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[INDEX]], [[TMP5]]
33+
; CHECK-NEXT: [[TMP7:%.*]] = shl i64 [[TMP6]], 1
34+
; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[FIRST_COERCE]], i64 [[TMP7]]
2935
; CHECK-NEXT: br label %[[RETURN]]
3036
; CHECK: [[RETURN]]:
31-
; CHECK-NEXT: [[RES_PRE_PHI:%.*]] = phi i64 [ [[DOTPRE]], %[[RETURN_LOOPEXIT]] ], [ [[TMP0]], %[[ENTRY]] ]
32-
; CHECK-NEXT: ret i64 [[RES_PRE_PHI]]
37+
; CHECK-NEXT: [[__FIRST_ADDR_0_LCSSA_I_I_PH:%.*]] = phi ptr [ [[TMP8]], %[[VECTOR_EARLY_EXIT]] ], [ [[COERCE_VAL_IP]], %[[MIDDLE_SPLIT]] ]
38+
; CHECK-NEXT: [[DOTPRE:%.*]] = ptrtoint ptr [[__FIRST_ADDR_0_LCSSA_I_I_PH]] to i64
39+
; CHECK-NEXT: ret i64 [[DOTPRE]]
3340
;
3441
entry:
3542
%first = alloca { ptr }, align 8
@@ -71,27 +78,21 @@ define i64 @std_find_i16_constant_offset_no_assumptions(ptr %first.coerce, i16 n
7178
; CHECK-LABEL: define i64 @std_find_i16_constant_offset_no_assumptions(
7279
; CHECK-SAME: ptr [[FIRST_COERCE:%.*]], i16 noundef signext [[S:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
7380
; CHECK-NEXT: [[ENTRY:.*]]:
74-
; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[FIRST_COERCE]] to i64
75-
; CHECK-NEXT: [[COERCE_VAL_PI_I:%.*]] = add i64 [[TMP0]], 256
76-
; CHECK-NEXT: [[COERCE_VAL_IP:%.*]] = inttoptr i64 [[COERCE_VAL_PI_I]] to ptr
77-
; CHECK-NEXT: [[CMP_NOT6_I_I:%.*]] = icmp eq ptr [[FIRST_COERCE]], [[COERCE_VAL_IP]]
78-
; CHECK-NEXT: br i1 [[CMP_NOT6_I_I]], label %[[RETURN:.*]], label %[[LOOP_HEADER:.*]]
81+
; CHECK-NEXT: [[COERCE_VAL_IP:%.*]] = getelementptr i8, ptr [[FIRST_COERCE]], i64 256
82+
; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]
7983
; CHECK: [[LOOP_HEADER]]:
80-
; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[FIRST_COERCE]], %[[ENTRY]] ]
84+
; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[FIRST_COERCE]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
8185
; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[PTR_IV]], align 2
8286
; CHECK-NEXT: [[CMP2_I_I:%.*]] = icmp eq i16 [[TMP1]], [[S]]
83-
; CHECK-NEXT: br i1 [[CMP2_I_I]], label %[[RETURN_LOOPEXIT:.*]], label %[[LOOP_LATCH]]
87+
; CHECK-NEXT: br i1 [[CMP2_I_I]], label %[[RETURN:.*]], label %[[LOOP_LATCH]]
8488
; CHECK: [[LOOP_LATCH]]:
8589
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 2
8690
; CHECK-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[COERCE_VAL_IP]]
87-
; CHECK-NEXT: br i1 [[CMP_NOT_I_I]], label %[[RETURN_LOOPEXIT]], label %[[LOOP_HEADER]]
88-
; CHECK: [[RETURN_LOOPEXIT]]:
91+
; CHECK-NEXT: br i1 [[CMP_NOT_I_I]], label %[[RETURN]], label %[[LOOP_HEADER]]
92+
; CHECK: [[RETURN]]:
8993
; CHECK-NEXT: [[MERGE_PH:%.*]] = phi ptr [ [[COERCE_VAL_IP]], %[[LOOP_LATCH]] ], [ [[PTR_IV]], %[[LOOP_HEADER]] ]
9094
; CHECK-NEXT: [[DOTPRE:%.*]] = ptrtoint ptr [[MERGE_PH]] to i64
91-
; CHECK-NEXT: br label %[[RETURN]]
92-
; CHECK: [[RETURN]]:
93-
; CHECK-NEXT: [[RES_PRE_PHI:%.*]] = phi i64 [ [[DOTPRE]], %[[RETURN_LOOPEXIT]] ], [ [[TMP0]], %[[ENTRY]] ]
94-
; CHECK-NEXT: ret i64 [[RES_PRE_PHI]]
95+
; CHECK-NEXT: ret i64 [[DOTPRE]]
9596
;
9697
entry:
9798
%first = alloca { ptr }, align 8
@@ -128,3 +129,8 @@ return:
128129
}
129130

130131
declare void @llvm.assume(i1 noundef)
132+
;.
133+
; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]}
134+
; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1}
135+
; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"}
136+
;.

0 commit comments

Comments
 (0)