When TTI was updated to use an explicit cost, TCK_CodeSize was used although the default implicit cost would have been the hand-wavey cost of size and latency. So, revert back to this behaviour. This is not expected to have (much) impact on targets since most (all?) of them return the same value for SizeAndLatency and CodeSize. When optimising for size, the logic has been changed to query CodeSize costs instead of SizeAndLatency. This patch also adds a testing option in the unroller so that OptSize thresholds can be specified. Differential Revision: https://reviews.llvm.org/D85723
398 lines
18 KiB
LLVM
398 lines
18 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -loop-unroll -unroll-allow-partial -unroll-optsize-threshold=18 -mtriple=thumbv8 -S %s -o - | FileCheck %s --check-prefix=CHECK-V8
|
|
|
|
define void @test_i32_add_optsize(i32* %a, i32* %b, i32* %c) #0 {
|
|
; CHECK-V8-LABEL: @test_i32_add_optsize(
|
|
; CHECK-V8-NEXT: entry:
|
|
; CHECK-V8-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK-V8: loop:
|
|
; CHECK-V8-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[COUNT_1:%.*]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: [[ADDR_A:%.*]] = getelementptr i32, i32* [[A:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[ADDR_B:%.*]] = getelementptr i32, i32* [[B:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[DATA_A:%.*]] = load i32, i32* [[ADDR_A]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B:%.*]] = load i32, i32* [[ADDR_B]], align 4
|
|
; CHECK-V8-NEXT: [[RES:%.*]] = add i32 [[DATA_A]], [[DATA_B]]
|
|
; CHECK-V8-NEXT: [[ADDR_C:%.*]] = getelementptr i32, i32* [[C:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: store i32 [[RES]], i32* [[ADDR_C]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT:%.*]] = add nuw nsw i32 [[IV]], 1
|
|
; CHECK-V8-NEXT: [[ADDR_A_1:%.*]] = getelementptr i32, i32* [[A]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: [[ADDR_B_1:%.*]] = getelementptr i32, i32* [[B]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: [[DATA_A_1:%.*]] = load i32, i32* [[ADDR_A_1]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B_1:%.*]] = load i32, i32* [[ADDR_B_1]], align 4
|
|
; CHECK-V8-NEXT: [[RES_1:%.*]] = add i32 [[DATA_A_1]], [[DATA_B_1]]
|
|
; CHECK-V8-NEXT: [[ADDR_C_1:%.*]] = getelementptr i32, i32* [[C]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: store i32 [[RES_1]], i32* [[ADDR_C_1]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT_1]] = add nuw nsw i32 [[COUNT]], 1
|
|
; CHECK-V8-NEXT: [[END_1:%.*]] = icmp ne i32 [[COUNT_1]], 100
|
|
; CHECK-V8-NEXT: br i1 [[END_1]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK-V8: exit:
|
|
; CHECK-V8-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ 0, %entry ], [ %count, %loop ]
|
|
%addr.a = getelementptr i32, i32* %a, i32 %iv
|
|
%addr.b = getelementptr i32, i32* %b, i32 %iv
|
|
%data.a = load i32, i32* %addr.a
|
|
%data.b = load i32, i32* %addr.b
|
|
%res = add i32 %data.a, %data.b
|
|
%addr.c = getelementptr i32, i32* %c, i32 %iv
|
|
store i32 %res, i32* %addr.c
|
|
%count = add nuw i32 %iv, 1
|
|
%end = icmp ne i32 %count, 100
|
|
br i1 %end, label %loop, label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @test_i32_add_minsize(i32* %a, i32* %b, i32* %c) #1 {
|
|
; CHECK-V8-LABEL: @test_i32_add_minsize(
|
|
; CHECK-V8-NEXT: entry:
|
|
; CHECK-V8-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK-V8: loop:
|
|
; CHECK-V8-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[COUNT_1:%.*]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: [[ADDR_A:%.*]] = getelementptr i32, i32* [[A:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[ADDR_B:%.*]] = getelementptr i32, i32* [[B:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[DATA_A:%.*]] = load i32, i32* [[ADDR_A]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B:%.*]] = load i32, i32* [[ADDR_B]], align 4
|
|
; CHECK-V8-NEXT: [[RES:%.*]] = add i32 [[DATA_A]], [[DATA_B]]
|
|
; CHECK-V8-NEXT: [[ADDR_C:%.*]] = getelementptr i32, i32* [[C:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: store i32 [[RES]], i32* [[ADDR_C]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT:%.*]] = add nuw nsw i32 [[IV]], 1
|
|
; CHECK-V8-NEXT: [[ADDR_A_1:%.*]] = getelementptr i32, i32* [[A]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: [[ADDR_B_1:%.*]] = getelementptr i32, i32* [[B]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: [[DATA_A_1:%.*]] = load i32, i32* [[ADDR_A_1]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B_1:%.*]] = load i32, i32* [[ADDR_B_1]], align 4
|
|
; CHECK-V8-NEXT: [[RES_1:%.*]] = add i32 [[DATA_A_1]], [[DATA_B_1]]
|
|
; CHECK-V8-NEXT: [[ADDR_C_1:%.*]] = getelementptr i32, i32* [[C]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: store i32 [[RES_1]], i32* [[ADDR_C_1]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT_1]] = add nuw nsw i32 [[COUNT]], 1
|
|
; CHECK-V8-NEXT: [[END_1:%.*]] = icmp ne i32 [[COUNT_1]], 100
|
|
; CHECK-V8-NEXT: br i1 [[END_1]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK-V8: exit:
|
|
; CHECK-V8-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ 0, %entry ], [ %count, %loop ]
|
|
%addr.a = getelementptr i32, i32* %a, i32 %iv
|
|
%addr.b = getelementptr i32, i32* %b, i32 %iv
|
|
%data.a = load i32, i32* %addr.a
|
|
%data.b = load i32, i32* %addr.b
|
|
%res = add i32 %data.a, %data.b
|
|
%addr.c = getelementptr i32, i32* %c, i32 %iv
|
|
store i32 %res, i32* %addr.c
|
|
%count = add nuw i32 %iv, 1
|
|
%end = icmp ne i32 %count, 100
|
|
br i1 %end, label %loop, label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @test_i64_add_optsize(i64* %a, i64* %b, i64* %c) #0 {
|
|
; CHECK-V8-LABEL: @test_i64_add_optsize(
|
|
; CHECK-V8-NEXT: entry:
|
|
; CHECK-V8-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK-V8: loop:
|
|
; CHECK-V8-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[COUNT_1:%.*]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: [[ADDR_A:%.*]] = getelementptr i64, i64* [[A:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[ADDR_B:%.*]] = getelementptr i64, i64* [[B:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[DATA_A:%.*]] = load i64, i64* [[ADDR_A]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B:%.*]] = load i64, i64* [[ADDR_B]], align 4
|
|
; CHECK-V8-NEXT: [[RES:%.*]] = add i64 [[DATA_A]], [[DATA_B]]
|
|
; CHECK-V8-NEXT: [[ADDR_C:%.*]] = getelementptr i64, i64* [[C:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: store i64 [[RES]], i64* [[ADDR_C]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT:%.*]] = add nuw nsw i32 [[IV]], 1
|
|
; CHECK-V8-NEXT: [[ADDR_A_1:%.*]] = getelementptr i64, i64* [[A]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: [[ADDR_B_1:%.*]] = getelementptr i64, i64* [[B]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: [[DATA_A_1:%.*]] = load i64, i64* [[ADDR_A_1]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B_1:%.*]] = load i64, i64* [[ADDR_B_1]], align 4
|
|
; CHECK-V8-NEXT: [[RES_1:%.*]] = add i64 [[DATA_A_1]], [[DATA_B_1]]
|
|
; CHECK-V8-NEXT: [[ADDR_C_1:%.*]] = getelementptr i64, i64* [[C]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: store i64 [[RES_1]], i64* [[ADDR_C_1]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT_1]] = add nuw nsw i32 [[COUNT]], 1
|
|
; CHECK-V8-NEXT: [[END_1:%.*]] = icmp ne i32 [[COUNT_1]], 100
|
|
; CHECK-V8-NEXT: br i1 [[END_1]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK-V8: exit:
|
|
; CHECK-V8-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ 0, %entry ], [ %count, %loop ]
|
|
%addr.a = getelementptr i64, i64* %a, i32 %iv
|
|
%addr.b = getelementptr i64, i64* %b, i32 %iv
|
|
%data.a = load i64, i64* %addr.a
|
|
%data.b = load i64, i64* %addr.b
|
|
%res = add i64 %data.a, %data.b
|
|
%addr.c = getelementptr i64, i64* %c, i32 %iv
|
|
store i64 %res, i64* %addr.c
|
|
%count = add nuw i32 %iv, 1
|
|
%end = icmp ne i32 %count, 100
|
|
br i1 %end, label %loop, label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @test_i64_add_minsize(i64* %a, i64* %b, i64* %c) #1 {
|
|
; CHECK-V8-LABEL: @test_i64_add_minsize(
|
|
; CHECK-V8-NEXT: entry:
|
|
; CHECK-V8-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK-V8: loop:
|
|
; CHECK-V8-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[COUNT_1:%.*]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: [[ADDR_A:%.*]] = getelementptr i64, i64* [[A:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[ADDR_B:%.*]] = getelementptr i64, i64* [[B:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[DATA_A:%.*]] = load i64, i64* [[ADDR_A]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B:%.*]] = load i64, i64* [[ADDR_B]], align 4
|
|
; CHECK-V8-NEXT: [[RES:%.*]] = add i64 [[DATA_A]], [[DATA_B]]
|
|
; CHECK-V8-NEXT: [[ADDR_C:%.*]] = getelementptr i64, i64* [[C:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: store i64 [[RES]], i64* [[ADDR_C]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT:%.*]] = add nuw nsw i32 [[IV]], 1
|
|
; CHECK-V8-NEXT: [[ADDR_A_1:%.*]] = getelementptr i64, i64* [[A]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: [[ADDR_B_1:%.*]] = getelementptr i64, i64* [[B]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: [[DATA_A_1:%.*]] = load i64, i64* [[ADDR_A_1]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B_1:%.*]] = load i64, i64* [[ADDR_B_1]], align 4
|
|
; CHECK-V8-NEXT: [[RES_1:%.*]] = add i64 [[DATA_A_1]], [[DATA_B_1]]
|
|
; CHECK-V8-NEXT: [[ADDR_C_1:%.*]] = getelementptr i64, i64* [[C]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: store i64 [[RES_1]], i64* [[ADDR_C_1]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT_1]] = add nuw nsw i32 [[COUNT]], 1
|
|
; CHECK-V8-NEXT: [[END_1:%.*]] = icmp ne i32 [[COUNT_1]], 100
|
|
; CHECK-V8-NEXT: br i1 [[END_1]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK-V8: exit:
|
|
; CHECK-V8-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ 0, %entry ], [ %count, %loop ]
|
|
%addr.a = getelementptr i64, i64* %a, i32 %iv
|
|
%addr.b = getelementptr i64, i64* %b, i32 %iv
|
|
%data.a = load i64, i64* %addr.a
|
|
%data.b = load i64, i64* %addr.b
|
|
%res = add i64 %data.a, %data.b
|
|
%addr.c = getelementptr i64, i64* %c, i32 %iv
|
|
store i64 %res, i64* %addr.c
|
|
%count = add nuw i32 %iv, 1
|
|
%end = icmp ne i32 %count, 100
|
|
br i1 %end, label %loop, label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define i32 @test_i32_select_optsize(i32* %a, i32* %b, i32* %c) #0 {
|
|
; CHECK-V8-LABEL: @test_i32_select_optsize(
|
|
; CHECK-V8-NEXT: entry:
|
|
; CHECK-V8-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK-V8: loop:
|
|
; CHECK-V8-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[COUNT_1:%.*]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ACC_NEXT_1:%.*]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: [[ADDR_A:%.*]] = getelementptr i32, i32* [[A:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[ADDR_B:%.*]] = getelementptr i32, i32* [[B:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[DATA_A:%.*]] = load i32, i32* [[ADDR_A]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B:%.*]] = load i32, i32* [[ADDR_B]], align 4
|
|
; CHECK-V8-NEXT: [[UGT:%.*]] = icmp ugt i32 [[DATA_A]], [[DATA_B]]
|
|
; CHECK-V8-NEXT: [[UMAX:%.*]] = select i1 [[UGT]], i32 [[DATA_A]], i32 [[DATA_B]]
|
|
; CHECK-V8-NEXT: [[ACC_NEXT:%.*]] = add i32 [[UMAX]], [[ACC]]
|
|
; CHECK-V8-NEXT: [[ADDR_C:%.*]] = getelementptr i32, i32* [[C:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: store i32 [[UMAX]], i32* [[ADDR_C]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT:%.*]] = add nuw nsw i32 [[IV]], 1
|
|
; CHECK-V8-NEXT: [[ADDR_A_1:%.*]] = getelementptr i32, i32* [[A]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: [[ADDR_B_1:%.*]] = getelementptr i32, i32* [[B]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: [[DATA_A_1:%.*]] = load i32, i32* [[ADDR_A_1]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B_1:%.*]] = load i32, i32* [[ADDR_B_1]], align 4
|
|
; CHECK-V8-NEXT: [[UGT_1:%.*]] = icmp ugt i32 [[DATA_A_1]], [[DATA_B_1]]
|
|
; CHECK-V8-NEXT: [[UMAX_1:%.*]] = select i1 [[UGT_1]], i32 [[DATA_A_1]], i32 [[DATA_B_1]]
|
|
; CHECK-V8-NEXT: [[ACC_NEXT_1]] = add i32 [[UMAX_1]], [[ACC_NEXT]]
|
|
; CHECK-V8-NEXT: [[ADDR_C_1:%.*]] = getelementptr i32, i32* [[C]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: store i32 [[UMAX_1]], i32* [[ADDR_C_1]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT_1]] = add nuw nsw i32 [[COUNT]], 1
|
|
; CHECK-V8-NEXT: [[END_1:%.*]] = icmp ne i32 [[COUNT_1]], 100
|
|
; CHECK-V8-NEXT: br i1 [[END_1]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK-V8: exit:
|
|
; CHECK-V8-NEXT: [[ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[ACC_NEXT_1]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: ret i32 [[ACC_NEXT_LCSSA]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ 0, %entry ], [ %count, %loop ]
|
|
%acc = phi i32 [ 0, %entry], [ %acc.next, %loop ]
|
|
%addr.a = getelementptr i32, i32* %a, i32 %iv
|
|
%addr.b = getelementptr i32, i32* %b, i32 %iv
|
|
%data.a = load i32, i32* %addr.a
|
|
%data.b = load i32, i32* %addr.b
|
|
%ugt = icmp ugt i32 %data.a, %data.b
|
|
%umax = select i1 %ugt, i32 %data.a, i32 %data.b
|
|
%acc.next = add i32 %umax, %acc
|
|
%addr.c = getelementptr i32, i32* %c, i32 %iv
|
|
store i32 %umax, i32* %addr.c
|
|
%count = add nuw i32 %iv, 1
|
|
%end = icmp ne i32 %count, 100
|
|
br i1 %end, label %loop, label %exit
|
|
|
|
exit:
|
|
ret i32 %acc.next
|
|
}
|
|
|
|
define i32 @test_i32_select_minsize(i32* %a, i32* %b, i32* %c) #1 {
|
|
; CHECK-V8-LABEL: @test_i32_select_minsize(
|
|
; CHECK-V8-NEXT: entry:
|
|
; CHECK-V8-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK-V8: loop:
|
|
; CHECK-V8-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[COUNT_1:%.*]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ACC_NEXT_1:%.*]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: [[ADDR_A:%.*]] = getelementptr i32, i32* [[A:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[ADDR_B:%.*]] = getelementptr i32, i32* [[B:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[DATA_A:%.*]] = load i32, i32* [[ADDR_A]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B:%.*]] = load i32, i32* [[ADDR_B]], align 4
|
|
; CHECK-V8-NEXT: [[UGT:%.*]] = icmp ugt i32 [[DATA_A]], [[DATA_B]]
|
|
; CHECK-V8-NEXT: [[UMAX:%.*]] = select i1 [[UGT]], i32 [[DATA_A]], i32 [[DATA_B]]
|
|
; CHECK-V8-NEXT: [[ACC_NEXT:%.*]] = add i32 [[UMAX]], [[ACC]]
|
|
; CHECK-V8-NEXT: [[ADDR_C:%.*]] = getelementptr i32, i32* [[C:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: store i32 [[UMAX]], i32* [[ADDR_C]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT:%.*]] = add nuw nsw i32 [[IV]], 1
|
|
; CHECK-V8-NEXT: [[ADDR_A_1:%.*]] = getelementptr i32, i32* [[A]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: [[ADDR_B_1:%.*]] = getelementptr i32, i32* [[B]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: [[DATA_A_1:%.*]] = load i32, i32* [[ADDR_A_1]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B_1:%.*]] = load i32, i32* [[ADDR_B_1]], align 4
|
|
; CHECK-V8-NEXT: [[UGT_1:%.*]] = icmp ugt i32 [[DATA_A_1]], [[DATA_B_1]]
|
|
; CHECK-V8-NEXT: [[UMAX_1:%.*]] = select i1 [[UGT_1]], i32 [[DATA_A_1]], i32 [[DATA_B_1]]
|
|
; CHECK-V8-NEXT: [[ACC_NEXT_1]] = add i32 [[UMAX_1]], [[ACC_NEXT]]
|
|
; CHECK-V8-NEXT: [[ADDR_C_1:%.*]] = getelementptr i32, i32* [[C]], i32 [[COUNT]]
|
|
; CHECK-V8-NEXT: store i32 [[UMAX_1]], i32* [[ADDR_C_1]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT_1]] = add nuw nsw i32 [[COUNT]], 1
|
|
; CHECK-V8-NEXT: [[END_1:%.*]] = icmp ne i32 [[COUNT_1]], 100
|
|
; CHECK-V8-NEXT: br i1 [[END_1]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK-V8: exit:
|
|
; CHECK-V8-NEXT: [[ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[ACC_NEXT_1]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: ret i32 [[ACC_NEXT_LCSSA]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ 0, %entry ], [ %count, %loop ]
|
|
%acc = phi i32 [ 0, %entry], [ %acc.next, %loop ]
|
|
%addr.a = getelementptr i32, i32* %a, i32 %iv
|
|
%addr.b = getelementptr i32, i32* %b, i32 %iv
|
|
%data.a = load i32, i32* %addr.a
|
|
%data.b = load i32, i32* %addr.b
|
|
%ugt = icmp ugt i32 %data.a, %data.b
|
|
%umax = select i1 %ugt, i32 %data.a, i32 %data.b
|
|
%acc.next = add i32 %umax, %acc
|
|
%addr.c = getelementptr i32, i32* %c, i32 %iv
|
|
store i32 %umax, i32* %addr.c
|
|
%count = add nuw i32 %iv, 1
|
|
%end = icmp ne i32 %count, 100
|
|
br i1 %end, label %loop, label %exit
|
|
|
|
exit:
|
|
ret i32 %acc.next
|
|
}
|
|
|
|
define i64 @test_i64_select_optsize(i64* %a, i64* %b, i64* %c) #0 {
|
|
; CHECK-V8-LABEL: @test_i64_select_optsize(
|
|
; CHECK-V8-NEXT: entry:
|
|
; CHECK-V8-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK-V8: loop:
|
|
; CHECK-V8-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[COUNT:%.*]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: [[ACC:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[ACC_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: [[ADDR_A:%.*]] = getelementptr i64, i64* [[A:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[ADDR_B:%.*]] = getelementptr i64, i64* [[B:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[DATA_A:%.*]] = load i64, i64* [[ADDR_A]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B:%.*]] = load i64, i64* [[ADDR_B]], align 4
|
|
; CHECK-V8-NEXT: [[UGT:%.*]] = icmp ugt i64 [[DATA_A]], [[DATA_B]]
|
|
; CHECK-V8-NEXT: [[UMAX:%.*]] = select i1 [[UGT]], i64 [[DATA_A]], i64 [[DATA_B]]
|
|
; CHECK-V8-NEXT: [[ACC_NEXT]] = add i64 [[UMAX]], [[ACC]]
|
|
; CHECK-V8-NEXT: [[ADDR_C:%.*]] = getelementptr i64, i64* [[C:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: store i64 [[UMAX]], i64* [[ADDR_C]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT]] = add nuw i32 [[IV]], 1
|
|
; CHECK-V8-NEXT: [[END:%.*]] = icmp ne i32 [[COUNT]], 100
|
|
; CHECK-V8-NEXT: br i1 [[END]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK-V8: exit:
|
|
; CHECK-V8-NEXT: [[ACC_NEXT_LCSSA:%.*]] = phi i64 [ [[ACC_NEXT]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: ret i64 [[ACC_NEXT_LCSSA]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ 0, %entry ], [ %count, %loop ]
|
|
%acc = phi i64 [ 0, %entry], [ %acc.next, %loop ]
|
|
%addr.a = getelementptr i64, i64* %a, i32 %iv
|
|
%addr.b = getelementptr i64, i64* %b, i32 %iv
|
|
%data.a = load i64, i64* %addr.a
|
|
%data.b = load i64, i64* %addr.b
|
|
%ugt = icmp ugt i64 %data.a, %data.b
|
|
%umax = select i1 %ugt, i64 %data.a, i64 %data.b
|
|
%acc.next = add i64 %umax, %acc
|
|
%addr.c = getelementptr i64, i64* %c, i32 %iv
|
|
store i64 %umax, i64* %addr.c
|
|
%count = add nuw i32 %iv, 1
|
|
%end = icmp ne i32 %count, 100
|
|
br i1 %end, label %loop, label %exit
|
|
|
|
exit:
|
|
ret i64 %acc.next
|
|
}
|
|
|
|
define i64 @test_i64_select_minsize(i64* %a, i64* %b, i64* %c) #1 {
|
|
; CHECK-V8-LABEL: @test_i64_select_minsize(
|
|
; CHECK-V8-NEXT: entry:
|
|
; CHECK-V8-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK-V8: loop:
|
|
; CHECK-V8-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[COUNT:%.*]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: [[ACC:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[ACC_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: [[ADDR_A:%.*]] = getelementptr i64, i64* [[A:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[ADDR_B:%.*]] = getelementptr i64, i64* [[B:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: [[DATA_A:%.*]] = load i64, i64* [[ADDR_A]], align 4
|
|
; CHECK-V8-NEXT: [[DATA_B:%.*]] = load i64, i64* [[ADDR_B]], align 4
|
|
; CHECK-V8-NEXT: [[UGT:%.*]] = icmp ugt i64 [[DATA_A]], [[DATA_B]]
|
|
; CHECK-V8-NEXT: [[UMAX:%.*]] = select i1 [[UGT]], i64 [[DATA_A]], i64 [[DATA_B]]
|
|
; CHECK-V8-NEXT: [[ACC_NEXT]] = add i64 [[UMAX]], [[ACC]]
|
|
; CHECK-V8-NEXT: [[ADDR_C:%.*]] = getelementptr i64, i64* [[C:%.*]], i32 [[IV]]
|
|
; CHECK-V8-NEXT: store i64 [[UMAX]], i64* [[ADDR_C]], align 4
|
|
; CHECK-V8-NEXT: [[COUNT]] = add nuw i32 [[IV]], 1
|
|
; CHECK-V8-NEXT: [[END:%.*]] = icmp ne i32 [[COUNT]], 100
|
|
; CHECK-V8-NEXT: br i1 [[END]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK-V8: exit:
|
|
; CHECK-V8-NEXT: [[ACC_NEXT_LCSSA:%.*]] = phi i64 [ [[ACC_NEXT]], [[LOOP]] ]
|
|
; CHECK-V8-NEXT: ret i64 [[ACC_NEXT_LCSSA]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ 0, %entry ], [ %count, %loop ]
|
|
%acc = phi i64 [ 0, %entry], [ %acc.next, %loop ]
|
|
%addr.a = getelementptr i64, i64* %a, i32 %iv
|
|
%addr.b = getelementptr i64, i64* %b, i32 %iv
|
|
%data.a = load i64, i64* %addr.a
|
|
%data.b = load i64, i64* %addr.b
|
|
%ugt = icmp ugt i64 %data.a, %data.b
|
|
%umax = select i1 %ugt, i64 %data.a, i64 %data.b
|
|
%acc.next = add i64 %umax, %acc
|
|
%addr.c = getelementptr i64, i64* %c, i32 %iv
|
|
store i64 %umax, i64* %addr.c
|
|
%count = add nuw i32 %iv, 1
|
|
%end = icmp ne i32 %count, 100
|
|
br i1 %end, label %loop, label %exit
|
|
|
|
exit:
|
|
ret i64 %acc.next
|
|
}
|
|
|
|
attributes #0 = { optsize }
|
|
attributes #1 = { minsize optsize }
|