| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: opt < %s -S -mtriple=amdgpu-- -passes=loop-unroll | FileCheck %s |
| |
| ; Check that the threshold used for partial unrolling is independent of the |
| ; threshold used for full unrolling. A partial threshold of 30 produces two |
| ; copies of the loop body while the threshold for full unrolling remains zero. |
| |
| define void @partial_unroll_threshold(ptr addrspace(1) %a, ptr addrspace(1) %b) #0 { |
| ; CHECK-LABEL: define void @partial_unroll_threshold( |
| ; CHECK-SAME: ptr addrspace(1) [[A:%.*]], ptr addrspace(1) [[B:%.*]]) #[[ATTR0:[0-9]+]] { |
| ; CHECK-NEXT: [[ENTRY:.*]]: |
| ; CHECK-NEXT: br label %[[PARTIAL_BODY:.*]] |
| ; CHECK: [[PARTIAL_BODY]]: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 1, %[[ENTRY]] ], [ [[IV_NEXT_1:%.*]], %[[PARTIAL_BODY_1:.*]] ] |
| ; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[B]], i64 [[IV]] |
| ; CHECK-NEXT: [[VALUE:%.*]] = load i32, ptr addrspace(1) [[SRC]], align 4 |
| ; CHECK-NEXT: [[INDEX:%.*]] = sext i32 [[VALUE]] to i64 |
| ; CHECK-NEXT: [[DST:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[A]], i64 [[INDEX]] |
| ; CHECK-NEXT: [[STORED:%.*]] = trunc i64 [[IV]] to i32 |
| ; CHECK-NEXT: store i32 [[STORED]], ptr addrspace(1) [[DST]], align 4 |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add nuw nsw i64 [[IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 20 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label %[[EXIT:.*]], label %[[PARTIAL_BODY_1]] |
| ; CHECK: [[PARTIAL_BODY_1]]: |
| ; CHECK-NEXT: [[SRC_1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[B]], i64 [[IV_NEXT]] |
| ; CHECK-NEXT: [[VALUE_1:%.*]] = load i32, ptr addrspace(1) [[SRC_1]], align 4 |
| ; CHECK-NEXT: [[INDEX_1:%.*]] = sext i32 [[VALUE_1]] to i64 |
| ; CHECK-NEXT: [[DST_1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[A]], i64 [[INDEX_1]] |
| ; CHECK-NEXT: [[STORED_1:%.*]] = trunc i64 [[IV_NEXT]] to i32 |
| ; CHECK-NEXT: store i32 [[STORED_1]], ptr addrspace(1) [[DST_1]], align 4 |
| ; CHECK-NEXT: [[IV_NEXT_1]] = add nuw nsw i64 [[IV]], 2 |
| ; CHECK-NEXT: br label %[[PARTIAL_BODY]] |
| ; CHECK: [[EXIT]]: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %partial.body |
| |
| partial.body: ; preds = %entry, %partial.body |
| %iv = phi i64 [ 1, %entry ], [ %iv.next, %partial.body ] |
| %src = getelementptr inbounds i32, ptr addrspace(1) %b, i64 %iv |
| %value = load i32, ptr addrspace(1) %src, align 4 |
| %index = sext i32 %value to i64 |
| %dst = getelementptr inbounds i32, ptr addrspace(1) %a, i64 %index |
| %stored = trunc i64 %iv to i32 |
| store i32 %stored, ptr addrspace(1) %dst, align 4 |
| %iv.next = add nuw nsw i64 %iv, 1 |
| %exitcond = icmp eq i64 %iv.next, 20 |
| br i1 %exitcond, label %exit, label %partial.body |
| |
| exit: ; preds = %partial.body |
| ret void |
| } |
| |
| define void @zero_partial_unroll_threshold(ptr addrspace(1) %a, ptr addrspace(1) %b) #1 { |
| ; CHECK-LABEL: define void @zero_partial_unroll_threshold( |
| ; CHECK-SAME: ptr addrspace(1) [[A:%.*]], ptr addrspace(1) [[B:%.*]]) #[[ATTR1:[0-9]+]] { |
| ; CHECK-NEXT: [[ENTRY:.*]]: |
| ; CHECK-NEXT: br label %[[PARTIAL_BODY:.*]] |
| ; CHECK: [[PARTIAL_BODY]]: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 1, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[PARTIAL_BODY]] ] |
| ; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[B]], i64 [[IV]] |
| ; CHECK-NEXT: [[VALUE:%.*]] = load i32, ptr addrspace(1) [[SRC]], align 4 |
| ; CHECK-NEXT: [[INDEX:%.*]] = sext i32 [[VALUE]] to i64 |
| ; CHECK-NEXT: [[DST:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[A]], i64 [[INDEX]] |
| ; CHECK-NEXT: [[STORED:%.*]] = trunc i64 [[IV]] to i32 |
| ; CHECK-NEXT: store i32 [[STORED]], ptr addrspace(1) [[DST]], align 4 |
| ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 |
| ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 20 |
| ; CHECK-NEXT: br i1 [[EXITCOND]], label %[[EXIT:.*]], label %[[PARTIAL_BODY]] |
| ; CHECK: [[EXIT]]: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %partial.body |
| |
| partial.body: ; preds = %entry, %partial.body |
| %iv = phi i64 [ 1, %entry ], [ %iv.next, %partial.body ] |
| %src = getelementptr inbounds i32, ptr addrspace(1) %b, i64 %iv |
| %value = load i32, ptr addrspace(1) %src, align 4 |
| %index = sext i32 %value to i64 |
| %dst = getelementptr inbounds i32, ptr addrspace(1) %a, i64 %index |
| %stored = trunc i64 %iv to i32 |
| store i32 %stored, ptr addrspace(1) %dst, align 4 |
| %iv.next = add nuw nsw i64 %iv, 1 |
| %exitcond = icmp eq i64 %iv.next, 20 |
| br i1 %exitcond, label %exit, label %partial.body |
| |
| exit: ; preds = %partial.body |
| ret void |
| } |
| |
| attributes #0 = { "amdgpu-unroll-threshold"="0" "amdgpu-partial-unroll-threshold"="30" } |
| attributes #1 = { "amdgpu-unroll-threshold"="0" "amdgpu-partial-unroll-threshold"="0" } |