[llvm] f1483ea - [PhaseOrdering] Add more tests for expanding ptr SCEVs (NFC) (#211360)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 22 13:53:01 PDT 2026


Author: Florian Hahn
Date: 2026-07-22T21:52:57+01:00
New Revision: f1483ea484bafdf5e7ec6f17e94f7200256aa0e5

URL: https://github.com/llvm/llvm-project/commit/f1483ea484bafdf5e7ec6f17e94f7200256aa0e5
DIFF: https://github.com/llvm/llvm-project/commit/f1483ea484bafdf5e7ec6f17e94f7200256aa0e5.diff

LOG: [PhaseOrdering] Add more tests for expanding ptr SCEVs (NFC) (#211360)

Add more test cases requiring pointer-based SCEVs for
https://github.com/llvm/llvm-project/pull/180244.

Added: 
    llvm/test/Transforms/IndVarSimplify/AArch64/ptrtoaddr-ptrtoint.ll
    llvm/test/Transforms/IndVarSimplify/X86/ptrtoaddr-narrow-pointer.ll
    llvm/test/Transforms/LoopStrengthReduce/AArch64/expand-ptrtoaddr-reuse-ptrtoint.ll
    llvm/test/Transforms/PhaseOrdering/X86/ptrtoaddr-ptrtoint.ll

Modified: 
    llvm/test/Analysis/ScalarEvolution/ptrtoint.ll

Removed: 
    llvm/test/Transforms/IndVarSimplify/AArch64/expand-ptrtoaddr-reuse-ptrtoint.ll


################################################################################
diff  --git a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
index 2b07c944eb1d1..4863477fbd977 100644
--- a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
+++ b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
@@ -684,3 +684,58 @@ bb13:                                             ; preds = %bb10, %bb8
 bb14:                                             ; preds = %bb
   ret void
 }
+
+define i64 @ptrtoint_signbits(i1 %c) {
+; CHECK-LABEL: 'ptrtoint_signbits'
+; CHECK-NEXT:  Classifying expressions for: @ptrtoint_signbits
+; CHECK-NEXT:    %p = select i1 %c, ptr null, ptr inttoptr (i64 -1 to ptr)
+; CHECK-NEXT:    --> %p U: [-1,1) S: [-1,1)
+; CHECK-NEXT:    %a = ptrtoint ptr %p to i64
+; CHECK-NEXT:    --> %a U: full-set S: full-set
+; CHECK-NEXT:  Determining loop execution counts for: @ptrtoint_signbits
+;
+  %p = select i1 %c, ptr null, ptr inttoptr (i64 -1 to ptr)
+  %a = ptrtoint ptr %p to i64
+  ret i64 %a
+}
+
+define void @ptrtoint_iv_start(ptr %arg, ptr %dst) {
+; CHECK-LABEL: 'ptrtoint_iv_start_no_cancel'
+; CHECK-NEXT:  Classifying expressions for: @ptrtoint_iv_start_no_cancel
+; CHECK-NEXT:    %start = ptrtoint ptr %arg to i64
+; CHECK-NEXT:    --> %start U: full-set S: full-set
+; CHECK-NEXT:    %p = phi ptr [ %arg, %entry ], [ %p.next, %loop ]
+; CHECK-NEXT:    --> {%arg,+,8}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %pi = phi i64 [ %start, %entry ], [ %pi.next, %loop ]
+; CHECK-NEXT:    --> {%start,+,8}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %cur = ptrtoint ptr %p to i64
+; CHECK-NEXT:    --> {(ptrtoaddr ptr %arg to i64),+,8}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %off = sub i64 %cur, %pi
+; CHECK-NEXT:    --> ((-1 * %start) + (ptrtoaddr ptr %arg to i64)) U: full-set S: full-set Exits: ((-1 * %start) + (ptrtoaddr ptr %arg to i64)) LoopDispositions: { %loop: Invariant }
+; CHECK-NEXT:    %p.next = getelementptr i8, ptr %p, i64 8
+; CHECK-NEXT:    --> {(8 + %arg),+,8}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %pi.next = add i64 %pi, 8
+; CHECK-NEXT:    --> {(8 + %start),+,8}<%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @ptrtoint_iv_start_no_cancel
+; CHECK-NEXT:  Loop %loop: Unpredictable backedge-taken count.
+; CHECK-NEXT:  Loop %loop: Unpredictable constant max backedge-taken count.
+; CHECK-NEXT:  Loop %loop: Unpredictable symbolic max backedge-taken count.
+;
+entry:
+  %start = ptrtoint ptr %arg to i64
+  br label %loop
+
+loop:
+  %p = phi ptr [ %arg, %entry ], [ %p.next, %loop ]
+  %pi = phi i64 [ %start, %entry ], [ %pi.next, %loop ]
+  %cur = ptrtoint ptr %p to i64
+  %off = sub i64 %cur, %pi
+  store i64 %off, ptr %dst, align 8
+  %p.next = getelementptr i8, ptr %p, i64 8
+  %pi.next = add i64 %pi, 8
+  %ec = icmp eq i64 %off, 80
+  br i1 %ec, label %exit, label %loop
+
+exit:
+  ret void
+}

diff  --git a/llvm/test/Transforms/IndVarSimplify/AArch64/expand-ptrtoaddr-reuse-ptrtoint.ll b/llvm/test/Transforms/IndVarSimplify/AArch64/expand-ptrtoaddr-reuse-ptrtoint.ll
deleted file mode 100644
index 30afcf6237067..0000000000000
--- a/llvm/test/Transforms/IndVarSimplify/AArch64/expand-ptrtoaddr-reuse-ptrtoint.ll
+++ /dev/null
@@ -1,46 +0,0 @@
-; RUN: opt -passes='indvars' -S %s | FileCheck %s
-
-target triple = "arm64-apple-macosx"
-
-define i64 @count_then_convert(ptr %end) {
-; CHECK-LABEL: @count_then_convert(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[END1:%.*]] = ptrtoint ptr [[END:%.*]] to i64
-; CHECK-NEXT:    [[ISEMPTY:%.*]] = icmp eq ptr [[END]], null
-; CHECK-NEXT:    br i1 [[ISEMPTY]], label [[EXIT:%.*]], label [[BODY_PH:%.*]]
-; CHECK:       body.ph:
-; CHECK-NEXT:    br label [[BODY:%.*]]
-; CHECK:       body:
-; CHECK-NEXT:    br i1 true, label [[EXIT_LOOPEXIT:%.*]], label [[BODY]]
-; CHECK:       exit.loopexit:
-; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[END1]], -8
-; CHECK-NEXT:    [[TMP1:%.*]] = lshr i64 [[TMP0]], 3
-; CHECK-NEXT:    [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1
-; CHECK-NEXT:    br label [[EXIT]]
-; CHECK:       exit:
-; CHECK-NEXT:    [[CNT:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[EXIT_LOOPEXIT]] ]
-; CHECK-NEXT:    [[ENDI:%.*]] = ptrtoint ptr [[END]] to i64
-; CHECK-NEXT:    [[R:%.*]] = or i64 [[CNT]], [[ENDI]]
-; CHECK-NEXT:    ret i64 [[R]]
-;
-entry:
-  %isempty = icmp eq ptr %end, null
-  br i1 %isempty, label %exit, label %body.ph
-
-body.ph:
-  br label %body
-
-body:
-  %p = phi ptr [ null, %body.ph ], [ %pn, %body ]
-  %n = phi i64 [ 0, %body.ph ], [ %nn, %body ]
-  %nn = add i64 %n, 1
-  %pn = getelementptr inbounds nuw i8, ptr %p, i64 8
-  %done = icmp eq ptr %pn, %end
-  br i1 %done, label %exit, label %body
-
-exit:
-  %cnt = phi i64 [ 0, %entry ], [ %nn, %body ]
-  %endi = ptrtoint ptr %end to i64
-  %r = or i64 %cnt, %endi
-  ret i64 %r
-}

diff  --git a/llvm/test/Transforms/IndVarSimplify/AArch64/ptrtoaddr-ptrtoint.ll b/llvm/test/Transforms/IndVarSimplify/AArch64/ptrtoaddr-ptrtoint.ll
new file mode 100644
index 0000000000000..fee21dc0a9300
--- /dev/null
+++ b/llvm/test/Transforms/IndVarSimplify/AArch64/ptrtoaddr-ptrtoint.ll
@@ -0,0 +1,106 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes='indvars' -S %s | FileCheck %s
+
+target triple = "arm64-apple-macosx"
+
+define i64 @count_then_convert(ptr %end) {
+; CHECK-LABEL: define i64 @count_then_convert(
+; CHECK-SAME: ptr [[END:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[END1:%.*]] = ptrtoint ptr [[END]] to i64
+; CHECK-NEXT:    [[ISEMPTY:%.*]] = icmp eq ptr [[END]], null
+; CHECK-NEXT:    br i1 [[ISEMPTY]], label %[[EXIT:.*]], label %[[BODY_PH:.*]]
+; CHECK:       [[BODY_PH]]:
+; CHECK-NEXT:    br label %[[BODY:.*]]
+; CHECK:       [[BODY]]:
+; CHECK-NEXT:    br i1 true, label %[[EXIT_LOOPEXIT:.*]], label %[[BODY]]
+; CHECK:       [[EXIT_LOOPEXIT]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[END1]], -8
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i64 [[TMP0]], 3
+; CHECK-NEXT:    [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1
+; CHECK-NEXT:    br label %[[EXIT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[CNT:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[TMP2]], %[[EXIT_LOOPEXIT]] ]
+; CHECK-NEXT:    [[ENDI:%.*]] = ptrtoint ptr [[END]] to i64
+; CHECK-NEXT:    [[R:%.*]] = or i64 [[CNT]], [[ENDI]]
+; CHECK-NEXT:    ret i64 [[R]]
+;
+entry:
+  %isempty = icmp eq ptr %end, null
+  br i1 %isempty, label %exit, label %body.ph
+
+body.ph:
+  br label %body
+
+body:
+  %p = phi ptr [ null, %body.ph ], [ %pn, %body ]
+  %n = phi i64 [ 0, %body.ph ], [ %nn, %body ]
+  %nn = add i64 %n, 1
+  %pn = getelementptr inbounds nuw i8, ptr %p, i64 8
+  %done = icmp eq ptr %pn, %end
+  br i1 %done, label %exit, label %body
+
+exit:
+  %cnt = phi i64 [ 0, %entry ], [ %nn, %body ]
+  %endi = ptrtoint ptr %end to i64
+  %r = or i64 %cnt, %endi
+  ret i64 %r
+}
+
+define i64 @ptrtoint_sub_in_exit(ptr %start, ptr %bound) {
+; CHECK-LABEL: define i64 @ptrtoint_sub_in_exit(
+; CHECK-SAME: ptr [[START:%.*]], ptr [[BOUND:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[START3:%.*]] = ptrtoint ptr [[START]] to i64
+; CHECK-NEXT:    [[BOUND2:%.*]] = ptrtoint ptr [[BOUND]] to i64
+; CHECK-NEXT:    [[TMP0:%.*]] = sub i64 [[BOUND2]], [[START3]]
+; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP0]]
+; CHECK-NEXT:    br label %[[BODY:.*]]
+; CHECK:       [[BODY]]:
+; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PN:%.*]], %[[LATCH:.*]] ]
+; CHECK-NEXT:    [[C:%.*]] = load i8, ptr [[P]], align 1
+; CHECK-NEXT:    [[ISC:%.*]] = icmp slt i8 [[C]], -64
+; CHECK-NEXT:    br i1 [[ISC]], label %[[LATCH]], label %[[EXIT_BYTE:.*]]
+; CHECK:       [[LATCH]]:
+; CHECK-NEXT:    [[PN]] = getelementptr inbounds i8, ptr [[P]], i64 -1
+; CHECK-NEXT:    [[DONE:%.*]] = icmp eq ptr [[PN]], [[BOUND]]
+; CHECK-NEXT:    br i1 [[DONE]], label %[[EXIT_BOUND:.*]], label %[[BODY]]
+; CHECK:       [[EXIT_BYTE]]:
+; CHECK-NEXT:    [[P_LCSSA:%.*]] = phi ptr [ [[P]], %[[BODY]] ]
+; CHECK-NEXT:    br label %[[EXIT:.*]]
+; CHECK:       [[EXIT_BOUND]]:
+; CHECK-NEXT:    br label %[[EXIT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[FINAL:%.*]] = phi ptr [ [[P_LCSSA]], %[[EXIT_BYTE]] ], [ [[SCEVGEP]], %[[EXIT_BOUND]] ]
+; CHECK-NEXT:    [[FI:%.*]] = ptrtoint ptr [[FINAL]] to i64
+; CHECK-NEXT:    [[BI:%.*]] = ptrtoint ptr [[BOUND]] to i64
+; CHECK-NEXT:    [[LEN:%.*]] = sub i64 [[FI]], [[BI]]
+; CHECK-NEXT:    ret i64 [[LEN]]
+;
+entry:
+  br label %body
+
+body:
+  %p = phi ptr [ %start, %entry ], [ %pn, %latch ]
+  %c = load i8, ptr %p, align 1
+  %isc = icmp slt i8 %c, -64
+  br i1 %isc, label %latch, label %exit.byte
+
+latch:
+  %pn = getelementptr inbounds i8, ptr %p, i64 -1
+  %done = icmp eq ptr %pn, %bound
+  br i1 %done, label %exit.bound, label %body
+
+exit.byte:
+  br label %exit
+
+exit.bound:
+  br label %exit
+
+exit:
+  %final = phi ptr [ %p, %exit.byte ], [ %pn, %exit.bound ]
+  %fi = ptrtoint ptr %final to i64
+  %bi = ptrtoint ptr %bound to i64
+  %len = sub i64 %fi, %bi
+  ret i64 %len
+}

diff  --git a/llvm/test/Transforms/IndVarSimplify/X86/ptrtoaddr-narrow-pointer.ll b/llvm/test/Transforms/IndVarSimplify/X86/ptrtoaddr-narrow-pointer.ll
new file mode 100644
index 0000000000000..0019e7b1eea18
--- /dev/null
+++ b/llvm/test/Transforms/IndVarSimplify/X86/ptrtoaddr-narrow-pointer.ll
@@ -0,0 +1,40 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes='indvars' -S %s | FileCheck %s
+
+target datalayout = "e-p:64:64-p1:64:64:64:32"
+target triple = "x86_64-unknown-linux"
+
+define ptr addrspace(1) @exit_value_narrow_address(ptr addrspace(1) %start, ptr addrspace(1) %end) {
+; CHECK-LABEL: define ptr addrspace(1) @exit_value_narrow_address(
+; CHECK-SAME: ptr addrspace(1) [[START:%.*]], ptr addrspace(1) [[END:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[PRE:%.*]] = icmp ult ptr addrspace(1) [[START]], [[END]]
+; CHECK-NEXT:    br i1 [[PRE]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]]
+; CHECK:       [[LOOP_PREHEADER]]:
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[P:%.*]] = phi ptr addrspace(1) [ [[P_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ]
+; CHECK-NEXT:    [[P_NEXT]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 1
+; CHECK-NEXT:    [[C:%.*]] = icmp ult ptr addrspace(1) [[P_NEXT]], [[END]]
+; CHECK-NEXT:    br i1 [[C]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]]
+; CHECK:       [[EXIT_LOOPEXIT]]:
+; CHECK-NEXT:    [[P_NEXT_LCSSA:%.*]] = phi ptr addrspace(1) [ [[P_NEXT]], %[[LOOP]] ]
+; CHECK-NEXT:    br label %[[EXIT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[RES:%.*]] = phi ptr addrspace(1) [ [[START]], %[[ENTRY]] ], [ [[P_NEXT_LCSSA]], %[[EXIT_LOOPEXIT]] ]
+; CHECK-NEXT:    ret ptr addrspace(1) [[RES]]
+;
+entry:
+  %pre = icmp ult ptr addrspace(1) %start, %end
+  br i1 %pre, label %loop, label %exit
+
+loop:
+  %p = phi ptr addrspace(1) [ %start, %entry ], [ %p.next, %loop ]
+  %p.next = getelementptr inbounds i8, ptr addrspace(1) %p, i64 1
+  %c = icmp ult ptr addrspace(1) %p.next, %end
+  br i1 %c, label %loop, label %exit
+
+exit:
+  %res = phi ptr addrspace(1) [ %start, %entry ], [ %p.next, %loop ]
+  ret ptr addrspace(1) %res
+}

diff  --git a/llvm/test/Transforms/LoopStrengthReduce/AArch64/expand-ptrtoaddr-reuse-ptrtoint.ll b/llvm/test/Transforms/LoopStrengthReduce/AArch64/expand-ptrtoaddr-reuse-ptrtoint.ll
new file mode 100644
index 0000000000000..38d9ad1418373
--- /dev/null
+++ b/llvm/test/Transforms/LoopStrengthReduce/AArch64/expand-ptrtoaddr-reuse-ptrtoint.ll
@@ -0,0 +1,58 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes='loop-reduce' -S %s | FileCheck %s
+
+target triple = "arm64-apple-macosx"
+
+define i64 @expand_reuses_existing_ptrtoint(ptr %begin, ptr %end, ptr %cap) {
+; CHECK-LABEL: define i64 @expand_reuses_existing_ptrtoint(
+; CHECK-SAME: ptr [[BEGIN:%.*]], ptr [[END:%.*]], ptr [[CAP:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[BEGIN2:%.*]] = ptrtoint ptr [[BEGIN]] to i64
+; CHECK-NEXT:    [[END1:%.*]] = ptrtoint ptr [[END]] to i64
+; CHECK-NEXT:    [[C0:%.*]] = icmp eq ptr [[BEGIN]], [[END]]
+; CHECK-NEXT:    br i1 [[C0]], label %[[DONE:.*]], label %[[COUNT_PH:.*]]
+; CHECK:       [[COUNT_PH]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[END1]], -8
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i64 [[TMP0]], [[BEGIN2]]
+; CHECK-NEXT:    [[TMP2:%.*]] = lshr i64 [[TMP1]], 3
+; CHECK-NEXT:    [[TMP3:%.*]] = shl nuw i64 [[TMP2]], 3
+; CHECK-NEXT:    [[TMP4:%.*]] = add i64 [[TMP3]], 8
+; CHECK-NEXT:    br label %[[COUNT:.*]]
+; CHECK:       [[COUNT]]:
+; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[BEGIN]], %[[COUNT_PH]] ], [ [[PN:%.*]], %[[COUNT]] ]
+; CHECK-NEXT:    [[PN]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8
+; CHECK-NEXT:    [[D:%.*]] = icmp eq ptr [[PN]], [[END]]
+; CHECK-NEXT:    br i1 [[D]], label %[[DONE_LOOPEXIT:.*]], label %[[COUNT]]
+; CHECK:       [[DONE_LOOPEXIT]]:
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    [[USED:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[TMP4]], %[[DONE_LOOPEXIT]] ]
+; CHECK-NEXT:    [[CAPI:%.*]] = ptrtoint ptr [[CAP]] to i64
+; CHECK-NEXT:    [[ENDI:%.*]] = ptrtoint ptr [[END]] to i64
+; CHECK-NEXT:    [[SLACK:%.*]] = sub i64 [[CAPI]], [[ENDI]]
+; CHECK-NEXT:    [[TOTAL:%.*]] = add i64 [[USED]], [[SLACK]]
+; CHECK-NEXT:    ret i64 [[TOTAL]]
+;
+entry:
+  %c0 = icmp eq ptr %begin, %end
+  br i1 %c0, label %done, label %count.ph
+
+count.ph:
+  br label %count
+
+count:
+  %p = phi ptr [ %begin, %count.ph ], [ %pn, %count ]
+  %n = phi i64 [ 0, %count.ph ], [ %nn, %count ]
+  %pn = getelementptr inbounds nuw i8, ptr %p, i64 8
+  %nn = add i64 %n, 8
+  %d = icmp eq ptr %pn, %end
+  br i1 %d, label %done, label %count
+
+done:
+  %used = phi i64 [ 0, %entry ], [ %nn, %count ]
+  %capi = ptrtoint ptr %cap to i64
+  %endi = ptrtoint ptr %end to i64
+  %slack = sub i64 %capi, %endi
+  %total = add i64 %used, %slack
+  ret i64 %total
+}

diff  --git a/llvm/test/Transforms/PhaseOrdering/X86/ptrtoaddr-ptrtoint.ll b/llvm/test/Transforms/PhaseOrdering/X86/ptrtoaddr-ptrtoint.ll
new file mode 100644
index 0000000000000..efcc1701c9bbe
--- /dev/null
+++ b/llvm/test/Transforms/PhaseOrdering/X86/ptrtoaddr-ptrtoint.ll
@@ -0,0 +1,379 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 6
+; RUN: opt -passes="default<O3>" -S < %s | FileCheck %s
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+declare void @llvm.memmove.p0.p0.i64(ptr writeonly captures(none), ptr readonly captures(none), i64, i1 immarg)
+
+define void @redundant_int_iv(ptr %first) {
+; CHECK-LABEL: define void @redundant_int_iv(
+; CHECK-SAME: ptr [[FIRST:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[PTR_INT1:%.*]] = ptrtoint ptr [[FIRST]] to i64
+; CHECK-NEXT:    [[OFF2:%.*]] = add i64 [[PTR_INT1]], 1
+; CHECK-NEXT:    [[EC_OUTER3:%.*]] = icmp slt i64 [[OFF2]], 0
+; CHECK-NEXT:    br i1 [[EC_OUTER3]], label %[[INNER_PH:.*]], label %[[EXIT:.*]]
+; CHECK:       [[INNER_PH]]:
+; CHECK-NEXT:    [[PTR_IV4:%.*]] = phi ptr [ [[LAST:%.*]], %[[INNER_PH]] ], [ [[FIRST]], %[[ENTRY]] ]
+; CHECK-NEXT:    [[LAST]] = getelementptr i8, ptr [[PTR_IV4]], i64 7
+; CHECK-NEXT:    [[CUR_NEXT:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 1
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[PTR_IV4]], align 1
+; CHECK-NEXT:    store i8 [[TMP0]], ptr [[CUR_NEXT]], align 1
+; CHECK-NEXT:    [[CUR_NEXT_1:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 2
+; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[PTR_IV4]], align 1
+; CHECK-NEXT:    store i16 [[TMP1]], ptr [[CUR_NEXT_1]], align 1
+; CHECK-NEXT:    [[CUR_NEXT_2:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 3
+; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(3) [[CUR_NEXT_2]], ptr noundef nonnull align 1 dereferenceable(3) [[PTR_IV4]], i64 3, i1 false)
+; CHECK-NEXT:    [[CUR_NEXT_3:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 4
+; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[PTR_IV4]], align 1
+; CHECK-NEXT:    store i32 [[TMP2]], ptr [[CUR_NEXT_3]], align 1
+; CHECK-NEXT:    [[CUR_NEXT_4:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 5
+; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[CUR_NEXT_4]], ptr noundef nonnull align 1 dereferenceable(5) [[PTR_IV4]], i64 5, i1 false)
+; CHECK-NEXT:    [[CUR_NEXT_5:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 6
+; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(6) [[CUR_NEXT_5]], ptr noundef nonnull align 1 dereferenceable(6) [[PTR_IV4]], i64 6, i1 false)
+; CHECK-NEXT:    [[CUR_NEXT_6:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 7
+; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(7) [[CUR_NEXT_6]], ptr noundef nonnull align 1 dereferenceable(7) [[PTR_IV4]], i64 7, i1 false)
+; CHECK-NEXT:    [[PTR_INT:%.*]] = ptrtoint ptr [[LAST]] to i64
+; CHECK-NEXT:    [[OFF:%.*]] = add i64 [[PTR_INT]], 1
+; CHECK-NEXT:    [[EC_OUTER:%.*]] = icmp slt i64 [[OFF]], 0
+; CHECK-NEXT:    br i1 [[EC_OUTER]], label %[[INNER_PH]], label %[[EXIT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %outer
+
+outer:
+  %ptr.iv = phi ptr [ %first, %entry ], [ %ptr.next, %inner.exit ]
+  %ptr.int = ptrtoint ptr %ptr.iv to i64
+  %off = add i64 %ptr.int, 1
+  %ec.outer = icmp slt i64 %off, 0
+  br i1 %ec.outer, label %inner.ph, label %exit
+
+inner.ph:
+  %last = getelementptr i8, ptr %ptr.iv, i64 7
+  br label %inner
+
+inner:
+  %cur = phi ptr [ %ptr.iv, %inner.ph ], [ %cur.next, %inner ]
+  %cur.next = getelementptr i8, ptr %cur, i64 1
+  %cur.int = ptrtoint ptr %cur.next to i64
+  %len = sub i64 %cur.int, %ptr.int
+  call void @llvm.memmove.p0.p0.i64(ptr %cur.next, ptr %ptr.iv, i64 %len, i1 false)
+  %inner.done = icmp eq ptr %cur.next, %last
+  br i1 %inner.done, label %inner.exit, label %inner
+
+inner.exit:
+  %ptr.next = getelementptr i8, ptr %ptr.iv, i64 7
+  br label %outer
+
+exit:
+  ret void
+}
+
+define ptr @cancel_out_of_range(ptr %p) {
+; CHECK-LABEL: define noalias noundef ptr @cancel_out_of_range(
+; CHECK-SAME: ptr [[P:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[P1:%.*]] = ptrtoint ptr [[P]] to i64
+; CHECK-NEXT:    store ptr [[P]], ptr [[P]], align 8
+; CHECK-NEXT:    [[TMP0:%.*]] = and i64 [[P1]], 255
+; CHECK-NEXT:    [[IS_ZERO:%.*]] = icmp eq i64 [[TMP0]], 0
+; CHECK-NEXT:    [[SPEC_SELECT_IDX:%.*]] = select i1 [[IS_ZERO]], i64 0, i64 [[P1]]
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = getelementptr i8, ptr null, i64 [[SPEC_SELECT_IDX]]
+; CHECK-NEXT:    ret ptr [[SPEC_SELECT]]
+;
+entry:
+  store ptr %p, ptr %p, align 8
+  %first = load i8, ptr %p, align 1
+  %is.zero = icmp eq i8 %first, 0
+  br i1 %is.zero, label %exit, label %loop
+
+exit:
+  %res = phi ptr [ null, %entry ], [ %cur, %loop ]
+  ret ptr %res
+
+loop:
+  %cur = phi ptr [ null, %entry ], [ %prev, %loop.dec ]
+  %found = icmp eq ptr %cur, %p
+  br i1 %found, label %exit, label %loop.dec
+
+loop.dec:
+  %prev = getelementptr i8, ptr %cur, i64 -1
+  br label %loop
+}
+
+ at end = external global i8
+
+define i64 @cse_two_guards(ptr %base, i64 %n, ptr %cmp) {
+; CHECK-LABEL: define i64 @cse_two_guards(
+; CHECK-SAME: ptr [[BASE:%.*]], i64 [[N:%.*]], ptr nofree readonly captures(none) [[CMP:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[N_FR:%.*]] = freeze i64 [[N]]
+; CHECK-NEXT:    store ptr [[BASE]], ptr [[BASE]], align 8
+; CHECK-NEXT:    [[NE_I_NOT6:%.*]] = icmp eq ptr [[BASE]], @end
+; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[BASE]] to i64
+; CHECK-NEXT:    br i1 [[NE_I_NOT6]], label %[[RET:.*]], label %[[LOOP1_INC_PREHEADER:.*]]
+; CHECK:       [[LOOP1_INC_PREHEADER]]:
+; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[BASE]] to i64
+; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 add (i64 ptrtoint (ptr @end to i64), i64 -48), [[TMP1]]
+; CHECK-NEXT:    [[TMP3:%.*]] = udiv i64 [[TMP2]], 48
+; CHECK-NEXT:    [[TMP4:%.*]] = add nuw nsw i64 [[TMP3]], 1
+; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP2]], 144
+; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label %[[LOOP1_INC_PREHEADER41:.*]], label %[[VECTOR_PH:.*]]
+; CHECK:       [[VECTOR_PH]]:
+; CHECK-NEXT:    [[N_VEC:%.*]] = and i64 [[TMP4]], 1152921504606846972
+; CHECK-NEXT:    [[TMP5:%.*]] = mul i64 [[N_VEC]], 48
+; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[TMP5]]
+; CHECK-NEXT:    [[TMP7:%.*]] = icmp ult i64 [[N_FR]], 2
+; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
+; CHECK:       [[VECTOR_BODY]]:
+; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
+; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
+; CHECK-NEXT:    br i1 [[TMP8]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
+; CHECK:       [[MIDDLE_BLOCK]]:
+; CHECK-NEXT:    [[RDX_SELECT:%.*]] = zext i1 [[TMP7]] to i64
+; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 [[TMP4]], [[N_VEC]]
+; CHECK-NEXT:    br i1 [[CMP_N]], label %[[LOOP2_BODY_LR_PH:.*]], label %[[LOOP1_INC_PREHEADER41]]
+; CHECK:       [[LOOP1_INC_PREHEADER41]]:
+; CHECK-NEXT:    [[R8_PH:%.*]] = phi i64 [ 1, %[[LOOP1_INC_PREHEADER]] ], [ [[RDX_SELECT]], %[[MIDDLE_BLOCK]] ]
+; CHECK-NEXT:    [[IT1_07_PH:%.*]] = phi ptr [ [[BASE]], %[[LOOP1_INC_PREHEADER]] ], [ [[TMP6]], %[[MIDDLE_BLOCK]] ]
+; CHECK-NEXT:    br label %[[LOOP1_INC:.*]]
+; CHECK:       [[LOOP2_BODY_LR_PH]]:
+; CHECK-NEXT:    [[SEL_LCSSA:%.*]] = phi i64 [ [[RDX_SELECT]], %[[MIDDLE_BLOCK]] ], [ [[SEL:%.*]], %[[LOOP1_INC]] ]
+; CHECK-NEXT:    [[TMP9:%.*]] = uitofp nneg i64 [[SEL_LCSSA]] to double
+; CHECK-NEXT:    [[MIN_ITERS_CHECK18:%.*]] = icmp ult i64 [[TMP2]], 144
+; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK18]], label %[[LOOP2_BODY_PREHEADER:.*]], label %[[VECTOR_MEMCHECK:.*]]
+; CHECK:       [[VECTOR_MEMCHECK]]:
+; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[BASE]], i64 8
+; CHECK-NEXT:    [[SCEVGEP16:%.*]] = getelementptr i8, ptr [[CMP]], i64 8
+; CHECK-NEXT:    [[BOUND0:%.*]] = icmp ult ptr [[BASE]], [[SCEVGEP16]]
+; CHECK-NEXT:    [[BOUND1:%.*]] = icmp ult ptr [[CMP]], [[SCEVGEP]]
+; CHECK-NEXT:    [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]]
+; CHECK-NEXT:    br i1 [[FOUND_CONFLICT]], label %[[LOOP2_BODY_PREHEADER]], label %[[VECTOR_PH19:.*]]
+; CHECK:       [[VECTOR_PH19]]:
+; CHECK-NEXT:    [[N_VEC21:%.*]] = and i64 [[TMP4]], 1152921504606846974
+; CHECK-NEXT:    [[BROADCAST_SPLATINSERT22:%.*]] = insertelement <2 x double> poison, double [[TMP9]], i64 0
+; CHECK-NEXT:    [[TMP10:%.*]] = mul i64 [[N_VEC21]], 48
+; CHECK-NEXT:    [[TMP11:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[TMP10]]
+; CHECK-NEXT:    [[TMP12:%.*]] = load i64, ptr [[CMP]], align 8, !alias.scope [[META3:![0-9]+]]
+; CHECK-NEXT:    [[BROADCAST_SPLATINSERT24:%.*]] = insertelement <2 x i64> poison, i64 [[TMP12]], i64 0
+; CHECK-NEXT:    [[TMP13:%.*]] = uitofp <2 x i64> [[BROADCAST_SPLATINSERT24]] to <2 x double>
+; CHECK-NEXT:    [[TMP14:%.*]] = fmul nnan <2 x double> [[BROADCAST_SPLATINSERT22]], [[TMP13]]
+; CHECK-NEXT:    [[TMP15:%.*]] = fcmp ugt <2 x double> [[TMP14]], zeroinitializer
+; CHECK-NEXT:    [[TMP16:%.*]] = shufflevector <2 x i1> [[TMP15]], <2 x i1> poison, <2 x i32> zeroinitializer
+; CHECK-NEXT:    [[TMP17:%.*]] = freeze <2 x i1> [[TMP16]]
+; CHECK-NEXT:    [[TMP18:%.*]] = bitcast <2 x i1> [[TMP17]] to i2
+; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp eq i2 [[TMP18]], 0
+; CHECK-NEXT:    [[BROADCAST_SPLATINSERT26:%.*]] = insertelement <2 x i64> poison, i64 [[TMP0]], i64 0
+; CHECK-NEXT:    [[BROADCAST_SPLAT27:%.*]] = shufflevector <2 x i64> [[BROADCAST_SPLATINSERT26]], <2 x i64> poison, <2 x i32> zeroinitializer
+; CHECK-NEXT:    [[TMP19:%.*]] = bitcast <2 x i1> [[TMP17]] to i2
+; CHECK-NEXT:    [[DOTNOT39:%.*]] = icmp eq i2 [[TMP19]], 0
+; CHECK-NEXT:    br label %[[VECTOR_BODY28:.*]]
+; CHECK:       [[VECTOR_BODY28]]:
+; CHECK-NEXT:    [[INDEX29:%.*]] = phi i64 [ 0, %[[VECTOR_PH19]] ], [ [[INDEX_NEXT33:%.*]], %[[TMP22:.*]] ]
+; CHECK-NEXT:    [[VEC_PHI30:%.*]] = phi <2 x i64> [ [[BROADCAST_SPLAT27]], %[[VECTOR_PH19]] ], [ [[TMP24:%.*]], %[[TMP22]] ]
+; CHECK-NEXT:    [[TMP20:%.*]] = phi <2 x i1> [ zeroinitializer, %[[VECTOR_PH19]] ], [ [[TMP23:%.*]], %[[TMP22]] ]
+; CHECK-NEXT:    br i1 [[DOTNOT39]], label %[[TMP22]], label %[[BB21:.*]]
+; CHECK:       [[BB21]]:
+; CHECK-NEXT:    store i64 0, ptr [[BASE]], align 8, !alias.scope [[META6:![0-9]+]], !noalias [[META3]]
+; CHECK-NEXT:    br label %[[TMP22]]
+; CHECK:       [[TMP22]]:
+; CHECK-NEXT:    [[TMP23]] = select i1 [[DOTNOT]], <2 x i1> [[TMP20]], <2 x i1> [[TMP17]]
+; CHECK-NEXT:    [[TMP24]] = select i1 [[DOTNOT]], <2 x i64> [[VEC_PHI30]], <2 x i64> zeroinitializer
+; CHECK-NEXT:    [[INDEX_NEXT33]] = add nuw i64 [[INDEX29]], 2
+; CHECK-NEXT:    [[TMP25:%.*]] = icmp eq i64 [[INDEX_NEXT33]], [[N_VEC21]]
+; CHECK-NEXT:    br i1 [[TMP25]], label %[[MIDDLE_BLOCK34:.*]], label %[[VECTOR_BODY28]], !llvm.loop [[LOOP8:![0-9]+]]
+; CHECK:       [[MIDDLE_BLOCK34]]:
+; CHECK-NEXT:    [[TMP26:%.*]] = tail call i64 @llvm.experimental.vector.extract.last.active.v2i64(<2 x i64> [[TMP24]], <2 x i1> [[TMP23]], i64 [[TMP0]])
+; CHECK-NEXT:    [[CMP_N35:%.*]] = icmp eq i64 [[TMP4]], [[N_VEC21]]
+; CHECK-NEXT:    br i1 [[CMP_N35]], label %[[RET]], label %[[LOOP2_BODY_PREHEADER]]
+; CHECK:       [[LOOP2_BODY_PREHEADER]]:
+; CHECK-NEXT:    [[RES12_PH:%.*]] = phi i64 [ [[TMP0]], %[[VECTOR_MEMCHECK]] ], [ [[TMP0]], %[[LOOP2_BODY_LR_PH]] ], [ [[TMP26]], %[[MIDDLE_BLOCK34]] ]
+; CHECK-NEXT:    [[IT2_010_PH:%.*]] = phi ptr [ [[BASE]], %[[VECTOR_MEMCHECK]] ], [ [[BASE]], %[[LOOP2_BODY_LR_PH]] ], [ [[TMP11]], %[[MIDDLE_BLOCK34]] ]
+; CHECK-NEXT:    br label %[[LOOP2_BODY:.*]]
+; CHECK:       [[LOOP1_INC]]:
+; CHECK-NEXT:    [[R8:%.*]] = phi i64 [ [[SEL]], %[[LOOP1_INC]] ], [ [[R8_PH]], %[[LOOP1_INC_PREHEADER41]] ]
+; CHECK-NEXT:    [[IT1_07:%.*]] = phi ptr [ [[NEXT_I:%.*]], %[[LOOP1_INC]] ], [ [[IT1_07_PH]], %[[LOOP1_INC_PREHEADER41]] ]
+; CHECK-NEXT:    [[GT:%.*]] = icmp ugt i64 [[N_FR]], [[R8]]
+; CHECK-NEXT:    [[SEL]] = select i1 [[GT]], i64 0, i64 [[R8]]
+; CHECK-NEXT:    [[NEXT_I]] = getelementptr nusw nuw i8, ptr [[IT1_07]], i64 48
+; CHECK-NEXT:    [[NE_I_NOT:%.*]] = icmp eq ptr [[NEXT_I]], @end
+; CHECK-NEXT:    br i1 [[NE_I_NOT]], label %[[LOOP2_BODY_LR_PH]], label %[[LOOP1_INC]], !llvm.loop [[LOOP9:![0-9]+]]
+; CHECK:       [[RET]]:
+; CHECK-NEXT:    [[RES:%.*]] = phi i64 [ [[TMP0]], %[[ENTRY]] ], [ [[TMP26]], %[[MIDDLE_BLOCK34]] ], [ [[RES11:%.*]], %[[LOOP2_INC:.*]] ]
+; CHECK-NEXT:    ret i64 [[RES]]
+; CHECK:       [[LOOP2_BODY]]:
+; CHECK-NEXT:    [[RES12:%.*]] = phi i64 [ [[RES11]], %[[LOOP2_INC]] ], [ [[RES12_PH]], %[[LOOP2_BODY_PREHEADER]] ]
+; CHECK-NEXT:    [[IT2_010:%.*]] = phi ptr [ [[NEXT_I5:%.*]], %[[LOOP2_INC]] ], [ [[IT2_010_PH]], %[[LOOP2_BODY_PREHEADER]] ]
+; CHECK-NEXT:    [[CMP_VAL_I:%.*]] = load i64, ptr [[CMP]], align 8
+; CHECK-NEXT:    [[CMP_F_I:%.*]] = uitofp i64 [[CMP_VAL_I]] to double
+; CHECK-NEXT:    [[PROD_I:%.*]] = fmul nnan double [[TMP9]], [[CMP_F_I]]
+; CHECK-NEXT:    [[OLE_I:%.*]] = fcmp ugt double [[PROD_I]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[OLE_I]], label %[[CLEAR:.*]], label %[[LOOP2_INC]]
+; CHECK:       [[CLEAR]]:
+; CHECK-NEXT:    store i64 0, ptr [[BASE]], align 8
+; CHECK-NEXT:    br label %[[LOOP2_INC]]
+; CHECK:       [[LOOP2_INC]]:
+; CHECK-NEXT:    [[RES11]] = phi i64 [ 0, %[[CLEAR]] ], [ [[RES12]], %[[LOOP2_BODY]] ]
+; CHECK-NEXT:    [[NEXT_I5]] = getelementptr nusw nuw i8, ptr [[IT2_010]], i64 48
+; CHECK-NEXT:    [[NE_I3_NOT:%.*]] = icmp eq ptr [[NEXT_I5]], @end
+; CHECK-NEXT:    br i1 [[NE_I3_NOT]], label %[[RET]], label %[[LOOP2_BODY]], !llvm.loop [[LOOP10:![0-9]+]]
+;
+entry:
+  %it1 = alloca ptr, align 8
+  %lam = alloca i64, align 8
+  %it2 = alloca ptr, align 8
+  store ptr %base, ptr %it1, align 8
+  store ptr %base, ptr %base, align 8
+  br label %loop1
+
+loop1:
+  %r = phi i64 [ 1, %entry ], [ %sel, %loop1.inc ]
+  %ne1 = call i1 @iter_ne(ptr %it1)
+  br i1 %ne1, label %loop1.inc, label %between
+
+loop1.inc:
+  %gt = icmp ugt i64 %n, %r
+  %sel = select i1 %gt, i64 0, i64 %r
+  %adv1 = call ptr @iter_inc(ptr %it1)
+  br label %loop1
+
+between:
+  store i64 %r, ptr %lam, align 8
+  store ptr %base, ptr %it2, align 8
+  br label %loop2
+
+loop2:
+  %ne2 = call i1 @iter_ne(ptr %it2)
+  br i1 %ne2, label %loop2.body, label %ret
+
+ret:
+  %res = load i64, ptr %base, align 8
+  ret i64 %res
+
+loop2.body:
+  %pred = call i1 @lambda(ptr %lam, ptr %cmp)
+  br i1 %pred, label %loop2.inc, label %clear
+
+clear:
+  store i64 0, ptr %base, align 8
+  br label %loop2.inc
+
+loop2.inc:
+  %adv2 = call ptr @iter_inc(ptr %it2)
+  br label %loop2
+}
+
+define i1 @iter_ne(ptr %it) {
+; CHECK-LABEL: define i1 @iter_ne(
+; CHECK-SAME: ptr nofree readonly captures(none) [[IT:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+; CHECK-NEXT:    [[CUR:%.*]] = load ptr, ptr [[IT]], align 8
+; CHECK-NEXT:    [[NE:%.*]] = icmp ne ptr [[CUR]], @end
+; CHECK-NEXT:    ret i1 [[NE]]
+;
+  %cur = load ptr, ptr %it, align 8
+  %ne = icmp ne ptr %cur, @end
+  ret i1 %ne
+}
+
+define ptr @iter_inc(ptr %it) {
+; CHECK-LABEL: define noalias noundef ptr @iter_inc(
+; CHECK-SAME: ptr nofree captures(none) [[IT:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
+; CHECK-NEXT:    [[CUR:%.*]] = load ptr, ptr [[IT]], align 8
+; CHECK-NEXT:    [[NEXT:%.*]] = getelementptr nusw nuw i8, ptr [[CUR]], i64 48
+; CHECK-NEXT:    store ptr [[NEXT]], ptr [[IT]], align 8
+; CHECK-NEXT:    ret ptr null
+;
+  %cur = load ptr, ptr %it, align 8
+  %next = getelementptr nusw i8, ptr %cur, i64 48
+  store ptr %next, ptr %it, align 8
+  ret ptr null
+}
+
+define i1 @lambda(ptr %lam, ptr %cmp) {
+; CHECK-LABEL: define i1 @lambda(
+; CHECK-SAME: ptr nofree readonly captures(none) [[LAM:%.*]], ptr nofree readonly captures(none) [[CMP:%.*]]) local_unnamed_addr #[[ATTR2]] {
+; CHECK-NEXT:    [[CMP_VAL:%.*]] = load i64, ptr [[CMP]], align 8
+; CHECK-NEXT:    [[CMP_F:%.*]] = uitofp i64 [[CMP_VAL]] to double
+; CHECK-NEXT:    [[LAM_VAL:%.*]] = load i64, ptr [[LAM]], align 8
+; CHECK-NEXT:    [[LAM_F:%.*]] = uitofp i64 [[LAM_VAL]] to double
+; CHECK-NEXT:    [[PROD:%.*]] = fmul nnan double [[CMP_F]], [[LAM_F]]
+; CHECK-NEXT:    [[OLE:%.*]] = fcmp ole double [[PROD]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[OLE]]
+;
+  %cmp.val = load i64, ptr %cmp, align 8
+  %cmp.f = uitofp i64 %cmp.val to double
+  %lam.val = load i64, ptr %lam, align 8
+  %lam.f = uitofp i64 %lam.val to double
+  %prod = fmul double %cmp.f, %lam.f
+  %ole = fcmp ole double %prod, 0.000000e+00
+  ret i1 %ole
+}
+
+define ptr @gep_base_cancel(ptr %p, ptr %end, ptr noalias %a) {
+; CHECK-LABEL: define noundef ptr @gep_base_cancel(
+; CHECK-SAME: ptr nofree readonly captures(address) [[P:%.*]], ptr nofree readnone captures(address) [[END:%.*]], ptr noalias nofree captures(address, ret: address, provenance) [[A:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[IN_BOUNDS6:%.*]] = icmp ult ptr [[P]], [[END]]
+; CHECK-NEXT:    br i1 [[IN_BOUNDS6]], label %[[BODY_PREHEADER:.*]], label %[[COMMON_RET:.*]]
+; CHECK:       [[BODY_PREHEADER]]:
+; CHECK-NEXT:    [[END15:%.*]] = ptrtoint ptr [[END]] to i64
+; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr inttoptr (i64 -1 to ptr), i64 [[END15]]
+; CHECK-NEXT:    [[CHAR_PEEL:%.*]] = load i8, ptr [[P]], align 1
+; CHECK-NEXT:    switch i8 [[CHAR_PEEL]], label %[[TRAP:.*]] [
+; CHECK-NEXT:      i8 33, label %[[ADVANCE_PEEL:.*]]
+; CHECK-NEXT:      i8 36, label %[[ADVANCE_PEEL]]
+; CHECK-NEXT:    ]
+; CHECK:       [[ADVANCE_PEEL]]:
+; CHECK-NEXT:    [[EXITCOND_PEEL_NOT:%.*]] = icmp eq ptr [[P]], [[SCEVGEP]]
+; CHECK-NEXT:    br i1 [[EXITCOND_PEEL_NOT]], label %[[COMMON_RET]], label %[[BODY:.*]]
+; CHECK:       [[COMMON_RET]]:
+; CHECK-NEXT:    [[RET_KNOWN_TR3:%.*]] = phi ptr [ [[A_TR9_LCSSA:%.*]], %[[TRAP]] ], [ null, %[[ENTRY]] ], [ null, %[[ADVANCE_PEEL]] ], [ null, %[[ADVANCE:.*]] ]
+; CHECK-NEXT:    ret ptr [[RET_KNOWN_TR3]]
+; CHECK:       [[BODY]]:
+; CHECK-NEXT:    [[P_TR7_PN:%.*]] = phi ptr [ [[P_TR7:%.*]], %[[ADVANCE]] ], [ [[P]], %[[ADVANCE_PEEL]] ]
+; CHECK-NEXT:    [[P_TR7]] = getelementptr i8, ptr [[P_TR7_PN]], i64 1
+; CHECK-NEXT:    [[CHAR:%.*]] = load i8, ptr [[P_TR7]], align 1
+; CHECK-NEXT:    switch i8 [[CHAR]], label %[[TRAP]] [
+; CHECK-NEXT:      i8 33, label %[[ADVANCE]]
+; CHECK-NEXT:      i8 36, label %[[ADVANCE]]
+; CHECK-NEXT:    ]
+; CHECK:       [[ADVANCE]]:
+; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq ptr [[P_TR7]], [[SCEVGEP]]
+; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[COMMON_RET]], label %[[BODY]], !llvm.loop [[LOOP11:![0-9]+]]
+; CHECK:       [[TRAP]]:
+; CHECK-NEXT:    [[A_TR9_LCSSA]] = phi ptr [ [[A]], %[[BODY_PREHEADER]] ], [ null, %[[BODY]] ]
+; CHECK-NEXT:    store volatile i32 0, ptr [[A_TR9_LCSSA]], align 4
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  %in.bounds = icmp ult ptr %p, %end
+  br i1 %in.bounds, label %body, label %common.ret
+
+common.ret:
+  %ret = phi ptr [ %a, %trap ], [ null, %recurse ], [ null, %advance ], [ null, %entry ]
+  ret ptr %ret
+
+body:
+  %char = load i8, ptr %p, align 1
+  switch i8 %char, label %trap [
+  i8 33, label %advance
+  i8 36, label %advance
+  ]
+
+advance:
+  %p.next = getelementptr i8, ptr %p, i64 1
+  %next.in.bounds = icmp ult ptr %p.next, %end
+  br i1 %next.in.bounds, label %recurse, label %common.ret
+
+recurse:
+  %rec = call ptr @gep_base_cancel(ptr %p.next, ptr %end)
+  br label %common.ret
+
+trap:
+  store volatile i32 0, ptr %a, align 4
+  br label %common.ret
+}


        


More information about the llvm-commits mailing list