| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 |
| ; RUN: opt -passes=indvars -S %s | FileCheck %s |
| |
| target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" |
| |
| define i32 @last_loaded_with_or_exit(i32 %n, ptr %arr) mustprogress { |
| ; CHECK-LABEL: define i32 @last_loaded_with_or_exit( |
| ; CHECK-SAME: i32 [[N:%.*]], ptr [[ARR:%.*]]) #[[ATTR0:[0-9]+]] { |
| ; CHECK-NEXT: [[ENTRY:.*]]: |
| ; CHECK-NEXT: br label %[[HEADER:.*]] |
| ; CHECK: [[HEADER]]: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LATCH:.*]] ], [ 0, %[[ENTRY]] ] |
| ; CHECK-NEXT: [[LAST_LOADED:%.*]] = phi i32 [ [[LAST_LOADED_NEXT:%.*]], %[[LATCH]] ], [ 0, %[[ENTRY]] ] |
| ; CHECK-NEXT: [[IV_LT_N:%.*]] = icmp ult i32 [[IV]], [[N]] |
| ; CHECK-NEXT: [[IV_MINUS_ONE:%.*]] = add i32 -1, [[IV]] |
| ; CHECK-NEXT: [[IV_MINUS_ONE_LT_N:%.*]] = icmp ult i32 [[IV_MINUS_ONE]], [[N]] |
| ; CHECK-NEXT: [[STAY:%.*]] = or i1 [[IV_LT_N]], [[IV_MINUS_ONE_LT_N]] |
| ; CHECK-NEXT: br i1 [[STAY]], label %[[BODY:.*]], label %[[EXIT:.*]] |
| ; CHECK: [[BODY]]: |
| ; CHECK-NEXT: [[BODY_IV_MINUS_ONE:%.*]] = add i32 -1, [[IV]] |
| ; CHECK-NEXT: [[BODY_IV_MINUS_ONE_NONNEG:%.*]] = icmp sgt i32 [[BODY_IV_MINUS_ONE]], -1 |
| ; CHECK-NEXT: br i1 [[BODY_IV_MINUS_ONE_NONNEG]], label %[[DO_LOAD:.*]], label %[[LATCH]] |
| ; CHECK: [[DO_LOAD]]: |
| ; CHECK-NEXT: [[IDX:%.*]] = zext nneg i32 [[BODY_IV_MINUS_ONE]] to i64 |
| ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr inbounds i32, ptr [[ARR]], i64 [[IDX]] |
| ; CHECK-NEXT: [[LOADED:%.*]] = load i32, ptr [[ADDR]], align 4 |
| ; CHECK-NEXT: br label %[[LATCH]] |
| ; CHECK: [[LATCH]]: |
| ; CHECK-NEXT: [[LAST_LOADED_NEXT]] = phi i32 [ [[LAST_LOADED]], %[[BODY]] ], [ [[LOADED]], %[[DO_LOAD]] ] |
| ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 |
| ; CHECK-NEXT: br label %[[HEADER]] |
| ; CHECK: [[EXIT]]: |
| ; CHECK-NEXT: [[LAST_LOADED_LCSSA:%.*]] = phi i32 [ [[LAST_LOADED]], %[[HEADER]] ] |
| ; CHECK-NEXT: ret i32 [[LAST_LOADED_LCSSA]] |
| ; |
| entry: |
| br label %header |
| |
| header: |
| %iv = phi i32 [ %iv.next, %latch ], [ 0, %entry ] |
| %last_loaded = phi i32 [ %last_loaded.next, %latch ], [ 0, %entry ] |
| %iv_lt_n = icmp ult i32 %iv, %n |
| %iv_minus_one = add i32 -1, %iv |
| %iv_minus_one_lt_n = icmp ult i32 %iv_minus_one, %n |
| %stay = or i1 %iv_lt_n, %iv_minus_one_lt_n |
| br i1 %stay, label %body, label %exit |
| |
| body: |
| %body_iv_minus_one = add i32 -1, %iv |
| %body_iv_minus_one_nonneg = icmp sgt i32 %body_iv_minus_one, -1 |
| br i1 %body_iv_minus_one_nonneg, label %do_load, label %latch |
| |
| do_load: |
| %idx = zext nneg i32 %body_iv_minus_one to i64 |
| %addr = getelementptr inbounds i32, ptr %arr, i64 %idx |
| %loaded = load i32, ptr %addr |
| br label %latch |
| |
| latch: |
| %last_loaded.next = phi i32 [ %last_loaded, %body ], [ %loaded, %do_load ] |
| %iv.next = add i32 %iv, 1 |
| br label %header |
| |
| exit: |
| ret i32 %last_loaded |
| } |