| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 | |
| ; RUN: opt -passes=loop-load-elim -S %s | FileCheck %s | |
| ; %stride stride may be poison, if it never executes. | |
| define void @stride_used_conditionally(ptr noalias %a, ptr noalias %b, i64 %stride, i64 %x) { | |
| ; CHECK-LABEL: define void @stride_used_conditionally( | |
| ; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], i64 [[STRIDE:%.*]], i64 [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LOOP_HEADER_LVER_CHECK:.*:]] | |
| ; CHECK-NEXT: [[IDENT_CHECK:%.*]] = icmp ne i64 [[STRIDE]], 1 | |
| ; CHECK-NEXT: br i1 [[IDENT_CHECK]], label %[[LOOP_HEADER_PH_LVER_ORIG:.*]], label %[[LOOP_HEADER_PH:.*]] | |
| ; CHECK: [[LOOP_HEADER_PH_LVER_ORIG]]: | |
| ; CHECK-NEXT: br label %[[LOOP_HEADER_LVER_ORIG:.*]] | |
| ; CHECK: [[LOOP_HEADER_LVER_ORIG]]: | |
| ; CHECK-NEXT: [[IV_LVER_ORIG:%.*]] = phi i64 [ 0, %[[LOOP_HEADER_PH_LVER_ORIG]] ], [ [[IV_NEXT_LVER_ORIG:%.*]], %[[LOOP_LATCH_LVER_ORIG:.*]] ] | |
| ; CHECK-NEXT: [[IV_NEXT_LVER_ORIG]] = add nuw nsw i64 [[IV_LVER_ORIG]], 1 | |
| ; CHECK-NEXT: [[GEP_A_LVER_ORIG:%.*]] = getelementptr i64, ptr [[A]], i64 [[IV_LVER_ORIG]] | |
| ; CHECK-NEXT: [[L_A_LVER_ORIG:%.*]] = load i64, ptr [[GEP_A_LVER_ORIG]], align 8 | |
| ; CHECK-NEXT: [[GEP_A_NEXT_LVER_ORIG:%.*]] = getelementptr i64, ptr [[A]], i64 [[IV_NEXT_LVER_ORIG]] | |
| ; CHECK-NEXT: store i64 [[L_A_LVER_ORIG]], ptr [[GEP_A_NEXT_LVER_ORIG]], align 8 | |
| ; CHECK-NEXT: [[C_LVER_ORIG:%.*]] = icmp sge i64 [[IV_LVER_ORIG]], [[X]] | |
| ; CHECK-NEXT: br i1 [[C_LVER_ORIG]], label %[[THEN_LVER_ORIG:.*]], label %[[LOOP_LATCH_LVER_ORIG]] | |
| ; CHECK: [[THEN_LVER_ORIG]]: | |
| ; CHECK-NEXT: [[IDX_LVER_ORIG:%.*]] = mul i64 [[IV_LVER_ORIG]], [[STRIDE]] | |
| ; CHECK-NEXT: [[GEP_A_IDX_LVER_ORIG:%.*]] = getelementptr i64, ptr [[A]], i64 [[IDX_LVER_ORIG]] | |
| ; CHECK-NEXT: [[L_A_IDX_LVER_ORIG:%.*]] = load i64, ptr [[GEP_A_IDX_LVER_ORIG]], align 8 | |
| ; CHECK-NEXT: [[GEP_B_LVER_ORIG:%.*]] = getelementptr i64, ptr [[B]], i64 [[IV_LVER_ORIG]] | |
| ; CHECK-NEXT: store i64 [[L_A_IDX_LVER_ORIG]], ptr [[GEP_B_LVER_ORIG]], align 8 | |
| ; CHECK-NEXT: br label %[[LOOP_LATCH_LVER_ORIG]] | |
| ; CHECK: [[LOOP_LATCH_LVER_ORIG]]: | |
| ; CHECK-NEXT: [[EC_LVER_ORIG:%.*]] = icmp eq i64 [[IV_NEXT_LVER_ORIG]], 100 | |
| ; CHECK-NEXT: br i1 [[EC_LVER_ORIG]], label %[[EXIT_LOOPEXIT:.*]], label %[[LOOP_HEADER_LVER_ORIG]] | |
| ; CHECK: [[LOOP_HEADER_PH]]: | |
| ; CHECK-NEXT: [[LOAD_INITIAL:%.*]] = load i64, ptr [[A]], align 8 | |
| ; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] | |
| ; CHECK: [[LOOP_HEADER]]: | |
| ; CHECK-NEXT: [[STORE_FORWARDED:%.*]] = phi i64 [ [[LOAD_INITIAL]], %[[LOOP_HEADER_PH]] ], [ [[STORE_FORWARDED]], %[[LOOP_LATCH:.*]] ] | |
| ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[LOOP_HEADER_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH]] ] | |
| ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 | |
| ; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr i64, ptr [[A]], i64 [[IV]] | |
| ; CHECK-NEXT: [[L_A:%.*]] = load i64, ptr [[GEP_A]], align 8 | |
| ; CHECK-NEXT: [[GEP_A_NEXT:%.*]] = getelementptr i64, ptr [[A]], i64 [[IV_NEXT]] | |
| ; CHECK-NEXT: store i64 [[STORE_FORWARDED]], ptr [[GEP_A_NEXT]], align 8 | |
| ; CHECK-NEXT: [[C:%.*]] = icmp sge i64 [[IV]], [[X]] | |
| ; CHECK-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[LOOP_LATCH]] | |
| ; CHECK: [[THEN]]: | |
| ; CHECK-NEXT: [[IDX:%.*]] = mul i64 [[IV]], [[STRIDE]] | |
| ; CHECK-NEXT: [[GEP_A_IDX:%.*]] = getelementptr i64, ptr [[A]], i64 [[IDX]] | |
| ; CHECK-NEXT: [[L_A_IDX:%.*]] = load i64, ptr [[GEP_A_IDX]], align 8 | |
| ; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr i64, ptr [[B]], i64 [[IV]] | |
| ; CHECK-NEXT: store i64 [[L_A_IDX]], ptr [[GEP_B]], align 8 | |
| ; CHECK-NEXT: br label %[[LOOP_LATCH]] | |
| ; CHECK: [[LOOP_LATCH]]: | |
| ; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 100 | |
| ; CHECK-NEXT: br i1 [[EC]], label %[[EXIT_LOOPEXIT1:.*]], label %[[LOOP_HEADER]] | |
| ; CHECK: [[EXIT_LOOPEXIT]]: | |
| ; CHECK-NEXT: br label %[[EXIT:.*]] | |
| ; CHECK: [[EXIT_LOOPEXIT1]]: | |
| ; CHECK-NEXT: br label %[[EXIT]] | |
| ; CHECK: [[EXIT]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| br label %loop.header | |
| loop.header: | |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] | |
| %iv.next = add nuw nsw i64 %iv, 1 | |
| %gep.a = getelementptr i64, ptr %a, i64 %iv | |
| %l.a = load i64, ptr %gep.a, align 8 | |
| %gep.a.next = getelementptr i64, ptr %a, i64 %iv.next | |
| store i64 %l.a, ptr %gep.a.next, align 8 | |
| %c = icmp sge i64 %iv, %x | |
| br i1 %c, label %then, label %loop.latch | |
| then: | |
| %idx = mul i64 %iv, %stride | |
| %gep.a.idx = getelementptr i64, ptr %a, i64 %idx | |
| %l.a.idx = load i64, ptr %gep.a.idx, align 8 | |
| %gep.b = getelementptr i64, ptr %b, i64 %iv | |
| store i64 %l.a.idx, ptr %gep.b, align 8 | |
| br label %loop.latch | |
| loop.latch: | |
| %ec = icmp eq i64 %iv.next, 100 | |
| br i1 %ec, label %exit, label %loop.header | |
| exit: | |
| ret void | |
| } |