1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=verify,iroutliner < %s | FileCheck %s 3; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s -check-prefix=NOCOST 4 5; This test checks that we have different results from when the cost model 6; is on versus when it is off. That is, if the number of instructions needed to 7; handle the arguments is greater than the number of instructions being added, 8; we do not outline. 9 10define void @function1() #0 { 11; CHECK-LABEL: @function1( 12; CHECK-NEXT: entry: 13; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 14; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 15; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]]) 16; CHECK-NEXT: ret void 17; 18; NOCOST-LABEL: @function1( 19; NOCOST-NEXT: entry: 20; NOCOST-NEXT: [[A:%.*]] = alloca i32, align 4 21; NOCOST-NEXT: [[B:%.*]] = alloca i32, align 4 22; NOCOST-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]]) 23; NOCOST-NEXT: ret void 24; 25entry: 26 %a = alloca i32, align 4 27 %b = alloca i32, align 4 28 %0 = load i32, ptr %a, align 4 29 %1 = load i32, ptr %b, align 4 30 %add = add i32 %0, %1 31 %mul = mul i32 %0, %1 32 %sub = sub i32 %0, %1 33 %div = sdiv i32 %0, %1 34 %add1 = add i32 %0, %1 35 %mul1 = mul i32 %0, %1 36 %sub1 = sub i32 %0, %1 37 %div1 = sdiv i32 %0, %1 38 %add2 = add i32 %0, %1 39 %mul2 = mul i32 %0, %1 40 %sub2 = sub i32 %0, %1 41 %div2 = sdiv i32 %0, %1 42 ret void 43} 44 45define void @function2() #0 { 46; CHECK-LABEL: @function2( 47; CHECK-NEXT: entry: 48; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 49; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 50; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]]) 51; CHECK-NEXT: ret void 52; 53; NOCOST-LABEL: @function2( 54; NOCOST-NEXT: entry: 55; NOCOST-NEXT: [[A:%.*]] = alloca i32, align 4 56; NOCOST-NEXT: [[B:%.*]] = alloca i32, align 4 57; NOCOST-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]]) 58; NOCOST-NEXT: ret void 59; 60entry: 61 %a = alloca i32, align 4 62 %b = alloca i32, align 4 63 %0 = load i32, ptr %a, align 4 64 %1 = load i32, ptr %b, align 4 65 %add = add i32 %0, %1 66 %mul = mul i32 %0, %1 67 %sub = sub i32 %0, %1 68 %div = sdiv i32 %0, %1 69 %add1 = add i32 %0, %1 70 %mul1 = mul i32 %0, %1 71 %sub1 = sub i32 %0, %1 72 %div1 = sdiv i32 %0, %1 73 %add2 = add i32 %0, %1 74 %mul2 = mul i32 %0, %1 75 %sub2 = sub i32 %0, %1 76 %div2 = sdiv i32 %0, %1 77 ret void 78} 79 80define void @function3() #0 { 81; CHECK-LABEL: @function3( 82; CHECK-NEXT: entry: 83; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 84; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 85; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4 86; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4 87; CHECK-NEXT: store i32 2, ptr [[A]], align 4 88; CHECK-NEXT: store i32 3, ptr [[B]], align 4 89; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4 90; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B]], align 4 91; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[TMP1]] 92; CHECK-NEXT: store i32 [[ADD]], ptr [[OUTPUT]], align 4 93; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[OUTPUT]], align 4 94; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[OUTPUT]], align 4 95; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[TMP2]], [[ADD]] 96; CHECK-NEXT: store i32 [[MUL]], ptr [[RESULT]], align 4 97; CHECK-NEXT: ret void 98; 99; NOCOST-LABEL: @function3( 100; NOCOST-NEXT: entry: 101; NOCOST-NEXT: [[DOTLOC:%.*]] = alloca i32, align 4 102; NOCOST-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4 103; NOCOST-NEXT: [[A:%.*]] = alloca i32, align 4 104; NOCOST-NEXT: [[B:%.*]] = alloca i32, align 4 105; NOCOST-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4 106; NOCOST-NEXT: [[RESULT:%.*]] = alloca i32, align 4 107; NOCOST-NEXT: call void @llvm.lifetime.start.p0(i64 -1, ptr [[ADD_LOC]]) 108; NOCOST-NEXT: call void @llvm.lifetime.start.p0(i64 -1, ptr [[DOTLOC]]) 109; NOCOST-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[ADD_LOC]], ptr [[DOTLOC]]) 110; NOCOST-NEXT: [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4 111; NOCOST-NEXT: [[DOTRELOAD:%.*]] = load i32, ptr [[DOTLOC]], align 4 112; NOCOST-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[ADD_LOC]]) 113; NOCOST-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[DOTLOC]]) 114; NOCOST-NEXT: [[TMP0:%.*]] = load i32, ptr [[OUTPUT]], align 4 115; NOCOST-NEXT: call void @outlined_ir_func_2(i32 [[DOTRELOAD]], i32 [[ADD_RELOAD]], ptr [[RESULT]]) 116; NOCOST-NEXT: ret void 117; 118entry: 119 %a = alloca i32, align 4 120 %b = alloca i32, align 4 121 %output = alloca i32, align 4 122 %result = alloca i32, align 4 123 store i32 2, ptr %a, align 4 124 store i32 3, ptr %b, align 4 125 %0 = load i32, ptr %a, align 4 126 %1 = load i32, ptr %b, align 4 127 %add = add i32 %0, %1 128 store i32 %add, ptr %output, align 4 129 %2 = load i32, ptr %output, align 4 130 %3 = load i32, ptr %output, align 4 131 %mul = mul i32 %2, %add 132 store i32 %mul, ptr %result, align 4 133 ret void 134} 135 136define void @function4() #0 { 137; CHECK-LABEL: @function4( 138; CHECK-NEXT: entry: 139; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 140; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 141; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4 142; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4 143; CHECK-NEXT: store i32 2, ptr [[A]], align 4 144; CHECK-NEXT: store i32 3, ptr [[B]], align 4 145; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4 146; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B]], align 4 147; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[TMP1]] 148; CHECK-NEXT: store i32 [[ADD]], ptr [[OUTPUT]], align 4 149; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[OUTPUT]], align 4 150; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[TMP2]], [[ADD]] 151; CHECK-NEXT: store i32 [[MUL]], ptr [[RESULT]], align 4 152; CHECK-NEXT: ret void 153; 154; NOCOST-LABEL: @function4( 155; NOCOST-NEXT: entry: 156; NOCOST-NEXT: [[DOTLOC:%.*]] = alloca i32, align 4 157; NOCOST-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4 158; NOCOST-NEXT: [[A:%.*]] = alloca i32, align 4 159; NOCOST-NEXT: [[B:%.*]] = alloca i32, align 4 160; NOCOST-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4 161; NOCOST-NEXT: [[RESULT:%.*]] = alloca i32, align 4 162; NOCOST-NEXT: call void @llvm.lifetime.start.p0(i64 -1, ptr [[ADD_LOC]]) 163; NOCOST-NEXT: call void @llvm.lifetime.start.p0(i64 -1, ptr [[DOTLOC]]) 164; NOCOST-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[ADD_LOC]], ptr [[DOTLOC]]) 165; NOCOST-NEXT: [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4 166; NOCOST-NEXT: [[DOTRELOAD:%.*]] = load i32, ptr [[DOTLOC]], align 4 167; NOCOST-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[ADD_LOC]]) 168; NOCOST-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[DOTLOC]]) 169; NOCOST-NEXT: call void @outlined_ir_func_2(i32 [[DOTRELOAD]], i32 [[ADD_RELOAD]], ptr [[RESULT]]) 170; NOCOST-NEXT: ret void 171; 172entry: 173 %a = alloca i32, align 4 174 %b = alloca i32, align 4 175 %output = alloca i32, align 4 176 %result = alloca i32, align 4 177 store i32 2, ptr %a, align 4 178 store i32 3, ptr %b, align 4 179 %0 = load i32, ptr %a, align 4 180 %1 = load i32, ptr %b, align 4 181 %add = add i32 %0, %1 182 store i32 %add, ptr %output, align 4 183 %2 = load i32, ptr %output, align 4 184 %mul = mul i32 %2, %add 185 store i32 %mul, ptr %result, align 4 186 ret void 187} 188