
For value-accumulating recurrences of kind: ``` %umax.acc = phi i8 [ %umax, %backedge ], [ %a, %entry ] %umax = call i8 @llvm.umax.i8(i8 %umax.acc, i8 %b) ``` The binary intrinsic may be simplified into an intrinsic with init value and the other operand, if the latter is loop-invariant: ``` %umax = call i8 @llvm.umax.i8(i8 %a, i8 %b) ``` Proofs: https://alive2.llvm.org/ce/z/ea2cVC. Fixes: https://github.com/llvm/llvm-project/issues/145875.
385 lines
14 KiB
LLVM
385 lines
14 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
|
|
; RUN: opt -passes=instcombine -S < %s | FileCheck %s
|
|
|
|
define i8 @simple_recurrence_intrinsic_smax(i8 %n, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: define i8 @simple_recurrence_intrinsic_smax(
|
|
; CHECK-SAME: i8 [[N:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 [[B]])
|
|
; CHECK-NEXT: ret i8 [[SMAX]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i8 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%smax.acc = phi i8 [ %smax, %loop ], [ %a, %entry ]
|
|
%smax = call i8 @llvm.smax.i8(i8 %smax.acc, i8 %b)
|
|
%iv.next = add nuw i8 %iv, 1
|
|
%cmp = icmp ult i8 %iv.next, %n
|
|
br i1 %cmp, label %loop, label %exit
|
|
|
|
exit:
|
|
ret i8 %smax
|
|
}
|
|
|
|
define i8 @simple_recurrence_intrinsic_smin(i8 %n, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: define i8 @simple_recurrence_intrinsic_smin(
|
|
; CHECK-SAME: i8 [[N:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[A]], i8 [[B]])
|
|
; CHECK-NEXT: ret i8 [[SMIN]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i8 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%smin.acc = phi i8 [ %smin, %loop ], [ %a, %entry ]
|
|
%smin = call i8 @llvm.smin.i8(i8 %smin.acc, i8 %b)
|
|
%iv.next = add nuw i8 %iv, 1
|
|
%cmp = icmp ult i8 %iv.next, %n
|
|
br i1 %cmp, label %loop, label %exit
|
|
|
|
exit:
|
|
ret i8 %smin
|
|
}
|
|
|
|
define i8 @simple_recurrence_intrinsic_umax(i8 %n, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: define i8 @simple_recurrence_intrinsic_umax(
|
|
; CHECK-SAME: i8 [[N:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: [[UMAX:%.*]] = call i8 @llvm.umax.i8(i8 [[A]], i8 [[B]])
|
|
; CHECK-NEXT: ret i8 [[UMAX]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i8 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%umax.acc = phi i8 [ %umax, %loop ], [ %a, %entry ]
|
|
%umax = call i8 @llvm.umax.i8(i8 %umax.acc, i8 %b)
|
|
%iv.next = add nuw i8 %iv, 1
|
|
%cmp = icmp ult i8 %iv.next, %n
|
|
br i1 %cmp, label %loop, label %exit
|
|
|
|
exit:
|
|
ret i8 %umax
|
|
}
|
|
|
|
define i8 @simple_recurrence_intrinsic_umin(i8 %n, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: define i8 @simple_recurrence_intrinsic_umin(
|
|
; CHECK-SAME: i8 [[N:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: [[UMIN:%.*]] = call i8 @llvm.umin.i8(i8 [[A]], i8 [[B]])
|
|
; CHECK-NEXT: ret i8 [[UMIN]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i8 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%umin.acc = phi i8 [ %umin, %loop ], [ %a, %entry ]
|
|
%umin = call i8 @llvm.umin.i8(i8 %umin.acc, i8 %b)
|
|
%iv.next = add nuw i8 %iv, 1
|
|
%cmp = icmp ult i8 %iv.next, %n
|
|
br i1 %cmp, label %loop, label %exit
|
|
|
|
exit:
|
|
ret i8 %umin
|
|
}
|
|
|
|
define float @simple_recurrence_intrinsic_maxnum(i32 %n, float %a, float %b) {
|
|
; CHECK-LABEL: define float @simple_recurrence_intrinsic_maxnum(
|
|
; CHECK-SAME: i32 [[N:%.*]], float [[A:%.*]], float [[B:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IV_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: [[FMAX:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[B]])
|
|
; CHECK-NEXT: ret float [[FMAX]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%fmax.acc = phi float [ %fmax, %loop ], [ %a, %entry ]
|
|
%fmax = call float @llvm.maxnum.f32(float %fmax.acc, float %b)
|
|
%iv.next = add nuw i32 %iv, 1
|
|
%cmp = icmp ult i32 %iv.next, %n
|
|
br i1 %cmp, label %loop, label %exit
|
|
exit:
|
|
ret float %fmax
|
|
}
|
|
|
|
define float @simple_recurrence_intrinsic_minnum(i32 %n, float %a, float %b) {
|
|
; CHECK-LABEL: define float @simple_recurrence_intrinsic_minnum(
|
|
; CHECK-SAME: i32 [[N:%.*]], float [[A:%.*]], float [[B:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IV_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: [[FMIN:%.*]] = call float @llvm.minnum.f32(float [[A]], float [[B]])
|
|
; CHECK-NEXT: ret float [[FMIN]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%fmin.acc = phi float [ %fmin, %loop ], [ %a, %entry ]
|
|
%fmin = call float @llvm.minnum.f32(float %fmin.acc, float %b)
|
|
%iv.next = add nuw i32 %iv, 1
|
|
%cmp = icmp ult i32 %iv.next, %n
|
|
br i1 %cmp, label %loop, label %exit
|
|
exit:
|
|
ret float %fmin
|
|
}
|
|
|
|
define float @simple_recurrence_intrinsic_maximum(i32 %n, float %a, float %b) {
|
|
; CHECK-LABEL: define float @simple_recurrence_intrinsic_maximum(
|
|
; CHECK-SAME: i32 [[N:%.*]], float [[A:%.*]], float [[B:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IV_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: [[FMAX:%.*]] = call nnan float @llvm.maximum.f32(float [[A]], float [[B]])
|
|
; CHECK-NEXT: ret float [[FMAX]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%fmax.acc = phi float [ %fmax, %loop ], [ %a, %entry ]
|
|
%fmax = call nnan float @llvm.maximum.f32(float %fmax.acc, float %b)
|
|
%iv.next = add nuw i32 %iv, 1
|
|
%cmp = icmp ult i32 %iv.next, %n
|
|
br i1 %cmp, label %loop, label %exit
|
|
exit:
|
|
ret float %fmax
|
|
}
|
|
|
|
define float @simple_recurrence_intrinsic_minimum(i32 %n, float %a, float %b) {
|
|
; CHECK-LABEL: define float @simple_recurrence_intrinsic_minimum(
|
|
; CHECK-SAME: i32 [[N:%.*]], float [[A:%.*]], float [[B:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IV_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: [[FMIN:%.*]] = call nnan float @llvm.minimum.f32(float [[A]], float [[B]])
|
|
; CHECK-NEXT: ret float [[FMIN]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%fmin.acc = phi float [ %fmin, %loop ], [ %a, %entry ]
|
|
%fmin = call nnan float @llvm.minimum.f32(float %fmin.acc, float %b)
|
|
%iv.next = add nuw i32 %iv, 1
|
|
%cmp = icmp ult i32 %iv.next, %n
|
|
br i1 %cmp, label %loop, label %exit
|
|
exit:
|
|
ret float %fmin
|
|
}
|
|
|
|
define float @simple_recurrence_intrinsic_maximumnum(i32 %n, float %a, float %b) {
|
|
; CHECK-LABEL: define float @simple_recurrence_intrinsic_maximumnum(
|
|
; CHECK-SAME: i32 [[N:%.*]], float [[A:%.*]], float [[B:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IV_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: [[FMAX:%.*]] = call nnan float @llvm.maximumnum.f32(float [[A]], float [[B]])
|
|
; CHECK-NEXT: ret float [[FMAX]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%fmax.acc = phi float [ %fmax, %loop ], [ %a, %entry ]
|
|
%fmax = call nnan float @llvm.maximumnum.f32(float %fmax.acc, float %b)
|
|
%iv.next = add nuw i32 %iv, 1
|
|
%cmp = icmp ult i32 %iv.next, %n
|
|
br i1 %cmp, label %loop, label %exit
|
|
exit:
|
|
ret float %fmax
|
|
}
|
|
|
|
define float @simple_recurrence_intrinsic_minimumnum(i32 %n, float %a, float %b) {
|
|
; CHECK-LABEL: define float @simple_recurrence_intrinsic_minimumnum(
|
|
; CHECK-SAME: i32 [[N:%.*]], float [[A:%.*]], float [[B:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IV_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: [[FMIN:%.*]] = call nnan float @llvm.minimumnum.f32(float [[A]], float [[B]])
|
|
; CHECK-NEXT: ret float [[FMIN]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%fmin.acc = phi float [ %fmin, %loop ], [ %a, %entry ]
|
|
%fmin = call nnan float @llvm.minimumnum.f32(float %fmin.acc, float %b)
|
|
%iv.next = add nuw i32 %iv, 1
|
|
%cmp = icmp ult i32 %iv.next, %n
|
|
br i1 %cmp, label %loop, label %exit
|
|
exit:
|
|
ret float %fmin
|
|
}
|
|
|
|
define i8 @simple_recurrence_intrinsic_multiuse_phi(i8 %n, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: define i8 @simple_recurrence_intrinsic_multiuse_phi(
|
|
; CHECK-SAME: i8 [[N:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[UMAX_ACC:%.*]] = phi i8 [ [[UMAX:%.*]], %[[LOOP]] ], [ [[A]], %[[ENTRY]] ]
|
|
; CHECK-NEXT: call void @use(i8 [[UMAX_ACC]])
|
|
; CHECK-NEXT: [[UMAX]] = call i8 @llvm.umax.i8(i8 [[A]], i8 [[B]])
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: ret i8 [[UMAX]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i8 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%umax.acc = phi i8 [ %umax, %loop ], [ %a, %entry ]
|
|
call void @use(i8 %umax.acc)
|
|
%umax = call i8 @llvm.umax.i8(i8 %umax.acc, i8 %b)
|
|
%iv.next = add nuw i8 %iv, 1
|
|
%cmp = icmp ult i8 %iv.next, %n
|
|
br i1 %cmp, label %loop, label %exit
|
|
|
|
exit:
|
|
ret i8 %umax
|
|
}
|
|
|
|
; Negative tests.
|
|
|
|
define i8 @simple_recurrence_intrinsic_uadd_sat(i8 %n, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: define i8 @simple_recurrence_intrinsic_uadd_sat(
|
|
; CHECK-SAME: i8 [[N:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[UADD_SAT_ACC:%.*]] = phi i8 [ [[UADD_SAT:%.*]], %[[LOOP]] ], [ [[A]], %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[UADD_SAT]] = call i8 @llvm.uadd.sat.i8(i8 [[UADD_SAT_ACC]], i8 [[B]])
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: ret i8 [[UADD_SAT]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i8 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%uadd.sat.acc = phi i8 [ %uadd.sat, %loop ], [ %a, %entry ]
|
|
%uadd.sat = call i8 @llvm.uadd.sat.i8(i8 %uadd.sat.acc, i8 %b)
|
|
%iv.next = add nuw i8 %iv, 1
|
|
%cmp = icmp ult i8 %iv.next, %n
|
|
br i1 %cmp, label %loop, label %exit
|
|
|
|
exit:
|
|
ret i8 %uadd.sat
|
|
}
|
|
|
|
define i8 @simple_recurrence_intrinsic_arg_loop_variant(i8 %n, i8 %a) {
|
|
; CHECK-LABEL: define i8 @simple_recurrence_intrinsic_arg_loop_variant(
|
|
; CHECK-SAME: i8 [[N:%.*]], i8 [[A:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*]]:
|
|
; CHECK-NEXT: br label %[[LOOP:.*]]
|
|
; CHECK: [[LOOP]]:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[UMAX_ACC:%.*]] = phi i8 [ [[UMAX:%.*]], %[[LOOP]] ], [ [[A]], %[[ENTRY]] ]
|
|
; CHECK-NEXT: [[B:%.*]] = xor i8 [[IV]], 42
|
|
; CHECK-NEXT: [[UMAX]] = call i8 @llvm.umax.i8(i8 [[UMAX_ACC]], i8 [[B]])
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i8 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: ret i8 [[UMAX]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i8 [ %iv.next, %loop ], [ 0, %entry ]
|
|
%umax.acc = phi i8 [ %umax, %loop ], [ %a, %entry ]
|
|
%b = xor i8 %iv, 42
|
|
%umax = call i8 @llvm.umax.i8(i8 %umax.acc, i8 %b)
|
|
%iv.next = add nuw i8 %iv, 1
|
|
%cmp = icmp ult i8 %iv.next, %n
|
|
br i1 %cmp, label %loop, label %exit
|
|
|
|
exit:
|
|
ret i8 %umax
|
|
}
|
|
|
|
declare void @use(i8)
|