| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -loop-idiom -mtriple=x86_64 -mcpu=core-avx2 < %s -S | FileCheck %s |
| |
| declare void @escape_inner(i8, i8, i8, i1, i8) |
| declare void @escape_outer(i8, i8, i8, i1, i8) |
| |
| declare i8 @gen.i8() |
| |
| ; Most basic pattern; Note that iff the shift amount is offset, said offsetting |
| ; must not cause an overflow, but `add nsw` is fine. |
| define i8 @p0(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @p0( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i8 @llvm.ctlz.i8(i8 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i8 8, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[TMP0:%.*]] = sub i8 0, [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i8 [[VAL_NUMACTIVEBITS]], [[TMP0]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i8 @llvm.smax.i8(i8 [[VAL_NUMACTIVEBITS_OFFSET]], i8 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i8 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i8 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i8 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i8 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i8 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; `add nuw` is also fine. |
| define i8 @p1(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @p1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i8 @llvm.ctlz.i8(i8 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i8 8, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[TMP0:%.*]] = sub i8 0, [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i8 [[VAL_NUMACTIVEBITS]], [[TMP0]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i8 @llvm.smax.i8(i8 [[VAL_NUMACTIVEBITS_OFFSET]], i8 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i8 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i8 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i8 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i8 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i8 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nuw i8 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nuw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; `sub nsw` is also fine. |
| define i8 @p2(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @p2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i8 @llvm.ctlz.i8(i8 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i8 8, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i8 [[VAL_NUMACTIVEBITS]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i8 @llvm.smax.i8(i8 [[VAL_NUMACTIVEBITS_OFFSET]], i8 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i8 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i8 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i8 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i8 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i8 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = sub nsw i8 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = sub nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; But `sub nuw` is not fine.. |
| define i8 @n3(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n3( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS:%.*]] = sub nuw i8 [[IV]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = sub nuw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; Likewise, plain `sub` is not fine. |
| define i8 @n4(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n4( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS:%.*]] = sub i8 [[IV]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = sub i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; Likewise, plain `add` is not fine. |
| define i8 @n5(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n5( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add i8 [[IV]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; Of course, we don't have to have an offset |
| define i8 @p6(i8 %val, i8 %start) { |
| ; CHECK-LABEL: @p6( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i8 @llvm.ctlz.i8(i8 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i8 8, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nuw nsw i8 [[VAL_NUMACTIVEBITS]], 0 |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i8 @llvm.smax.i8(i8 [[VAL_NUMACTIVEBITS_OFFSET]], i8 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nuw nsw i8 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i8 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i8 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i8 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i8 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL]], [[IV]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[IV]], i8 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[IV_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %val.shifted = lshr i8 %val, %iv |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %iv, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %iv.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| declare void @escape_inner.i7(i7, i7, i7, i1, i7) |
| declare void @escape_outer.i7(i7, i7, i7, i1, i7) |
| |
| ; Other bitwidths are fine also |
| define i7 @p7(i7 %val, i7 %start, i7 %extraoffset) { |
| ; CHECK-LABEL: @p7( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i7 @llvm.ctlz.i7(i7 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i7 7, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[TMP0:%.*]] = sub i7 0, [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i7 [[VAL_NUMACTIVEBITS]], [[TMP0]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i7 @llvm.smax.i7(i7 [[VAL_NUMACTIVEBITS_OFFSET]], i7 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i7 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i7 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i7 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i7 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i7 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i7 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i7 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i7 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i7 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner.i7(i7 [[IV]], i7 [[NBITS]], i7 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i7 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i7 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i7 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i7 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i7 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer.i7(i7 [[IV_RES]], i7 [[NBITS_RES]], i7 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i7 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i7 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i7 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i7 %iv, %extraoffset |
| %val.shifted = lshr i7 %val, %nbits |
| %val.shifted.iszero = icmp eq i7 %val.shifted, 0 |
| %iv.next = add i7 %iv, 1 |
| |
| call void @escape_inner.i7(i7 %iv, i7 %nbits, i7 %val.shifted, i1 %val.shifted.iszero, i7 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i7 [ %iv, %loop ] |
| %nbits.res = phi i7 [ %nbits, %loop ] |
| %val.shifted.res = phi i7 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i7 [ %iv.next, %loop ] |
| |
| call void @escape_outer.i7(i7 %iv.res, i7 %nbits.res, i7 %val.shifted.res, i1 %val.shifted.iszero.res, i7 %iv.next.res) |
| |
| ret i7 %iv.res |
| } |
| |
| ; Step must be 1 |
| define i8 @n8(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n8( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[IV]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 2 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 2 ; not 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; Cmp-br are commutable |
| define i8 @t9(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @t9( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i8 @llvm.ctlz.i8(i8 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i8 8, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[TMP0:%.*]] = sub i8 0, [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i8 [[VAL_NUMACTIVEBITS]], [[TMP0]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i8 @llvm.smax.i8(i8 [[VAL_NUMACTIVEBITS_OFFSET]], i8 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i8 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i8 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i8 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i8 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISNOTZERO:%.*]] = xor i1 [[LOOP_IVCHECK]], true |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i8 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISNOTZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISNOTZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISNOTZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISNOTZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.isnotzero = icmp ne i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.isnotzero, i8 %iv.next) |
| |
| br i1 %val.shifted.isnotzero, label %loop, label %end |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.isnotzero.res = phi i1 [ %val.shifted.isnotzero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.isnotzero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; We want to exit once it becomes zero |
| define i8 @n10(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n10( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[IV]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISNOTZERO:%.*]] = icmp ne i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISNOTZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISNOTZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISNOTZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISNOTZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISNOTZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.isnotzero = icmp ne i8 %val.shifted, 0 ; not eq |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.isnotzero, i8 %iv.next) |
| |
| br i1 %val.shifted.isnotzero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.isnotzero.res = phi i1 [ %val.shifted.isnotzero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.isnotzero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; Once it compares zero, we want to exit, not exit when it compares non-zero |
| define i8 @n11(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n11( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[IV]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[LOOP]], label [[END:%.*]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %loop, label %end ; wrong destinations |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; We must be comparing with 0 |
| define i8 @n12(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n12( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[IV]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 1 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 1 ; not 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; Loop must have a single block. |
| define i8 @n13(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n13( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_END:%.*]] ] |
| ; CHECK-NEXT: br label [[LOOP_END]] |
| ; CHECK: loop.end: |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[IV]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP_END]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP_END]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP_END]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP_END]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP_END]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop.end ] |
| br label %loop.end |
| |
| loop.end: |
| %nbits = add nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop.end ] |
| %nbits.res = phi i8 [ %nbits, %loop.end ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop.end ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop.end ] |
| %iv.next.res = phi i8 [ %iv.next, %loop.end ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; The comparison must have an equality predicate |
| define i8 @n14(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n14( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[IV]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp ult i8 [[VAL_SHIFTED]], 1 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp ult i8 %val.shifted, 1 ; not `==0` |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; offset computation can be commuted |
| define i8 @t15(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @t15( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i8 @llvm.ctlz.i8(i8 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i8 8, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[TMP0:%.*]] = sub i8 0, [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i8 [[VAL_NUMACTIVEBITS]], [[TMP0]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i8 @llvm.smax.i8(i8 [[VAL_NUMACTIVEBITS_OFFSET]], i8 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i8 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i8 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i8 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i8 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i8 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[EXTRAOFFSET]], [[IV]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i8 %extraoffset, %iv ; swapped order |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; But for `sub nsw`, it is not commutable. |
| define i8 @n16(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n16( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS:%.*]] = sub nsw i8 [[EXTRAOFFSET:%.*]], [[IV]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = sub nsw i8 %extraoffset, %iv |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; The offset must be loop-invariant |
| define i8 @n17(i8 %val, i8 %start) { |
| ; CHECK-LABEL: @n17( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[EXTRAOFFSET:%.*]] = call i8 @gen.i8() |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %extraoffset = call i8 @gen.i8() |
| %nbits = add nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; Likewise for `sub nsw`. |
| define i8 @n18(i8 %val, i8 %start) { |
| ; CHECK-LABEL: @n18( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[EXTRAOFFSET:%.*]] = call i8 @gen.i8() |
| ; CHECK-NEXT: [[NBITS:%.*]] = sub nsw i8 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %extraoffset = call i8 @gen.i8() |
| %nbits = sub nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; The "induction variable" must be in the loop header. |
| define i8 @n19(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n19( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP_PREHEADER:%.*]] |
| ; CHECK: loop.preheader: |
| ; CHECK-NEXT: [[NOTIV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ] |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[LOOP_PREHEADER]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[NOTIV]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop.preheader |
| |
| loop.preheader: |
| %notiv = phi i8 [ 0, %entry ] |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %loop.preheader ], [ %iv.next, %loop ] |
| %nbits = add nsw i8 %notiv, %extraoffset ; uses %notiv instead of %iv |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; IV must really be a PHI |
| define i8 @n20(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n20( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = add i8 0, 0 |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[IV]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = add i8 0, 0 ; again not IV |
| %nbits = add nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; The induction should be actually increasing IV |
| define i8 @n21(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n21( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[IV]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL:%.*]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 0, 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 0, 1 ; should be adding to IV |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; We should not just blindly look for add, we should look what IV actually uses. |
| define i8 @n22(i8 %val, i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n22( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i8 @llvm.ctlz.i8(i8 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i8 8, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[TMP0:%.*]] = sub i8 0, [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i8 [[VAL_NUMACTIVEBITS]], [[TMP0]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i8 @llvm.smax.i8(i8 [[VAL_NUMACTIVEBITS_OFFSET]], i8 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i8 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i8 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i8 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i8 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i8 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[NOT_IV_NEXT:%.*]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: [[ALSO_IV_NEXT:%.*]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i8 %iv, %extraoffset |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %not.iv.next = add i8 %iv, 1 ; not used by %iv |
| %iv.next = add i8 %iv, 1 |
| %also.iv.next = add i8 %iv, 1 ; not used by %iv |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| define i8 @n23(i8 %start, i8 %extraoffset) { |
| ; CHECK-LABEL: @n23( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i8 [[IV]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL:%.*]] = call i8 @gen.i8() |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i8 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO:%.*]] = icmp eq i8 [[VAL_SHIFTED]], 0 |
| ; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner(i8 [[IV]], i8 [[NBITS]], i8 [[VAL_SHIFTED]], i1 [[VAL_SHIFTED_ISZERO]], i8 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[VAL_SHIFTED_ISZERO]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i8 [ [[IV]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i8 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i8 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[VAL_SHIFTED_ISZERO]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i8 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer(i8 [[IV_RES]], i8 [[NBITS_RES]], i8 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i8 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i8 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i8 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i8 %iv, %extraoffset |
| %val = call i8 @gen.i8() |
| %val.shifted = lshr i8 %val, %nbits |
| %val.shifted.iszero = icmp eq i8 %val.shifted, 0 |
| %iv.next = add i8 %iv, 1 |
| |
| call void @escape_inner(i8 %iv, i8 %nbits, i8 %val.shifted, i1 %val.shifted.iszero, i8 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i8 [ %iv, %loop ] |
| %nbits.res = phi i8 [ %nbits, %loop ] |
| %val.shifted.res = phi i8 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i8 [ %iv.next, %loop ] |
| |
| call void @escape_outer(i8 %iv.res, i8 %nbits.res, i8 %val.shifted.res, i1 %val.shifted.iszero.res, i8 %iv.next.res) |
| |
| ret i8 %iv.res |
| } |
| |
| ; Tests with some small bit widths |
| declare void @escape_inner.i1(i1, i1, i1, i1, i1) |
| declare void @escape_outer.i1(i1, i1, i1, i1, i1) |
| declare void @escape_inner.i2(i2, i2, i2, i1, i2) |
| declare void @escape_outer.i2(i2, i2, i2, i1, i2) |
| declare void @escape_inner.i3(i3, i3, i3, i1, i3) |
| declare void @escape_outer.i3(i3, i3, i3, i1, i3) |
| |
| define i1 @t24_nooffset_i1(i1 %val, i1 %start) { |
| ; CHECK-LABEL: @t24_nooffset_i1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i1 @llvm.ctlz.i1(i1 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i1 true, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nuw nsw i1 [[VAL_NUMACTIVEBITS]], false |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i1 @llvm.smax.i1(i1 [[VAL_NUMACTIVEBITS_OFFSET]], i1 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nuw nsw i1 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i1 [[LOOP_BACKEDGETAKENCOUNT]], true |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i1 [[LOOP_IV]], true |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i1 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i1 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i1 [[VAL]], [[IV]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i1 [[IV]], true |
| ; CHECK-NEXT: call void @escape_inner.i1(i1 [[IV]], i1 [[IV]], i1 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i1 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i1 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i1 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i1 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer.i1(i1 [[IV_RES]], i1 [[IV_RES]], i1 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i1 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i1 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i1 [ %start, %entry ], [ %iv.next, %loop ] |
| %val.shifted = lshr i1 %val, %iv |
| %val.shifted.iszero = icmp eq i1 %val.shifted, 0 |
| %iv.next = add i1 %iv, 1 |
| |
| call void @escape_inner.i1(i1 %iv, i1 %iv, i1 %val.shifted, i1 %val.shifted.iszero, i1 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i1 [ %iv, %loop ] |
| %val.shifted.res = phi i1 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i1 [ %iv.next, %loop ] |
| |
| call void @escape_outer.i1(i1 %iv.res, i1 %iv.res, i1 %val.shifted.res, i1 %val.shifted.iszero.res, i1 %iv.next.res) |
| |
| ret i1 %iv.res |
| } |
| define i2 @t25_nooffset_i2(i2 %val, i2 %start) { |
| ; CHECK-LABEL: @t25_nooffset_i2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i2 @llvm.ctlz.i2(i2 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw i2 -2, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nuw nsw i2 [[VAL_NUMACTIVEBITS]], 0 |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i2 @llvm.smax.i2(i2 [[VAL_NUMACTIVEBITS_OFFSET]], i2 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nuw nsw i2 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw i2 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i2 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw i2 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i2 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i2 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i2 [[VAL]], [[IV]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i2 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner.i2(i2 [[IV]], i2 [[IV]], i2 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i2 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i2 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i2 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i2 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer.i2(i2 [[IV_RES]], i2 [[IV_RES]], i2 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i2 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i2 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i2 [ %start, %entry ], [ %iv.next, %loop ] |
| %val.shifted = lshr i2 %val, %iv |
| %val.shifted.iszero = icmp eq i2 %val.shifted, 0 |
| %iv.next = add i2 %iv, 1 |
| |
| call void @escape_inner.i2(i2 %iv, i2 %iv, i2 %val.shifted, i1 %val.shifted.iszero, i2 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i2 [ %iv, %loop ] |
| %val.shifted.res = phi i2 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i2 [ %iv.next, %loop ] |
| |
| call void @escape_outer.i2(i2 %iv.res, i2 %iv.res, i2 %val.shifted.res, i1 %val.shifted.iszero.res, i2 %iv.next.res) |
| |
| ret i2 %iv.res |
| } |
| define i3 @t26_nooffset_i3(i3 %val, i3 %start) { |
| ; CHECK-LABEL: @t26_nooffset_i3( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i3 @llvm.ctlz.i3(i3 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i3 3, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nuw nsw i3 [[VAL_NUMACTIVEBITS]], 0 |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i3 @llvm.smax.i3(i3 [[VAL_NUMACTIVEBITS_OFFSET]], i3 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nuw nsw i3 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i3 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i3 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i3 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i3 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i3 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i3 [[VAL]], [[IV]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i3 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner.i3(i3 [[IV]], i3 [[IV]], i3 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i3 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i3 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i3 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i3 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer.i3(i3 [[IV_RES]], i3 [[IV_RES]], i3 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i3 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i3 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i3 [ %start, %entry ], [ %iv.next, %loop ] |
| %val.shifted = lshr i3 %val, %iv |
| %val.shifted.iszero = icmp eq i3 %val.shifted, 0 |
| %iv.next = add i3 %iv, 1 |
| |
| call void @escape_inner.i3(i3 %iv, i3 %iv, i3 %val.shifted, i1 %val.shifted.iszero, i3 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i3 [ %iv, %loop ] |
| %val.shifted.res = phi i3 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i3 [ %iv.next, %loop ] |
| |
| call void @escape_outer.i3(i3 %iv.res, i3 %iv.res, i3 %val.shifted.res, i1 %val.shifted.iszero.res, i3 %iv.next.res) |
| |
| ret i3 %iv.res |
| } |
| |
| define i1 @t27_addnsw_i1(i1 %val, i1 %start, i1 %extraoffset) { |
| ; CHECK-LABEL: @t27_addnsw_i1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i1 @llvm.ctlz.i1(i1 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i1 true, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i1 [[VAL_NUMACTIVEBITS]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i1 @llvm.smax.i1(i1 [[VAL_NUMACTIVEBITS_OFFSET]], i1 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i1 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i1 [[LOOP_BACKEDGETAKENCOUNT]], true |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i1 [[LOOP_IV]], true |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i1 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i1 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i1 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i1 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i1 [[IV]], true |
| ; CHECK-NEXT: call void @escape_inner.i1(i1 [[IV]], i1 [[NBITS]], i1 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i1 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i1 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i1 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i1 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i1 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer.i1(i1 [[IV_RES]], i1 [[NBITS_RES]], i1 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i1 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i1 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i1 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i1 %iv, %extraoffset |
| %val.shifted = lshr i1 %val, %nbits |
| %val.shifted.iszero = icmp eq i1 %val.shifted, 0 |
| %iv.next = add i1 %iv, 1 |
| |
| call void @escape_inner.i1(i1 %iv, i1 %nbits, i1 %val.shifted, i1 %val.shifted.iszero, i1 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i1 [ %iv, %loop ] |
| %nbits.res = phi i1 [ %nbits, %loop ] |
| %val.shifted.res = phi i1 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i1 [ %iv.next, %loop ] |
| |
| call void @escape_outer.i1(i1 %iv.res, i1 %nbits.res, i1 %val.shifted.res, i1 %val.shifted.iszero.res, i1 %iv.next.res) |
| |
| ret i1 %iv.res |
| } |
| define i2 @t28_addnsw_i2(i2 %val, i2 %start, i2 %extraoffset) { |
| ; CHECK-LABEL: @t28_addnsw_i2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i2 @llvm.ctlz.i2(i2 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw i2 -2, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[TMP0:%.*]] = sub i2 0, [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i2 [[VAL_NUMACTIVEBITS]], [[TMP0]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i2 @llvm.smax.i2(i2 [[VAL_NUMACTIVEBITS_OFFSET]], i2 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i2 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw i2 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i2 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw i2 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i2 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i2 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i2 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i2 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i2 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner.i2(i2 [[IV]], i2 [[NBITS]], i2 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i2 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i2 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i2 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i2 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i2 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer.i2(i2 [[IV_RES]], i2 [[NBITS_RES]], i2 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i2 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i2 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i2 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i2 %iv, %extraoffset |
| %val.shifted = lshr i2 %val, %nbits |
| %val.shifted.iszero = icmp eq i2 %val.shifted, 0 |
| %iv.next = add i2 %iv, 1 |
| |
| call void @escape_inner.i2(i2 %iv, i2 %nbits, i2 %val.shifted, i1 %val.shifted.iszero, i2 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i2 [ %iv, %loop ] |
| %nbits.res = phi i2 [ %nbits, %loop ] |
| %val.shifted.res = phi i2 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i2 [ %iv.next, %loop ] |
| |
| call void @escape_outer.i2(i2 %iv.res, i2 %nbits.res, i2 %val.shifted.res, i1 %val.shifted.iszero.res, i2 %iv.next.res) |
| |
| ret i2 %iv.res |
| } |
| define i3 @t29_addnsw_i3(i3 %val, i3 %start, i3 %extraoffset) { |
| ; CHECK-LABEL: @t29_addnsw_i3( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i3 @llvm.ctlz.i3(i3 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i3 3, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[TMP0:%.*]] = sub i3 0, [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i3 [[VAL_NUMACTIVEBITS]], [[TMP0]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i3 @llvm.smax.i3(i3 [[VAL_NUMACTIVEBITS_OFFSET]], i3 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i3 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i3 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i3 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i3 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i3 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i3 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nsw i3 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i3 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i3 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner.i3(i3 [[IV]], i3 [[NBITS]], i3 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i3 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i3 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i3 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i3 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i3 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer.i3(i3 [[IV_RES]], i3 [[NBITS_RES]], i3 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i3 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i3 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i3 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nsw i3 %iv, %extraoffset |
| %val.shifted = lshr i3 %val, %nbits |
| %val.shifted.iszero = icmp eq i3 %val.shifted, 0 |
| %iv.next = add i3 %iv, 1 |
| |
| call void @escape_inner.i3(i3 %iv, i3 %nbits, i3 %val.shifted, i1 %val.shifted.iszero, i3 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i3 [ %iv, %loop ] |
| %nbits.res = phi i3 [ %nbits, %loop ] |
| %val.shifted.res = phi i3 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i3 [ %iv.next, %loop ] |
| |
| call void @escape_outer.i3(i3 %iv.res, i3 %nbits.res, i3 %val.shifted.res, i1 %val.shifted.iszero.res, i3 %iv.next.res) |
| |
| ret i3 %iv.res |
| } |
| |
| define i1 @t30_addnuw_i1(i1 %val, i1 %start, i1 %extraoffset) { |
| ; CHECK-LABEL: @t30_addnuw_i1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i1 @llvm.ctlz.i1(i1 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i1 true, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i1 [[VAL_NUMACTIVEBITS]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i1 @llvm.smax.i1(i1 [[VAL_NUMACTIVEBITS_OFFSET]], i1 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i1 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i1 [[LOOP_BACKEDGETAKENCOUNT]], true |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i1 [[LOOP_IV]], true |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i1 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i1 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nuw i1 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i1 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i1 [[IV]], true |
| ; CHECK-NEXT: call void @escape_inner.i1(i1 [[IV]], i1 [[NBITS]], i1 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i1 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i1 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i1 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i1 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i1 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer.i1(i1 [[IV_RES]], i1 [[NBITS_RES]], i1 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i1 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i1 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i1 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nuw i1 %iv, %extraoffset |
| %val.shifted = lshr i1 %val, %nbits |
| %val.shifted.iszero = icmp eq i1 %val.shifted, 0 |
| %iv.next = add i1 %iv, 1 |
| |
| call void @escape_inner.i1(i1 %iv, i1 %nbits, i1 %val.shifted, i1 %val.shifted.iszero, i1 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i1 [ %iv, %loop ] |
| %nbits.res = phi i1 [ %nbits, %loop ] |
| %val.shifted.res = phi i1 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i1 [ %iv.next, %loop ] |
| |
| call void @escape_outer.i1(i1 %iv.res, i1 %nbits.res, i1 %val.shifted.res, i1 %val.shifted.iszero.res, i1 %iv.next.res) |
| |
| ret i1 %iv.res |
| } |
| define i2 @t31_addnuw_i2(i2 %val, i2 %start, i2 %extraoffset) { |
| ; CHECK-LABEL: @t31_addnuw_i2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i2 @llvm.ctlz.i2(i2 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw i2 -2, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[TMP0:%.*]] = sub i2 0, [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i2 [[VAL_NUMACTIVEBITS]], [[TMP0]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i2 @llvm.smax.i2(i2 [[VAL_NUMACTIVEBITS_OFFSET]], i2 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i2 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw i2 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i2 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw i2 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i2 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i2 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nuw i2 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i2 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i2 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner.i2(i2 [[IV]], i2 [[NBITS]], i2 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i2 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i2 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i2 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i2 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i2 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer.i2(i2 [[IV_RES]], i2 [[NBITS_RES]], i2 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i2 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i2 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i2 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nuw i2 %iv, %extraoffset |
| %val.shifted = lshr i2 %val, %nbits |
| %val.shifted.iszero = icmp eq i2 %val.shifted, 0 |
| %iv.next = add i2 %iv, 1 |
| |
| call void @escape_inner.i2(i2 %iv, i2 %nbits, i2 %val.shifted, i1 %val.shifted.iszero, i2 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i2 [ %iv, %loop ] |
| %nbits.res = phi i2 [ %nbits, %loop ] |
| %val.shifted.res = phi i2 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i2 [ %iv.next, %loop ] |
| |
| call void @escape_outer.i2(i2 %iv.res, i2 %nbits.res, i2 %val.shifted.res, i1 %val.shifted.iszero.res, i2 %iv.next.res) |
| |
| ret i2 %iv.res |
| } |
| define i3 @t32_addnuw_i3(i3 %val, i3 %start, i3 %extraoffset) { |
| ; CHECK-LABEL: @t32_addnuw_i3( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i3 @llvm.ctlz.i3(i3 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i3 3, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[TMP0:%.*]] = sub i3 0, [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i3 [[VAL_NUMACTIVEBITS]], [[TMP0]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i3 @llvm.smax.i3(i3 [[VAL_NUMACTIVEBITS_OFFSET]], i3 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i3 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i3 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i3 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i3 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i3 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i3 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = add nuw i3 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i3 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i3 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner.i3(i3 [[IV]], i3 [[NBITS]], i3 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i3 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i3 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i3 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i3 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i3 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer.i3(i3 [[IV_RES]], i3 [[NBITS_RES]], i3 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i3 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i3 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i3 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = add nuw i3 %iv, %extraoffset |
| %val.shifted = lshr i3 %val, %nbits |
| %val.shifted.iszero = icmp eq i3 %val.shifted, 0 |
| %iv.next = add i3 %iv, 1 |
| |
| call void @escape_inner.i3(i3 %iv, i3 %nbits, i3 %val.shifted, i1 %val.shifted.iszero, i3 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i3 [ %iv, %loop ] |
| %nbits.res = phi i3 [ %nbits, %loop ] |
| %val.shifted.res = phi i3 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i3 [ %iv.next, %loop ] |
| |
| call void @escape_outer.i3(i3 %iv.res, i3 %nbits.res, i3 %val.shifted.res, i1 %val.shifted.iszero.res, i3 %iv.next.res) |
| |
| ret i3 %iv.res |
| } |
| |
| |
| define i1 @t33_subnsw_i1(i1 %val, i1 %start, i1 %extraoffset) { |
| ; CHECK-LABEL: @t33_subnsw_i1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i1 @llvm.ctlz.i1(i1 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i1 true, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i1 [[VAL_NUMACTIVEBITS]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i1 @llvm.smax.i1(i1 [[VAL_NUMACTIVEBITS_OFFSET]], i1 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i1 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i1 [[LOOP_BACKEDGETAKENCOUNT]], true |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i1 [[LOOP_IV]], true |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i1 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i1 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = sub nsw i1 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i1 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i1 [[IV]], true |
| ; CHECK-NEXT: call void @escape_inner.i1(i1 [[IV]], i1 [[NBITS]], i1 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i1 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i1 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i1 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i1 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i1 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer.i1(i1 [[IV_RES]], i1 [[NBITS_RES]], i1 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i1 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i1 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i1 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = sub nsw i1 %iv, %extraoffset |
| %val.shifted = lshr i1 %val, %nbits |
| %val.shifted.iszero = icmp eq i1 %val.shifted, 0 |
| %iv.next = add i1 %iv, 1 |
| |
| call void @escape_inner.i1(i1 %iv, i1 %nbits, i1 %val.shifted, i1 %val.shifted.iszero, i1 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i1 [ %iv, %loop ] |
| %nbits.res = phi i1 [ %nbits, %loop ] |
| %val.shifted.res = phi i1 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i1 [ %iv.next, %loop ] |
| |
| call void @escape_outer.i1(i1 %iv.res, i1 %nbits.res, i1 %val.shifted.res, i1 %val.shifted.iszero.res, i1 %iv.next.res) |
| |
| ret i1 %iv.res |
| } |
| define i2 @t34_addnuw_i2(i2 %val, i2 %start, i2 %extraoffset) { |
| ; CHECK-LABEL: @t34_addnuw_i2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i2 @llvm.ctlz.i2(i2 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw i2 -2, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i2 [[VAL_NUMACTIVEBITS]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i2 @llvm.smax.i2(i2 [[VAL_NUMACTIVEBITS_OFFSET]], i2 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i2 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw i2 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i2 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw i2 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i2 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i2 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = sub nsw i2 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i2 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i2 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner.i2(i2 [[IV]], i2 [[NBITS]], i2 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i2 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i2 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i2 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i2 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i2 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer.i2(i2 [[IV_RES]], i2 [[NBITS_RES]], i2 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i2 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i2 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i2 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = sub nsw i2 %iv, %extraoffset |
| %val.shifted = lshr i2 %val, %nbits |
| %val.shifted.iszero = icmp eq i2 %val.shifted, 0 |
| %iv.next = add i2 %iv, 1 |
| |
| call void @escape_inner.i2(i2 %iv, i2 %nbits, i2 %val.shifted, i1 %val.shifted.iszero, i2 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i2 [ %iv, %loop ] |
| %nbits.res = phi i2 [ %nbits, %loop ] |
| %val.shifted.res = phi i2 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i2 [ %iv.next, %loop ] |
| |
| call void @escape_outer.i2(i2 %iv.res, i2 %nbits.res, i2 %val.shifted.res, i1 %val.shifted.iszero.res, i2 %iv.next.res) |
| |
| ret i2 %iv.res |
| } |
| define i3 @t35_addnuw_i3(i3 %val, i3 %start, i3 %extraoffset) { |
| ; CHECK-LABEL: @t35_addnuw_i3( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[VAL_NUMLEADINGZEROS:%.*]] = call i3 @llvm.ctlz.i3(i3 [[VAL:%.*]], i1 false) |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS:%.*]] = sub nuw nsw i3 3, [[VAL_NUMLEADINGZEROS]] |
| ; CHECK-NEXT: [[VAL_NUMACTIVEBITS_OFFSET:%.*]] = add nsw i3 [[VAL_NUMACTIVEBITS]], [[EXTRAOFFSET:%.*]] |
| ; CHECK-NEXT: [[IV_FINAL:%.*]] = call i3 @llvm.smax.i3(i3 [[VAL_NUMACTIVEBITS_OFFSET]], i3 [[START:%.*]]) |
| ; CHECK-NEXT: [[LOOP_BACKEDGETAKENCOUNT:%.*]] = sub nsw i3 [[IV_FINAL]], [[START]] |
| ; CHECK-NEXT: [[LOOP_TRIPCOUNT:%.*]] = add nuw nsw i3 [[LOOP_BACKEDGETAKENCOUNT]], 1 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: [[LOOP_IV:%.*]] = phi i3 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_IV_NEXT:%.*]], [[LOOP]] ] |
| ; CHECK-NEXT: [[LOOP_IV_NEXT]] = add nuw nsw i3 [[LOOP_IV]], 1 |
| ; CHECK-NEXT: [[LOOP_IVCHECK:%.*]] = icmp eq i3 [[LOOP_IV_NEXT]], [[LOOP_TRIPCOUNT]] |
| ; CHECK-NEXT: [[IV:%.*]] = add nsw i3 [[LOOP_IV]], [[START]] |
| ; CHECK-NEXT: [[NBITS:%.*]] = sub nsw i3 [[IV]], [[EXTRAOFFSET]] |
| ; CHECK-NEXT: [[VAL_SHIFTED:%.*]] = lshr i3 [[VAL]], [[NBITS]] |
| ; CHECK-NEXT: [[IV_NEXT:%.*]] = add i3 [[IV]], 1 |
| ; CHECK-NEXT: call void @escape_inner.i3(i3 [[IV]], i3 [[NBITS]], i3 [[VAL_SHIFTED]], i1 [[LOOP_IVCHECK]], i3 [[IV_NEXT]]) |
| ; CHECK-NEXT: br i1 [[LOOP_IVCHECK]], label [[END:%.*]], label [[LOOP]] |
| ; CHECK: end: |
| ; CHECK-NEXT: [[IV_RES:%.*]] = phi i3 [ [[IV_FINAL]], [[LOOP]] ] |
| ; CHECK-NEXT: [[NBITS_RES:%.*]] = phi i3 [ [[NBITS]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_RES:%.*]] = phi i3 [ [[VAL_SHIFTED]], [[LOOP]] ] |
| ; CHECK-NEXT: [[VAL_SHIFTED_ISZERO_RES:%.*]] = phi i1 [ [[LOOP_IVCHECK]], [[LOOP]] ] |
| ; CHECK-NEXT: [[IV_NEXT_RES:%.*]] = phi i3 [ [[IV_NEXT]], [[LOOP]] ] |
| ; CHECK-NEXT: call void @escape_outer.i3(i3 [[IV_RES]], i3 [[NBITS_RES]], i3 [[VAL_SHIFTED_RES]], i1 [[VAL_SHIFTED_ISZERO_RES]], i3 [[IV_NEXT_RES]]) |
| ; CHECK-NEXT: ret i3 [[IV_RES]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i3 [ %start, %entry ], [ %iv.next, %loop ] |
| %nbits = sub nsw i3 %iv, %extraoffset |
| %val.shifted = lshr i3 %val, %nbits |
| %val.shifted.iszero = icmp eq i3 %val.shifted, 0 |
| %iv.next = add i3 %iv, 1 |
| |
| call void @escape_inner.i3(i3 %iv, i3 %nbits, i3 %val.shifted, i1 %val.shifted.iszero, i3 %iv.next) |
| |
| br i1 %val.shifted.iszero, label %end, label %loop |
| |
| end: |
| %iv.res = phi i3 [ %iv, %loop ] |
| %nbits.res = phi i3 [ %nbits, %loop ] |
| %val.shifted.res = phi i3 [ %val.shifted, %loop ] |
| %val.shifted.iszero.res = phi i1 [ %val.shifted.iszero, %loop ] |
| %iv.next.res = phi i3 [ %iv.next, %loop ] |
| |
| call void @escape_outer.i3(i3 %iv.res, i3 %nbits.res, i3 %val.shifted.res, i1 %val.shifted.iszero.res, i3 %iv.next.res) |
| |
| ret i3 %iv.res |
| } |