| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 6 |
| ; RUN: opt -passes=loop-vectorize \ |
| ; RUN: -prefer-predicate-over-epilogue=predicate-else-scalar-epilogue \ |
| ; RUN: -mtriple=riscv64 -mattr=+v -S < %s | FileCheck --check-prefix=IF-EVL %s |
| ; RUN: opt -passes=loop-vectorize \ |
| ; RUN: -prefer-predicate-over-epilogue=scalar-epilogue \ |
| ; RUN: -mtriple=riscv64 -mattr=+v -S < %s | FileCheck --check-prefix=NO-VP %s |
| |
| define void @low_trip_count_small(i32 %x, ptr %dst) { |
| ; IF-EVL-LABEL: define void @low_trip_count_small( |
| ; IF-EVL-SAME: i32 [[X:%.*]], ptr [[DST:%.*]]) #[[ATTR0:[0-9]+]] { |
| ; IF-EVL-NEXT: [[ENTRY:.*]]: |
| ; IF-EVL-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 1) |
| ; IF-EVL-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SMAX]], i32 4) |
| ; IF-EVL-NEXT: br label %[[LOOP:.*]] |
| ; IF-EVL: [[LOOP]]: |
| ; IF-EVL-NEXT: [[PTR:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[PTR_NEXT:%.*]], %[[LOOP]] ] |
| ; IF-EVL-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] |
| ; IF-EVL-NEXT: [[PTR_NEXT]] = getelementptr i8, ptr [[PTR]], i64 1 |
| ; IF-EVL-NEXT: store i8 0, ptr [[PTR_NEXT]], align 1 |
| ; IF-EVL-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 |
| ; IF-EVL-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[IV_NEXT]], [[UMIN]] |
| ; IF-EVL-NEXT: br i1 [[EXITCOND]], label %[[EXIT:.*]], label %[[LOOP]] |
| ; IF-EVL: [[EXIT]]: |
| ; IF-EVL-NEXT: ret void |
| ; |
| ; NO-VP-LABEL: define void @low_trip_count_small( |
| ; NO-VP-SAME: i32 [[X:%.*]], ptr [[DST:%.*]]) #[[ATTR0:[0-9]+]] { |
| ; NO-VP-NEXT: [[ENTRY:.*]]: |
| ; NO-VP-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 1) |
| ; NO-VP-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SMAX]], i32 4) |
| ; NO-VP-NEXT: br label %[[LOOP:.*]] |
| ; NO-VP: [[LOOP]]: |
| ; NO-VP-NEXT: [[PTR:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[PTR_NEXT:%.*]], %[[LOOP]] ] |
| ; NO-VP-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] |
| ; NO-VP-NEXT: [[PTR_NEXT]] = getelementptr i8, ptr [[PTR]], i64 1 |
| ; NO-VP-NEXT: store i8 0, ptr [[PTR_NEXT]], align 1 |
| ; NO-VP-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 |
| ; NO-VP-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[IV_NEXT]], [[UMIN]] |
| ; NO-VP-NEXT: br i1 [[EXITCOND]], label %[[EXIT:.*]], label %[[LOOP]] |
| ; NO-VP: [[EXIT]]: |
| ; NO-VP-NEXT: ret void |
| ; |
| entry: |
| %smax = call i32 @llvm.smax.i32(i32 %x, i32 1) |
| %umin = call i32 @llvm.umin.i32(i32 %smax, i32 4) |
| br label %loop |
| |
| loop: ; preds = %loop, %entry |
| %ptr = phi ptr [ %dst, %entry ], [ %ptr.next, %loop ] |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] |
| %ptr.next = getelementptr i8, ptr %ptr, i64 1 |
| store i8 0, ptr %ptr.next |
| %iv.next = add i32 %iv, 1 |
| %exitcond = icmp eq i32 %iv.next, %umin |
| br i1 %exitcond, label %exit, label %loop |
| |
| exit: |
| ret void |
| } |
| |
| |
| define ptr @low_trip_count_small_with_live_out(i32 %x, ptr %dst) { |
| ; IF-EVL-LABEL: define ptr @low_trip_count_small_with_live_out( |
| ; IF-EVL-SAME: i32 [[X:%.*]], ptr [[DST:%.*]]) #[[ATTR0]] { |
| ; IF-EVL-NEXT: [[ENTRY:.*]]: |
| ; IF-EVL-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 1) |
| ; IF-EVL-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SMAX]], i32 4) |
| ; IF-EVL-NEXT: br label %[[LOOP:.*]] |
| ; IF-EVL: [[LOOP]]: |
| ; IF-EVL-NEXT: [[PTR:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[PTR_NEXT:%.*]], %[[LOOP]] ] |
| ; IF-EVL-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] |
| ; IF-EVL-NEXT: [[PTR_NEXT]] = getelementptr i8, ptr [[PTR]], i64 1 |
| ; IF-EVL-NEXT: store i8 0, ptr [[PTR_NEXT]], align 1 |
| ; IF-EVL-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 |
| ; IF-EVL-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[IV_NEXT]], [[UMIN]] |
| ; IF-EVL-NEXT: br i1 [[EXITCOND]], label %[[EXIT:.*]], label %[[LOOP]] |
| ; IF-EVL: [[EXIT]]: |
| ; IF-EVL-NEXT: [[PTR_NEXT_LCSSA:%.*]] = phi ptr [ [[PTR_NEXT]], %[[LOOP]] ] |
| ; IF-EVL-NEXT: ret ptr [[PTR_NEXT_LCSSA]] |
| ; |
| ; NO-VP-LABEL: define ptr @low_trip_count_small_with_live_out( |
| ; NO-VP-SAME: i32 [[X:%.*]], ptr [[DST:%.*]]) #[[ATTR0]] { |
| ; NO-VP-NEXT: [[ENTRY:.*]]: |
| ; NO-VP-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 1) |
| ; NO-VP-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SMAX]], i32 4) |
| ; NO-VP-NEXT: br label %[[LOOP:.*]] |
| ; NO-VP: [[LOOP]]: |
| ; NO-VP-NEXT: [[PTR:%.*]] = phi ptr [ [[DST]], %[[ENTRY]] ], [ [[PTR_NEXT:%.*]], %[[LOOP]] ] |
| ; NO-VP-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] |
| ; NO-VP-NEXT: [[PTR_NEXT]] = getelementptr i8, ptr [[PTR]], i64 1 |
| ; NO-VP-NEXT: store i8 0, ptr [[PTR_NEXT]], align 1 |
| ; NO-VP-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 |
| ; NO-VP-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[IV_NEXT]], [[UMIN]] |
| ; NO-VP-NEXT: br i1 [[EXITCOND]], label %[[EXIT:.*]], label %[[LOOP]] |
| ; NO-VP: [[EXIT]]: |
| ; NO-VP-NEXT: [[PTR_NEXT_LCSSA:%.*]] = phi ptr [ [[PTR_NEXT]], %[[LOOP]] ] |
| ; NO-VP-NEXT: ret ptr [[PTR_NEXT_LCSSA]] |
| ; |
| entry: |
| %smax = call i32 @llvm.smax.i32(i32 %x, i32 1) |
| %umin = call i32 @llvm.umin.i32(i32 %smax, i32 4) |
| br label %loop |
| |
| loop: |
| %ptr = phi ptr [ %dst, %entry ], [ %ptr.next, %loop ] |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] |
| %ptr.next = getelementptr i8, ptr %ptr, i64 1 |
| store i8 0, ptr %ptr.next |
| %iv.next = add i32 %iv, 1 |
| %exitcond = icmp eq i32 %iv.next, %umin |
| br i1 %exitcond, label %exit, label %loop |
| |
| exit: |
| ret ptr %ptr.next |
| } |