1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=loop-rotate -verify-memoryssa < %s | FileCheck %s 3; RUN: opt -S -passes='require<target-ir>,require<assumptions>,loop(loop-rotate)' < %s | FileCheck %s 4 5; Demonstrate handling of invalid costs in LoopRotate. This test uses 6; scalable vectors on RISCV w/o +V to create a situation where a construct 7; can not be lowered, and is thus invalid regardless of what the target 8; does or does not implement in terms of a cost model. 9 10target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128" 11target triple = "riscv64-unknown-unknown" 12 13define void @valid() nounwind ssp { 14; CHECK-LABEL: @valid( 15; CHECK-NEXT: entry: 16; CHECK-NEXT: br label [[FOR_COND:%.*]] 17; CHECK: for.cond: 18; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_COND]] ] 19; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 100 20; CHECK-NEXT: [[INC]] = add nsw i32 [[I_0]], 1 21; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND]], label [[FOR_END:%.*]] 22; CHECK: for.end: 23; CHECK-NEXT: ret void 24; 25entry: 26 br label %for.cond 27 28for.cond: ; preds = %for.body, %entry 29 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] 30 %cmp = icmp slt i32 %i.0, 100 31 br i1 %cmp, label %for.body, label %for.end 32 33 34for.body: ; preds = %for.cond 35 %inc = add nsw i32 %i.0, 1 36 br label %for.cond 37 38for.end: ; preds = %for.cond 39 ret void 40} 41 42; Despite having an invalid cost, we can rotate this because we don't 43; need to duplicate any instructions or execute them more frequently. 44define void @invalid_no_dup(ptr %p) nounwind ssp { 45; CHECK-LABEL: @invalid_no_dup( 46; CHECK-NEXT: entry: 47; CHECK-NEXT: br label [[FOR_BODY:%.*]] 48; CHECK: for.body: 49; CHECK-NEXT: [[I_01:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] 50; CHECK-NEXT: [[A:%.*]] = load <vscale x 1 x i8>, ptr [[P:%.*]], align 1 51; CHECK-NEXT: [[B:%.*]] = add <vscale x 1 x i8> [[A]], [[A]] 52; CHECK-NEXT: store <vscale x 1 x i8> [[B]], ptr [[P]], align 1 53; CHECK-NEXT: [[INC]] = add nsw i32 [[I_01]], 1 54; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], 100 55; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 56; CHECK: for.end: 57; CHECK-NEXT: ret void 58; 59entry: 60 br label %for.cond 61 62for.cond: ; preds = %for.body, %entry 63 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] 64 %cmp = icmp slt i32 %i.0, 100 65 br i1 %cmp, label %for.body, label %for.end 66 67 68for.body: ; preds = %for.cond 69 %a = load <vscale x 1 x i8>, ptr %p 70 %b = add <vscale x 1 x i8> %a, %a 71 store <vscale x 1 x i8> %b, ptr %p 72 %inc = add nsw i32 %i.0, 1 73 br label %for.cond 74 75for.end: ; preds = %for.cond 76 ret void 77} 78 79; This demonstrates a case where a) loop rotate needs a cost estimate to 80; know if rotation is profitable, and b) there is no cost estimate available 81; due to invalid costs in the loop. We can't rotate this loop. 82define void @invalid_dup_required(ptr %p) nounwind ssp { 83; CHECK-LABEL: @invalid_dup_required( 84; CHECK-NEXT: entry: 85; CHECK-NEXT: br label [[FOR_COND:%.*]] 86; CHECK: for.cond: 87; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ] 88; CHECK-NEXT: [[A:%.*]] = load <vscale x 1 x i8>, ptr [[P:%.*]], align 1 89; CHECK-NEXT: [[B:%.*]] = add <vscale x 1 x i8> [[A]], [[A]] 90; CHECK-NEXT: store <vscale x 1 x i8> [[B]], ptr [[P]], align 1 91; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 100 92; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 93; CHECK: for.body: 94; CHECK-NEXT: call void @f() 95; CHECK-NEXT: [[INC]] = add nsw i32 [[I_0]], 1 96; CHECK-NEXT: br label [[FOR_COND]] 97; CHECK: for.end: 98; CHECK-NEXT: ret void 99; 100entry: 101 br label %for.cond 102 103for.cond: ; preds = %for.body, %entry 104 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] 105 %a = load <vscale x 1 x i8>, ptr %p 106 %b = add <vscale x 1 x i8> %a, %a 107 store <vscale x 1 x i8> %b, ptr %p 108 %cmp = icmp slt i32 %i.0, 100 109 br i1 %cmp, label %for.body, label %for.end 110 111 112for.body: ; preds = %for.cond 113 call void @f() 114 %inc = add nsw i32 %i.0, 1 115 br label %for.cond 116 117for.end: ; preds = %for.cond 118 ret void 119} 120 121declare void @f() 122