Skip to content

Commit 43e4b11

Browse files
committed
[InstComb] Fold inttoptr (add (ptrtoint %B), %O) -> GEP for ICMP users.
Replace inttoptr (add (ptrtoint %B), %O) with (getelementptr i8, %B, %o) if all users are ICmp instruction, which in turn means only the address value is compared. We should be able to do this, if the src pointer, the integer type and the destination pointer types have the same bitwidth and address space. A common source of such (inttoptr (add (ptrtoint %B), %O)) is from various iterations in libc++. In practice this triggers in a number of files in Clang and various open source projects, including cppcheck, diamond, llama and more. Alive2 Proof with constant offset: https://alive2.llvm.org/ce/z/K_5N_B
1 parent 32a5adb commit 43e4b11

File tree

2 files changed

+23
-13
lines changed

2 files changed

+23
-13
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,6 +2072,22 @@ Instruction *InstCombinerImpl::visitIntToPtr(IntToPtrInst &CI) {
20722072
return new IntToPtrInst(P, CI.getType());
20732073
}
20742074

2075+
// Replace (inttoptr (add (ptrtoint %Base), %Offset)) with
2076+
// (getelementptr i8, %Base, %Offset) if all users are ICmps.
2077+
Value *Base;
2078+
Value *Offset;
2079+
if (match(CI.getOperand(0),
2080+
m_Add(m_PtrToInt(m_Value(Base)), m_Value(Offset))) &&
2081+
all_of(CI.users(), IsaPred<ICmpInst>)) {
2082+
Type *BasePtrTy = Base->getType();
2083+
if (CI.getType()->getPointerAddressSpace() ==
2084+
BasePtrTy->getPointerAddressSpace() &&
2085+
DL.getTypeSizeInBits(BasePtrTy) ==
2086+
DL.getTypeSizeInBits(CI.getSrcTy())) {
2087+
return GetElementPtrInst::Create(Builder.getInt8Ty(), Base, Offset);
2088+
}
2089+
}
2090+
20752091
if (Instruction *I = commonCastTransforms(CI))
20762092
return I;
20772093

llvm/test/Transforms/InstCombine/fold-bin-operand.ll

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,8 @@ define i32 @g(i32 %x) {
3232

3333
define i1 @inttoptr_add_ptrtoint_used_by_single_icmp(ptr %src, ptr %p2) {
3434
; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_single_icmp(
35-
; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[SRC:%.*]] to i64
36-
; CHECK-NEXT: [[A:%.*]] = add i64 [[I]], 10
37-
; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[A]] to ptr
38-
; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2:%.*]], [[P]]
35+
; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 10
36+
; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2]], [[P:%.*]]
3937
; CHECK-NEXT: ret i1 [[C]]
4038
;
4139
%i = ptrtoint ptr %src to i64
@@ -181,10 +179,8 @@ define i1 @inttoptr_add_ptrtoint_used_by_single_icmp_in_different_bb(i1 %bc, ptr
181179
; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_single_icmp_in_different_bb(
182180
; CHECK-NEXT: br i1 [[BC:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
183181
; CHECK: then:
184-
; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[SRC:%.*]] to i64
185-
; CHECK-NEXT: [[A:%.*]] = add i64 [[I]], 10
186-
; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[A]] to ptr
187-
; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2:%.*]], [[P]]
182+
; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 10
183+
; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2]], [[P:%.*]]
188184
; CHECK-NEXT: ret i1 [[C]]
189185
; CHECK: else:
190186
; CHECK-NEXT: ret i1 false
@@ -204,11 +200,9 @@ else:
204200

205201
define i1 @inttoptr_add_ptrtoint_used_by_multiple_icmps(ptr %src, ptr %p2, ptr %p3) {
206202
; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_multiple_icmps(
207-
; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[SRC:%.*]] to i64
208-
; CHECK-NEXT: [[A:%.*]] = add i64 [[I]], 10
209-
; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[A]] to ptr
210-
; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[P2:%.*]], [[P]]
211-
; CHECK-NEXT: [[C_2:%.*]] = icmp eq ptr [[P3:%.*]], [[P]]
203+
; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 10
204+
; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[P2]], [[P:%.*]]
205+
; CHECK-NEXT: [[C_2:%.*]] = icmp eq ptr [[P2]], [[P3:%.*]]
212206
; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[C_1]], [[C_2]]
213207
; CHECK-NEXT: ret i1 [[XOR]]
214208
;

0 commit comments

Comments
 (0)