[llvm] 7ca0f44 - [indvars] Add tests for countdown style loops w/nonnegative IVs
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 3 10:13:59 PDT 2023
Author: Philip Reames
Date: 2023-11-03T10:13:49-07:00
New Revision: 7ca0f4418a6d385e07d9aff42865c34d3dc2adf7
URL: https://github.com/llvm/llvm-project/commit/7ca0f4418a6d385e07d9aff42865c34d3dc2adf7
DIFF: https://github.com/llvm/llvm-project/commit/7ca0f4418a6d385e07d9aff42865c34d3dc2adf7.diff
LOG: [indvars] Add tests for countdown style loops w/nonnegative IVs
Adding test coverage in advance of upcoming changes. Note that these
tests specifically use unsigned comparisons for the backends, the
signed versions are fairly well handled by existing logic.
Added:
llvm/test/Transforms/IndVarSimplify/widen-nonnegative-countdown.ll
Modified:
Removed:
################################################################################
diff --git a/llvm/test/Transforms/IndVarSimplify/widen-nonnegative-countdown.ll b/llvm/test/Transforms/IndVarSimplify/widen-nonnegative-countdown.ll
new file mode 100644
index 000000000000000..b0392cc6fe2c1ce
--- /dev/null
+++ b/llvm/test/Transforms/IndVarSimplify/widen-nonnegative-countdown.ll
@@ -0,0 +1,891 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -S -passes='indvars' -verify-loop-info -verify-dom-info -verify-scev | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+
+; This file covers proving non-negative IVs for IV widening on common
+; count down loop structures. Count down loops are tricky to prove
+; non-negative for since we canonicalize a sub to add, and loose the
+; sub nuw fact.
+
+; use(a[i]) loops
+; -------------------------------------------------------------------
+
+define void @zext_postinc_constant_start(ptr %A) {
+; CHECK-LABEL: @zext_postinc_constant_start(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1024, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV_NEXT]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ 1024, %entry ], [ %inc.us, %for.body ]
+ %idxprom.us = zext i32 %j.016.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %inc.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+
+define void @zext_preinc_constant_start(ptr %A) {
+; CHECK-LABEL: @zext_preinc_constant_start(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1024, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ 1024, %entry ], [ %inc.us, %for.body ]
+ %idxprom.us = zext i32 %j.016.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %j.016.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+define void @zext_postinc(ptr %A, i32 %start) {
+; CHECK-LABEL: @zext_postinc(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[NONPOS:%.*]] = icmp slt i32 [[START:%.*]], 2
+; CHECK-NEXT: br i1 [[NONPOS]], label [[EXIT:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START]] to i64
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: [[J_016_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[FOR_BODY]] ], [ [[START]], [[FOR_BODY_PREHEADER]] ]
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INC_US]] = add nsw i32 [[J_016_US]], -1
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i32 [[INC_US]], 6
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %nonpos = icmp slt i32 %start, 2
+ br i1 %nonpos, label %exit, label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ %start, %entry ], [ %inc.us, %for.body ]
+ %idxprom.us = zext i32 %j.016.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %inc.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+
+define void @zext_preinc(ptr %A, i32 %start) {
+; CHECK-LABEL: @zext_preinc(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[NONPOS:%.*]] = icmp slt i32 [[START:%.*]], 2
+; CHECK-NEXT: br i1 [[NONPOS]], label [[EXIT:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START]] to i64
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV]], 6
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %nonpos = icmp slt i32 %start, 2
+ br i1 %nonpos, label %exit, label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ %start, %entry ], [ %inc.us, %for.body ]
+ %idxprom.us = zext i32 %j.016.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %j.016.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+define void @sext_postinc_constant_start(ptr %A) {
+; CHECK-LABEL: @sext_postinc_constant_start(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1024, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV_NEXT]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ 1024, %entry ], [ %inc.us, %for.body ]
+ %idxprom.us = sext i32 %j.016.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %inc.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+
+define void @sext_preinc_constant_start(ptr %A) {
+; CHECK-LABEL: @sext_preinc_constant_start(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1024, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ 1024, %entry ], [ %inc.us, %for.body ]
+ %idxprom.us = sext i32 %j.016.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %j.016.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+define void @sext_postinc(ptr %A, i32 %start) {
+; CHECK-LABEL: @sext_postinc(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[NONPOS:%.*]] = icmp slt i32 [[START:%.*]], 2
+; CHECK-NEXT: br i1 [[NONPOS]], label [[EXIT:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[START]] to i64
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i32 [[TMP1]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %nonpos = icmp slt i32 %start, 2
+ br i1 %nonpos, label %exit, label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ %start, %entry ], [ %inc.us, %for.body ]
+ %idxprom.us = sext i32 %j.016.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %inc.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+
+define void @sext_preinc(ptr %A, i32 %start) {
+; CHECK-LABEL: @sext_preinc(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[NONPOS:%.*]] = icmp slt i32 [[START:%.*]], 2
+; CHECK-NEXT: br i1 [[NONPOS]], label [[EXIT:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[START]] to i64
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i32 [[TMP1]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %nonpos = icmp slt i32 %start, 2
+ br i1 %nonpos, label %exit, label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ %start, %entry ], [ %inc.us, %for.body ]
+ %idxprom.us = sext i32 %j.016.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %j.016.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+; use(a[i + 1]) loops
+; -------------------------------------------------------------------
+
+define void @zext_postinc_constant_start_offset_constant_one(ptr %A) {
+; CHECK-LABEL: @zext_postinc_constant_start_offset_constant_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1024, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP0]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV_NEXT]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ 1024, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, 1
+ %idxprom.us = zext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %inc.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+
+define void @zext_preinc_constant_start_offset_constant_one(ptr %A) {
+; CHECK-LABEL: @zext_preinc_constant_start_offset_constant_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1024, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP0]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ 1024, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, 1
+ %idxprom.us = zext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %j.016.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+define void @zext_postinc_offset_constant_one(ptr %A, i32 %start) {
+; CHECK-LABEL: @zext_postinc_offset_constant_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[NONPOS:%.*]] = icmp slt i32 [[START:%.*]], 2
+; CHECK-NEXT: br i1 [[NONPOS]], label [[EXIT:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START]] to i64
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: [[J_016_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[FOR_BODY]] ], [ [[START]], [[FOR_BODY_PREHEADER]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32
+; CHECK-NEXT: [[ADD_US:%.*]] = add i32 [[TMP1]], 1
+; CHECK-NEXT: [[IDXPROM_US:%.*]] = zext i32 [[ADD_US]] to i64
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INC_US]] = add nsw i32 [[J_016_US]], -1
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i32 [[INC_US]], 6
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %nonpos = icmp slt i32 %start, 2
+ br i1 %nonpos, label %exit, label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ %start, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, 1
+ %idxprom.us = zext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %inc.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+
+define void @zext_preinc_offset_constant_one(ptr %A, i32 %start) {
+; CHECK-LABEL: @zext_preinc_offset_constant_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[NONPOS:%.*]] = icmp slt i32 [[START:%.*]], 2
+; CHECK-NEXT: br i1 [[NONPOS]], label [[EXIT:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START]] to i64
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32
+; CHECK-NEXT: [[ADD_US:%.*]] = add i32 [[TMP1]], 1
+; CHECK-NEXT: [[IDXPROM_US:%.*]] = zext i32 [[ADD_US]] to i64
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV]], 6
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %nonpos = icmp slt i32 %start, 2
+ br i1 %nonpos, label %exit, label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ %start, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, 1
+ %idxprom.us = zext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %j.016.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+define void @sext_postinc_constant_start_offset_constant_one(ptr %A) {
+; CHECK-LABEL: @sext_postinc_constant_start_offset_constant_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1024, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP0]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV_NEXT]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ 1024, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, 1
+ %idxprom.us = sext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %inc.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+
+define void @sext_preinc_constant_start_offset_constant_one(ptr %A) {
+; CHECK-LABEL: @sext_preinc_constant_start_offset_constant_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1024, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP0]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ 1024, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, 1
+ %idxprom.us = sext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %j.016.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+define void @sext_postinc_offset_constant_one(ptr %A, i32 %start) {
+; CHECK-LABEL: @sext_postinc_offset_constant_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[NONPOS:%.*]] = icmp slt i32 [[START:%.*]], 2
+; CHECK-NEXT: br i1 [[NONPOS]], label [[EXIT:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[START]] to i64
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32
+; CHECK-NEXT: [[ADD_US:%.*]] = add i32 [[TMP1]], 1
+; CHECK-NEXT: [[IDXPROM_US:%.*]] = sext i32 [[ADD_US]] to i64
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i32 [[TMP2]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %nonpos = icmp slt i32 %start, 2
+ br i1 %nonpos, label %exit, label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ %start, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, 1
+ %idxprom.us = sext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %inc.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+
+define void @sext_preinc_offset_constant_one(ptr %A, i32 %start) {
+; CHECK-LABEL: @sext_preinc_offset_constant_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[NONPOS:%.*]] = icmp slt i32 [[START:%.*]], 2
+; CHECK-NEXT: br i1 [[NONPOS]], label [[EXIT:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[START]] to i64
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32
+; CHECK-NEXT: [[ADD_US:%.*]] = add i32 [[TMP1]], 1
+; CHECK-NEXT: [[IDXPROM_US:%.*]] = sext i32 [[ADD_US]] to i64
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVARS_IV]] to i32
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i32 [[TMP2]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %nonpos = icmp slt i32 %start, 2
+ br i1 %nonpos, label %exit, label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ %start, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, 1
+ %idxprom.us = sext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %j.016.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+; use(a[i - 1]) loops
+; -------------------------------------------------------------------
+
+define void @zext_postinc_constant_start_offset_constant_minus_one(ptr %A) {
+; CHECK-LABEL: @zext_postinc_constant_start_offset_constant_minus_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1024, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV_NEXT]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV_NEXT]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ 1024, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, -1
+ %idxprom.us = zext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %inc.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+
+define void @zext_preinc_constant_start_offset_constant_minus_one(ptr %A) {
+; CHECK-LABEL: @zext_preinc_constant_start_offset_constant_minus_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1024, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV_NEXT]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ 1024, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, -1
+ %idxprom.us = zext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %j.016.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+define void @zext_postinc_offset_constant_minus_one(ptr %A, i32 %start) {
+; CHECK-LABEL: @zext_postinc_offset_constant_minus_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[NONPOS:%.*]] = icmp slt i32 [[START:%.*]], 2
+; CHECK-NEXT: br i1 [[NONPOS]], label [[EXIT:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[J_016_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[FOR_BODY]] ], [ [[START]], [[FOR_BODY_PREHEADER]] ]
+; CHECK-NEXT: [[ADD_US:%.*]] = add i32 [[J_016_US]], -1
+; CHECK-NEXT: [[IDXPROM_US:%.*]] = zext i32 [[ADD_US]] to i64
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INC_US]] = add nsw i32 [[J_016_US]], -1
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i32 [[INC_US]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %nonpos = icmp slt i32 %start, 2
+ br i1 %nonpos, label %exit, label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ %start, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, -1
+ %idxprom.us = zext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %inc.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+
+define void @zext_preinc_offset_constant_minus_one(ptr %A, i32 %start) {
+; CHECK-LABEL: @zext_preinc_offset_constant_minus_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[NONPOS:%.*]] = icmp slt i32 [[START:%.*]], 2
+; CHECK-NEXT: br i1 [[NONPOS]], label [[EXIT:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START]] to i64
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: [[J_016_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[FOR_BODY]] ], [ [[START]], [[FOR_BODY_PREHEADER]] ]
+; CHECK-NEXT: [[ADD_US:%.*]] = add i32 [[J_016_US]], -1
+; CHECK-NEXT: [[IDXPROM_US:%.*]] = zext i32 [[ADD_US]] to i64
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INC_US]] = add nsw i32 [[J_016_US]], -1
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV]], 6
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %nonpos = icmp slt i32 %start, 2
+ br i1 %nonpos, label %exit, label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ %start, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, -1
+ %idxprom.us = zext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %j.016.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+define void @sext_postinc_constant_start_offset_constant_minus_one(ptr %A) {
+; CHECK-LABEL: @sext_postinc_constant_start_offset_constant_minus_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1024, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV_NEXT]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV_NEXT]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ 1024, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, -1
+ %idxprom.us = sext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %inc.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+
+define void @sext_preinc_constant_start_offset_constant_minus_one(ptr %A) {
+; CHECK-LABEL: @sext_preinc_constant_start_offset_constant_minus_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1024, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV_NEXT]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i64 [[INDVARS_IV]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ 1024, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, -1
+ %idxprom.us = sext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %j.016.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+define void @sext_postinc_offset_constant_minus_one(ptr %A, i32 %start) {
+; CHECK-LABEL: @sext_postinc_offset_constant_minus_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[NONPOS:%.*]] = icmp slt i32 [[START:%.*]], 2
+; CHECK-NEXT: br i1 [[NONPOS]], label [[EXIT:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[START]] to i64
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32
+; CHECK-NEXT: [[ADD_US:%.*]] = add i32 [[TMP1]], -1
+; CHECK-NEXT: [[IDXPROM_US:%.*]] = sext i32 [[ADD_US]] to i64
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i32 [[TMP2]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %nonpos = icmp slt i32 %start, 2
+ br i1 %nonpos, label %exit, label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ %start, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, -1
+ %idxprom.us = sext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %inc.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+
+define void @sext_preinc_offset_constant_minus_one(ptr %A, i32 %start) {
+; CHECK-LABEL: @sext_preinc_offset_constant_minus_one(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[NONPOS:%.*]] = icmp slt i32 [[START:%.*]], 2
+; CHECK-NEXT: br i1 [[NONPOS]], label [[EXIT:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[START]] to i64
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32
+; CHECK-NEXT: [[ADD_US:%.*]] = add i32 [[TMP1]], -1
+; CHECK-NEXT: [[IDXPROM_US:%.*]] = sext i32 [[ADD_US]] to i64
+; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
+; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]])
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVARS_IV]] to i32
+; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i32 [[TMP2]], 6
+; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK: exit.loopexit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %nonpos = icmp slt i32 %start, 2
+ br i1 %nonpos, label %exit, label %for.body
+
+for.body:
+ %j.016.us = phi i32 [ %start, %entry ], [ %inc.us, %for.body ]
+ %add.us = add i32 %j.016.us, -1
+ %idxprom.us = sext i32 %add.us to i64
+ %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
+ tail call void @use_ptr(ptr %arrayidx.us)
+ %inc.us = add nsw i32 %j.016.us, -1
+ %cmp2.us = icmp ugt i32 %j.016.us, 6
+ br i1 %cmp2.us, label %for.body, label %exit
+
+exit:
+ ret void
+}
+
+declare dso_local void @use_ptr(ptr %0)
+
+
More information about the llvm-commits
mailing list