| ; 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" |
| |
| ; Simple case of direct extend of index |
| ; -------------------------------------- |
| |
| define void @sext_no_offset(ptr %A, i32 %M) { |
| ; CHECK-LABEL: @sext_no_offset( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[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 nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %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 nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_no_offset(ptr %A, i32 %M) { |
| ; CHECK-LABEL: @zext_no_offset( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[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 nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %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 nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_nneg_no_offset(ptr %A, i32 %M) { |
| ; CHECK-LABEL: @zext_nneg_no_offset( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[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 nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %idxprom.us = zext nneg 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 nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; Offset with a loop invariant value, various combinations |
| ; -------------------------------------- |
| |
| define void @sext_add_nsw(ptr %A, i32 %offset, i32 %M) { |
| ; CHECK-LABEL: @sext_add_nsw( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[OFFSET:%.*]] to i64 |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], [[TMP0]] |
| ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]] |
| ; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]]) |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %add.us = add nsw i32 %j.016.us, %offset |
| %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 nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @sext_add_nuw(ptr %A, i32 %offset, i32 %M) { |
| ; CHECK-LABEL: @sext_add_nuw( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[OFFSET:%.*]] to i64 |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], [[TMP0]] |
| ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32 |
| ; CHECK-NEXT: [[IDXPROM_US:%.*]] = sext i32 [[TMP2]] 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 nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %add.us = add nuw i32 %j.016.us, %offset |
| %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 nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @sext_add_noflags(ptr %A, i32 %offset, i32 %M) { |
| ; CHECK-LABEL: @sext_add_noflags( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[INDVARS_IV]] to i32 |
| ; CHECK-NEXT: [[ADD_US:%.*]] = add i32 [[TMP0]], [[OFFSET:%.*]] |
| ; 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 nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %add.us = add i32 %j.016.us, %offset |
| %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 nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_add_nsw(ptr %A, i32 %offset, i32 %M) { |
| ; CHECK-LABEL: @zext_add_nsw( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[OFFSET:%.*]] to i64 |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], [[TMP0]] |
| ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32 |
| ; CHECK-NEXT: [[IDXPROM_US:%.*]] = zext i32 [[TMP2]] 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 nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %add.us = add nsw i32 %j.016.us, %offset |
| %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 nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_add_nuw(ptr %A, i32 %offset, i32 %M) { |
| ; CHECK-LABEL: @zext_add_nuw( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[OFFSET:%.*]] to i64 |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], [[TMP0]] |
| ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]] |
| ; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]]) |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %add.us = add nuw i32 %j.016.us, %offset |
| %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 nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_add_noflags(ptr %A, i32 %offset, i32 %M) { |
| ; CHECK-LABEL: @zext_add_noflags( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[INDVARS_IV]] to i32 |
| ; CHECK-NEXT: [[ADD_US:%.*]] = add i32 [[TMP0]], [[OFFSET:%.*]] |
| ; 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: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %add.us = add i32 %j.016.us, %offset |
| %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 nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_nneg_add_nsw(ptr %A, i32 %offset, i32 %M) { |
| ; CHECK-LABEL: @zext_nneg_add_nsw( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[OFFSET:%.*]] to i64 |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], [[TMP0]] |
| ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]] |
| ; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]]) |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %add.us = add nsw i32 %j.016.us, %offset |
| %idxprom.us = zext nneg 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 nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_nneg_add_nuw(ptr %A, i32 %offset, i32 %M) { |
| ; CHECK-LABEL: @zext_nneg_add_nuw( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[OFFSET:%.*]] to i64 |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], [[TMP0]] |
| ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]] |
| ; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]]) |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %add.us = add nuw i32 %j.016.us, %offset |
| %idxprom.us = zext nneg 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 nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_nneg_add_noflags(ptr %A, i32 %offset, i32 %M) { |
| ; CHECK-LABEL: @zext_nneg_add_noflags( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[INDVARS_IV]] to i32 |
| ; CHECK-NEXT: [[ADD_US:%.*]] = add i32 [[TMP0]], [[OFFSET:%.*]] |
| ; CHECK-NEXT: [[IDXPROM_US:%.*]] = zext nneg 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 nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %add.us = add i32 %j.016.us, %offset |
| %idxprom.us = zext nneg 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 nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; Offset is multiplied by a multiple |
| ; -------------------------------------- |
| |
| define void @sext_mul_nsw(ptr %A, i32 %multiple, i32 %M) { |
| ; CHECK-LABEL: @sext_mul_nsw( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[MULTIPLE:%.*]] to i64 |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP1:%.*]] = mul nsw i64 [[INDVARS_IV]], [[TMP0]] |
| ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]] |
| ; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]]) |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %mul.us = mul nsw i32 %j.016.us, %multiple |
| %idxprom.us = sext i32 %mul.us to i64 |
| %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us |
| tail call void @use_ptr(ptr %arrayidx.us) |
| %inc.us = add nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @sext_mul_nuw(ptr %A, i32 %multiple, i32 %M) { |
| ; CHECK-LABEL: @sext_mul_nuw( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[MULTIPLE:%.*]] to i64 |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], [[TMP0]] |
| ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32 |
| ; CHECK-NEXT: [[IDXPROM_US:%.*]] = sext i32 [[TMP2]] 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 nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %mul.us = mul nuw i32 %j.016.us, %multiple |
| %idxprom.us = sext i32 %mul.us to i64 |
| %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us |
| tail call void @use_ptr(ptr %arrayidx.us) |
| %inc.us = add nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @sext_mul_noflags(ptr %A, i32 %multiple, i32 %M) { |
| ; CHECK-LABEL: @sext_mul_noflags( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[INDVARS_IV]] to i32 |
| ; CHECK-NEXT: [[MUL_US:%.*]] = mul i32 [[TMP0]], [[MULTIPLE:%.*]] |
| ; CHECK-NEXT: [[IDXPROM_US:%.*]] = sext i32 [[MUL_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 nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %mul.us = mul i32 %j.016.us, %multiple |
| %idxprom.us = sext i32 %mul.us to i64 |
| %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us |
| tail call void @use_ptr(ptr %arrayidx.us) |
| %inc.us = add nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_mul_nsw(ptr %A, i32 %multiple, i32 %M) { |
| ; CHECK-LABEL: @zext_mul_nsw( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[MULTIPLE:%.*]] to i64 |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP1:%.*]] = mul nsw i64 [[INDVARS_IV]], [[TMP0]] |
| ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32 |
| ; CHECK-NEXT: [[IDXPROM_US:%.*]] = zext i32 [[TMP2]] 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 nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %mul.us = mul nsw i32 %j.016.us, %multiple |
| %idxprom.us = zext i32 %mul.us to i64 |
| %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us |
| tail call void @use_ptr(ptr %arrayidx.us) |
| %inc.us = add nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_mul_nuw(ptr %A, i32 %multiple, i32 %M) { |
| ; CHECK-LABEL: @zext_mul_nuw( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[MULTIPLE:%.*]] to i64 |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], [[TMP0]] |
| ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]] |
| ; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]]) |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %mul.us = mul nuw i32 %j.016.us, %multiple |
| %idxprom.us = zext i32 %mul.us to i64 |
| %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us |
| tail call void @use_ptr(ptr %arrayidx.us) |
| %inc.us = add nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_mul_noflags(ptr %A, i32 %multiple, i32 %M) { |
| ; CHECK-LABEL: @zext_mul_noflags( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[INDVARS_IV]] to i32 |
| ; CHECK-NEXT: [[MUL_US:%.*]] = mul i32 [[TMP0]], [[MULTIPLE:%.*]] |
| ; CHECK-NEXT: [[IDXPROM_US:%.*]] = zext i32 [[MUL_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 nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %mul.us = mul i32 %j.016.us, %multiple |
| %idxprom.us = zext i32 %mul.us to i64 |
| %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us |
| tail call void @use_ptr(ptr %arrayidx.us) |
| %inc.us = add nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_nneg_mul_nsw(ptr %A, i32 %multiple, i32 %M) { |
| ; CHECK-LABEL: @zext_nneg_mul_nsw( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[MULTIPLE:%.*]] to i64 |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP1:%.*]] = mul nsw i64 [[INDVARS_IV]], [[TMP0]] |
| ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]] |
| ; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]]) |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %mul.us = mul nsw i32 %j.016.us, %multiple |
| %idxprom.us = zext nneg i32 %mul.us to i64 |
| %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us |
| tail call void @use_ptr(ptr %arrayidx.us) |
| %inc.us = add nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_nneg_mul_nuw(ptr %A, i32 %multiple, i32 %M) { |
| ; CHECK-LABEL: @zext_nneg_mul_nuw( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[MULTIPLE:%.*]] to i64 |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], [[TMP0]] |
| ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]] |
| ; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]]) |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %mul.us = mul nuw i32 %j.016.us, %multiple |
| %idxprom.us = zext nneg i32 %mul.us to i64 |
| %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us |
| tail call void @use_ptr(ptr %arrayidx.us) |
| %inc.us = add nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| define void @zext_nneg_mul_noflags(ptr %A, i32 %multiple, i32 %M) { |
| ; CHECK-LABEL: @zext_nneg_mul_noflags( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1) |
| ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[INDVARS_IV]] to i32 |
| ; CHECK-NEXT: [[MUL_US:%.*]] = mul i32 [[TMP0]], [[MULTIPLE:%.*]] |
| ; CHECK-NEXT: [[IDXPROM_US:%.*]] = zext nneg i32 [[MUL_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 nuw nsw i64 [[INDVARS_IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: |
| %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ] |
| %mul.us = mul i32 %j.016.us, %multiple |
| %idxprom.us = zext nneg i32 %mul.us to i64 |
| %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us |
| tail call void @use_ptr(ptr %arrayidx.us) |
| %inc.us = add nuw nsw i32 %j.016.us, 1 |
| %cmp2.us = icmp slt i32 %inc.us, %M |
| br i1 %cmp2.us, label %for.body, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| declare dso_local void @use_ptr(ptr %0) |