Files
clang-p2996/llvm/test/Transforms/IndVarSimplify/widen-nonnegative-countdown.ll
Philip Reames 551c280cfd [indvars] Always fallback to truncation if AddRec widening fails (#70967)
The current code structure results in cases where if a) we can't clone
the IV user (because it's not in our whitelist) or b) can't prove the
SCEV expressions are identical, we'd sometimes leave both the original
unwiddened IV and the partially widdened IV in code. Instead, just
truncate thw wide IV to the use - same as what we'd do if we couldn't
find an addrec to start with.

Noticed this while playing with changing how we produce addrecs. The
current structure results in a very tight interlock between SCEVs
internal capabilities and indvars code.
2023-11-07 07:49:39 -08:00

889 lines
35 KiB
LLVM

; 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:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
; 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 nuw 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: [[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:%.*]] = add nsw i64 [[INDVARS_IV]], -1
; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
; 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_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: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
; 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_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)