diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index a43a6ee1f58b0..dcab043c14fa5 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -2073,6 +2073,26 @@ Instruction *InstCombinerImpl::visitIntToPtr(IntToPtrInst &CI) { return new IntToPtrInst(P, CI.getType()); } + // Replace (inttoptr (add (ptrtoint %Base), %Offset)) with + // (getelementptr i8, %Base, %Offset) if the pointer is only used as integer + // value. + Value *Base; + Value *Offset; + auto UsesPointerAsInt = [](User *U) { + if (isa(U)) + return true; + if (auto *P = dyn_cast(U)) + return P->hasOneUse() && isa(*P->user_begin()); + return false; + }; + if (match(CI.getOperand(0), + m_Add(m_PtrToIntSameSize(DL, m_Value(Base)), m_Value(Offset))) && + CI.getType()->getPointerAddressSpace() == + Base->getType()->getPointerAddressSpace() && + all_of(CI.users(), UsesPointerAsInt)) { + 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 f28262b2a77e0..f596bc5d226be 100644 --- a/llvm/test/Transforms/InstCombine/fold-bin-operand.ll +++ b/llvm/test/Transforms/InstCombine/fold-bin-operand.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s -target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" +target datalayout = "E-p:64:64:64-p1:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" define i1 @f(i1 %x) { ; CHECK-LABEL: @f( @@ -30,6 +30,156 @@ define i32 @g(i32 %x) { ret i32 %b } +define i1 @inttoptr_add_ptrtoint_used_by_single_icmp(ptr %src, ptr %p2) { +; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_single_icmp( +; 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 + %a = add i64 %i, 10 + %p = inttoptr i64 %a to ptr + %c = icmp eq ptr %p, %p2 + ret i1 %c +} + +define i1 @inttoptr_add_ptrtoint_used_by_single_icmp_different_src_address_spaces(ptr addrspace(1) %src, ptr %p2) { +; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_single_icmp_different_src_address_spaces( +; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr addrspace(1) [[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: ret i1 [[C]] +; + %i = ptrtoint ptr addrspace(1) %src to i64 + %a = add i64 %i, 10 + %p = inttoptr i64 %a to ptr + %c = icmp eq ptr %p, %p2 + ret i1 %c +} + +define i1 @inttoptr_add_ptrtoint_used_by_single_icmp_different_dst_address_spaces(ptr %src, ptr addrspace(1) %p2) { +; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_single_icmp_different_dst_address_spaces( +; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[SRC:%.*]] to i64 +; CHECK-NEXT: [[A:%.*]] = add i64 [[I]], 10 +; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[A]] to ptr addrspace(1) +; CHECK-NEXT: [[C:%.*]] = icmp eq ptr addrspace(1) [[P2:%.*]], [[P]] +; CHECK-NEXT: ret i1 [[C]] +; + %i = ptrtoint ptr %src to i64 + %a = add i64 %i, 10 + %p = inttoptr i64 %a to ptr addrspace(1) + %c = icmp eq ptr addrspace(1) %p, %p2 + ret i1 %c +} + +define i1 @inttoptr_add_ptrtoint_used_by_single_icmp_int_type_does_not_match_ptr_ty(ptr %src, ptr %p2) { +; CHECK-LABEL: @inttoptr_add_ptrtoint_used_by_single_icmp_int_type_does_not_match_ptr_ty( +; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[SRC:%.*]] to i64 +; CHECK-NEXT: [[I:%.*]] = trunc i64 [[TMP1]] to i8 +; CHECK-NEXT: [[A:%.*]] = add i8 [[I]], 10 +; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[A]] to i64 +; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[TMP2]] to ptr +; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P2:%.*]], [[P]] +; CHECK-NEXT: ret i1 [[C]] +; + %i = ptrtoint ptr %src to i8 + %a = add i8 %i, 10 + %p = inttoptr i8 %a to ptr + %c = icmp eq ptr %p, %p2 + 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 +; + %i = ptrtoint ptr %src to i64 + %a = add i64 %i, 10 + %p = inttoptr i64 %a to ptr + %a.2 = add i64 %i, 11 + %p.2 = inttoptr i64 %a.2 to ptr + %c = icmp eq ptr %p, %p.2 + ret i1 %c +} + +define i1 @multiple_inttoptr_add_ptrtoint_used_by_single_icmp_non_constant_offset(ptr %src, i64 %off.1, i64 %off.2) { +; CHECK-LABEL: @multiple_inttoptr_add_ptrtoint_used_by_single_icmp_non_constant_offset( +; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[OFF_1:%.*]], [[OFF_2:%.*]] +; CHECK-NEXT: ret i1 [[C]] +; + %i = ptrtoint ptr %src to i64 + %a = add i64 %i, %off.1 + %p = inttoptr i64 %a to ptr + %a.2 = add i64 %i, %off.2 + %p.2 = inttoptr i64 %a.2 to ptr + %c = icmp eq ptr %p, %p.2 + ret i1 %c +} + +define i1 @inttoptr_add_ptrtoint_used_by_single_icmp_in_different_bb(i1 %bc, ptr %src, ptr %p2) { +; 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: [[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 +; + %i = ptrtoint ptr %src to i64 + %a = add i64 %i, 10 + %p = inttoptr i64 %a to ptr + br i1 %bc, label %then, label %else + +then: + %c = icmp eq ptr %p, %p2 + ret i1 %c + +else: + ret i1 false +} + +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: [[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]] +; + %i = ptrtoint ptr %src to i64 + %a = add i64 %i, 10 + %p = inttoptr i64 %a to ptr + %c.1 = icmp eq ptr %p, %p2 + %c.2 = icmp eq ptr %p, %p3 + %xor = xor i1 %c.1, %c.2 + ret i1 %xor +} + +declare void @foo(ptr) + +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( +; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[SRC:%.*]] to i64 +; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], 10 +; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[TMP2]] to ptr +; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[P2:%.*]], [[P]] +; CHECK-NEXT: [[C_2:%.*]] = icmp eq ptr [[P3:%.*]], [[P]] +; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[C_1]], [[C_2]] +; CHECK-NEXT: call void @foo(ptr [[P]]) +; CHECK-NEXT: ret i1 [[XOR]] +; + %i = ptrtoint ptr %src to i64 + %a = add i64 %i, 10 + %p = inttoptr i64 %a to ptr + %c.1 = icmp eq ptr %p, %p2 + %c.2 = icmp eq ptr %p, %p3 + %xor = xor i1 %c.1, %c.2 + call void @foo(ptr %p) + ret i1 %xor +} + define i32 @h(i1 %A, i32 %B) { ; CHECK-LABEL: @h( ; CHECK-NEXT: EntryBlock: diff --git a/llvm/test/Transforms/InstCombine/inttoptr-add-phi.ll b/llvm/test/Transforms/InstCombine/inttoptr-add-phi.ll new file mode 100644 index 0000000000000..233ab328d7bbb --- /dev/null +++ b/llvm/test/Transforms/InstCombine/inttoptr-add-phi.ll @@ -0,0 +1,70 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -passes=instcombine -S %s | FileCheck %s +target datalayout = "E-p:64:64:64-p1:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" + +define i64 @inttoptr_used_by_phi_with_ptrtoint(i1 %c, ptr %src, ptr %p2) { +; CHECK-LABEL: define i64 @inttoptr_used_by_phi_with_ptrtoint( +; CHECK-SAME: i1 [[C:%.*]], ptr [[SRC:%.*]], ptr [[P2:%.*]]) { +; CHECK-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[ELSE:.*]] +; CHECK: [[THEN]]: +; CHECK-NEXT: [[P:%.*]] = getelementptr i8, ptr [[SRC]], i64 10 +; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64 +; CHECK-NEXT: br label %[[EXIT:.*]] +; CHECK: [[ELSE]]: +; CHECK-NEXT: br label %[[EXIT]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[TMP1]], %[[THEN]] ], [ 0, %[[ELSE]] ] +; CHECK-NEXT: ret i64 [[PHI]] +; + %i = ptrtoint ptr %src to i64 + %a = add i64 %i, 10 + %p = inttoptr i64 %a to ptr + br i1 %c, label %then, label %else + +then: + br label %exit + +else: + br label %exit + +exit: + %phi = phi ptr [ %p, %then ], [ null, %else ] + %i.2 = ptrtoint ptr %phi to i64 + ret i64 %i.2 +} + +declare void @foo(ptr) + +define i64 @inttoptr_used_by_phi_with_other_users(i1 %c, ptr %src, ptr %p2) { +; CHECK-LABEL: define i64 @inttoptr_used_by_phi_with_other_users( +; CHECK-SAME: i1 [[C:%.*]], ptr [[SRC:%.*]], ptr [[P2:%.*]]) { +; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[SRC]] to i64 +; CHECK-NEXT: [[A:%.*]] = add i64 [[I]], 10 +; CHECK-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[ELSE:.*]] +; CHECK: [[THEN]]: +; CHECK-NEXT: br label %[[EXIT:.*]] +; CHECK: [[ELSE]]: +; CHECK-NEXT: br label %[[EXIT]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[A]], %[[THEN]] ], [ 0, %[[ELSE]] ] +; CHECK-NEXT: [[P:%.*]] = inttoptr i64 [[A]] to ptr +; CHECK-NEXT: call void @foo(ptr [[P]]) +; CHECK-NEXT: ret i64 [[PHI]] +; + %i = ptrtoint ptr %src to i64 + %a = add i64 %i, 10 + %p = inttoptr i64 %a to ptr + br i1 %c, label %then, label %else + +then: + br label %exit + +else: + br label %exit + +exit: + %phi = phi ptr [ %p, %then ], [ null, %else ] + call void @foo(ptr %p) + %i.2 = ptrtoint ptr %phi to i64 + ret i64 %i.2 +} diff --git a/llvm/test/Transforms/PhaseOrdering/AArch64/std-find.ll b/llvm/test/Transforms/PhaseOrdering/AArch64/std-find.ll index fa25af5f3467d..0ef21adff74a6 100644 --- a/llvm/test/Transforms/PhaseOrdering/AArch64/std-find.ll +++ b/llvm/test/Transforms/PhaseOrdering/AArch64/std-find.ll @@ -9,27 +9,34 @@ define i64 @std_find_i16_constant_offset_with_assumptions(ptr %first.coerce, i16 ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[FIRST_COERCE]], i64 2) ] ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[FIRST_COERCE]], i64 256) ] -; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[FIRST_COERCE]] to i64 -; CHECK-NEXT: [[COERCE_VAL_PI_I:%.*]] = add i64 [[TMP0]], 256 -; CHECK-NEXT: [[COERCE_VAL_IP:%.*]] = inttoptr i64 [[COERCE_VAL_PI_I]] to ptr -; CHECK-NEXT: [[CMP_NOT6_I_I:%.*]] = icmp eq ptr [[FIRST_COERCE]], [[COERCE_VAL_IP]] -; CHECK-NEXT: br i1 [[CMP_NOT6_I_I]], label %[[RETURN:.*]], label %[[LOOP_HEADER:.*]] -; CHECK: [[LOOP_HEADER]]: -; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[FIRST_COERCE]], %[[ENTRY]] ] -; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[PTR_IV]], align 2 -; CHECK-NEXT: [[CMP2_I_I:%.*]] = icmp eq i16 [[TMP1]], [[S]] -; CHECK-NEXT: br i1 [[CMP2_I_I]], label %[[RETURN_LOOPEXIT:.*]], label %[[LOOP_LATCH]] -; CHECK: [[LOOP_LATCH]]: -; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 2 -; CHECK-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[COERCE_VAL_IP]] -; CHECK-NEXT: br i1 [[CMP_NOT_I_I]], label %[[RETURN_LOOPEXIT]], label %[[LOOP_HEADER]] -; CHECK: [[RETURN_LOOPEXIT]]: -; CHECK-NEXT: [[MERGE_PH:%.*]] = phi ptr [ [[COERCE_VAL_IP]], %[[LOOP_LATCH]] ], [ [[PTR_IV]], %[[LOOP_HEADER]] ] -; CHECK-NEXT: [[DOTPRE:%.*]] = ptrtoint ptr [[MERGE_PH]] to i64 +; CHECK-NEXT: [[COERCE_VAL_IP:%.*]] = getelementptr i8, ptr [[FIRST_COERCE]], i64 256 +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <8 x i16> poison, i16 [[S]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <8 x i16> [[BROADCAST_SPLATINSERT]], <8 x i16> poison, <8 x i32> zeroinitializer +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 1 +; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[FIRST_COERCE]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, ptr [[NEXT_GEP]], align 2 +; CHECK-NEXT: [[TMP0:%.*]] = icmp eq <8 x i16> [[WIDE_LOAD]], [[BROADCAST_SPLAT]] +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i1> [[TMP0]] to i8 +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[INDEX_NEXT]], 128 +; CHECK-NEXT: [[TMP4:%.*]] = or i1 [[TMP2]], [[TMP3]] +; CHECK-NEXT: br i1 [[TMP4]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: [[MIDDLE_SPLIT]]: +; CHECK-NEXT: br i1 [[TMP2]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[RETURN:.*]] +; CHECK: [[VECTOR_EARLY_EXIT]]: +; CHECK-NEXT: [[TMP5:%.*]] = tail call i64 @llvm.experimental.cttz.elts.i64.v8i1(<8 x i1> [[TMP0]], i1 true) +; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[INDEX]], [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = shl i64 [[TMP6]], 1 +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[FIRST_COERCE]], i64 [[TMP7]] ; CHECK-NEXT: br label %[[RETURN]] ; CHECK: [[RETURN]]: -; CHECK-NEXT: [[RES_PRE_PHI:%.*]] = phi i64 [ [[DOTPRE]], %[[RETURN_LOOPEXIT]] ], [ [[TMP0]], %[[ENTRY]] ] -; CHECK-NEXT: ret i64 [[RES_PRE_PHI]] +; CHECK-NEXT: [[__FIRST_ADDR_0_LCSSA_I_I_PH:%.*]] = phi ptr [ [[TMP8]], %[[VECTOR_EARLY_EXIT]] ], [ [[COERCE_VAL_IP]], %[[MIDDLE_SPLIT]] ] +; CHECK-NEXT: [[DOTPRE:%.*]] = ptrtoint ptr [[__FIRST_ADDR_0_LCSSA_I_I_PH]] to i64 +; CHECK-NEXT: ret i64 [[DOTPRE]] ; entry: %first = alloca { ptr }, align 8 @@ -71,27 +78,21 @@ define i64 @std_find_i16_constant_offset_no_assumptions(ptr %first.coerce, i16 n ; CHECK-LABEL: define i64 @std_find_i16_constant_offset_no_assumptions( ; CHECK-SAME: ptr [[FIRST_COERCE:%.*]], i16 noundef signext [[S:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { ; CHECK-NEXT: [[ENTRY:.*]]: -; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[FIRST_COERCE]] to i64 -; CHECK-NEXT: [[COERCE_VAL_PI_I:%.*]] = add i64 [[TMP0]], 256 -; CHECK-NEXT: [[COERCE_VAL_IP:%.*]] = inttoptr i64 [[COERCE_VAL_PI_I]] to ptr -; CHECK-NEXT: [[CMP_NOT6_I_I:%.*]] = icmp eq ptr [[FIRST_COERCE]], [[COERCE_VAL_IP]] -; CHECK-NEXT: br i1 [[CMP_NOT6_I_I]], label %[[RETURN:.*]], label %[[LOOP_HEADER:.*]] +; CHECK-NEXT: [[COERCE_VAL_IP:%.*]] = getelementptr i8, ptr [[FIRST_COERCE]], i64 256 +; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] ; CHECK: [[LOOP_HEADER]]: -; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[FIRST_COERCE]], %[[ENTRY]] ] +; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[FIRST_COERCE]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] ; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[PTR_IV]], align 2 ; CHECK-NEXT: [[CMP2_I_I:%.*]] = icmp eq i16 [[TMP1]], [[S]] -; CHECK-NEXT: br i1 [[CMP2_I_I]], label %[[RETURN_LOOPEXIT:.*]], label %[[LOOP_LATCH]] +; CHECK-NEXT: br i1 [[CMP2_I_I]], label %[[RETURN:.*]], label %[[LOOP_LATCH]] ; CHECK: [[LOOP_LATCH]]: ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 2 ; CHECK-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[COERCE_VAL_IP]] -; CHECK-NEXT: br i1 [[CMP_NOT_I_I]], label %[[RETURN_LOOPEXIT]], label %[[LOOP_HEADER]] -; CHECK: [[RETURN_LOOPEXIT]]: +; CHECK-NEXT: br i1 [[CMP_NOT_I_I]], label %[[RETURN]], label %[[LOOP_HEADER]] +; CHECK: [[RETURN]]: ; CHECK-NEXT: [[MERGE_PH:%.*]] = phi ptr [ [[COERCE_VAL_IP]], %[[LOOP_LATCH]] ], [ [[PTR_IV]], %[[LOOP_HEADER]] ] ; CHECK-NEXT: [[DOTPRE:%.*]] = ptrtoint ptr [[MERGE_PH]] to i64 -; CHECK-NEXT: br label %[[RETURN]] -; CHECK: [[RETURN]]: -; CHECK-NEXT: [[RES_PRE_PHI:%.*]] = phi i64 [ [[DOTPRE]], %[[RETURN_LOOPEXIT]] ], [ [[TMP0]], %[[ENTRY]] ] -; CHECK-NEXT: ret i64 [[RES_PRE_PHI]] +; CHECK-NEXT: ret i64 [[DOTPRE]] ; entry: %first = alloca { ptr }, align 8 @@ -128,3 +129,8 @@ return: } declare void @llvm.assume(i1 noundef) +;. +; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} +; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} +; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"} +;.