diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index 801ac00fa8fa8..6ef55d4bfc7d7 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -2072,6 +2072,19 @@ Instruction *InstCombinerImpl::visitIntToPtr(IntToPtrInst &CI) { return new IntToPtrInst(P, CI.getType()); } + // Replace (inttoptr (add (ptrtoint %Base), %Offset)) with + // (getelementptr i8, %Base, %Offset) if all users are ICmps. + Value *Base; + Value *Offset; + if (match(CI.getOperand(0), + m_OneUse(m_c_Add(m_PtrToIntSameSize(DL, m_Value(Base)), + m_Value(Offset)))) && + CI.getType()->getPointerAddressSpace() == + Base->getType()->getPointerAddressSpace() && + all_of(CI.users(), IsaPred)) { + return GetElementPtrInst::Create(Builder.getInt8Ty(), Base, Offset); + } + if (Instruction *I = commonCastTransforms(CI)) return I; diff --git a/llvm/test/Transforms/InstCombine/fold-bin-operand.ll b/llvm/test/Transforms/InstCombine/fold-bin-operand.ll index 45d09f41fb4c5..79671215dba61 100644 --- a/llvm/test/Transforms/InstCombine/fold-bin-operand.ll +++ b/llvm/test/Transforms/InstCombine/fold-bin-operand.ll @@ -32,10 +32,8 @@ define i32 @g(i32 %x) { define i1 @inttoptr_add_ptrtoint_used_by_single_icmp(ptr %src, ptr %p2) { ; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_single_icmp( -; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[SRC:%.*]] to i64 -; CHECK-NEXT: [[A:%.*]] = add i64 [[I]], 10 -; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[A]] to ptr -; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2:%.*]], [[P]] +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 10 +; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2]], [[P:%.*]] ; CHECK-NEXT: ret i1 [[C]] ; %i = ptrtoint ptr %src to i64 @@ -47,10 +45,8 @@ define i1 @inttoptr_add_ptrtoint_used_by_single_icmp(ptr %src, ptr %p2) { define i1 @inttoptr_add_ptrtoint_used_by_single_icmp_operands_swapped(ptr %src, ptr %p2) { ; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_single_icmp_operands_swapped( -; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[SRC:%.*]] to i64 -; CHECK-NEXT: [[A:%.*]] = add i64 [[I]], 10 -; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[A]] to ptr -; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2:%.*]], [[P]] +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 10 +; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2]], [[P:%.*]] ; CHECK-NEXT: ret i1 [[C]] ; %i = ptrtoint ptr %src to i64 @@ -62,10 +58,8 @@ define i1 @inttoptr_add_ptrtoint_used_by_single_icmp_operands_swapped(ptr %src, define i1 @inttoptr_add_ptrtoint_used_by_single_icmp_constant_offset(ptr %src, i64 %off, ptr %p2) { ; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_single_icmp_constant_offset( -; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[SRC:%.*]] to i64 -; CHECK-NEXT: [[A:%.*]] = add i64 [[OFF:%.*]], [[I]] -; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[A]] to ptr -; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2:%.*]], [[P]] +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[OFF:%.*]] +; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2]], [[P:%.*]] ; CHECK-NEXT: ret i1 [[C]] ; %i = ptrtoint ptr %src to i64 @@ -77,10 +71,8 @@ define i1 @inttoptr_add_ptrtoint_used_by_single_icmp_constant_offset(ptr %src, i define i1 @inttoptr_add_ptrtoint_used_by_single_icmp_constant_offset_operands_swapped(ptr %src, i64 %off, ptr %p2) { ; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_single_icmp_constant_offset_operands_swapped( -; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[SRC:%.*]] to i64 -; CHECK-NEXT: [[A:%.*]] = add i64 [[OFF:%.*]], [[I]] -; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[A]] to ptr -; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2:%.*]], [[P]] +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[OFF:%.*]] +; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2]], [[P:%.*]] ; CHECK-NEXT: ret i1 [[C]] ; %i = ptrtoint ptr %src to i64 @@ -137,6 +129,23 @@ define i1 @inttoptr_add_ptrtoint_used_by_single_icmp_int_type_does_not_match_ptr ret i1 %c } +define i1 @inttoptr_add_multiple_users_ptrtoint_used_by_single_icmp(ptr %src, ptr %p2) { +; CHECK-LABEL: @inttoptr_add_multiple_users_ptrtoint_used_by_single_icmp( +; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[SRC:%.*]] to i64 +; CHECK-NEXT: [[A:%.*]] = add i64 [[I]], 10 +; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[A]] to ptr +; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2:%.*]], [[P]] +; CHECK-NEXT: call void @bar(i64 [[A]]) +; CHECK-NEXT: ret i1 [[C]] +; + %i = ptrtoint ptr %src to i64 + %a = add i64 %i, 10 + %p = inttoptr i64 %a to ptr + %c = icmp eq ptr %p, %p2 + call void @bar(i64 %a) + ret i1 %c +} + define i1 @multiple_inttoptr_add_ptrtoint_used_by_single_icmp(ptr %src) { ; CHECK-LABEL: @multiple_inttoptr_add_ptrtoint_used_by_single_icmp( ; CHECK-NEXT: ret i1 false @@ -181,10 +190,8 @@ define i1 @inttoptr_add_ptrtoint_used_by_single_icmp_in_different_bb(i1 %bc, ptr ; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_single_icmp_in_different_bb( ; CHECK-NEXT: br i1 [[BC:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] ; CHECK: then: -; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[SRC:%.*]] to i64 -; CHECK-NEXT: [[A:%.*]] = add i64 [[I]], 10 -; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[A]] to ptr -; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2:%.*]], [[P]] +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 10 +; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2]], [[P:%.*]] ; CHECK-NEXT: ret i1 [[C]] ; CHECK: else: ; CHECK-NEXT: ret i1 false @@ -204,11 +211,9 @@ else: define i1 @inttoptr_add_ptrtoint_used_by_multiple_icmps(ptr %src, ptr %p2, ptr %p3) { ; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_multiple_icmps( -; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[SRC:%.*]] to i64 -; CHECK-NEXT: [[A:%.*]] = add i64 [[I]], 10 -; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[A]] to ptr -; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[P2:%.*]], [[P]] -; CHECK-NEXT: [[C_2:%.*]] = icmp eq ptr [[P3:%.*]], [[P]] +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 10 +; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[P2]], [[P:%.*]] +; CHECK-NEXT: [[C_2:%.*]] = icmp eq ptr [[P2]], [[P3:%.*]] ; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[C_1]], [[C_2]] ; CHECK-NEXT: ret i1 [[XOR]] ; @@ -222,6 +227,7 @@ define i1 @inttoptr_add_ptrtoint_used_by_multiple_icmps(ptr %src, ptr %p2, ptr % } declare void @foo(ptr) +declare void @bar(i64) define i1 @inttoptr_add_ptrtoint_used_by_multiple_icmps_and_other_user(ptr %src, ptr %p2, ptr %p3) { ; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_multiple_icmps_and_other_user(