| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs |
| ; RUN: opt -S -verify -iroutliner -ir-outlining-no-cost < %s | FileCheck %s |
| |
| ; Here we have multiple exits, but the different sources, same outputs are |
| ; needed, this checks that they are compressed, and moved into the appropriate |
| ; output blocks. |
| |
| define void @outline_outputs1() #0 { |
| entry: |
| %output = alloca i32, align 4 |
| %result = alloca i32, align 4 |
| %output2 = alloca i32, align 4 |
| %result2 = alloca i32, align 4 |
| %a = alloca i32, align 4 |
| %b = alloca i32, align 4 |
| br label %block_2 |
| block_1: |
| %a2 = alloca i32, align 4 |
| %b2 = alloca i32, align 4 |
| br label %block_2 |
| block_2: |
| %a2val = load i32, i32* %a |
| %b2val = load i32, i32* %b |
| %add2 = add i32 2, %a2val |
| %mul2 = mul i32 2, %b2val |
| br label %block_5 |
| block_3: |
| %aval = load i32, i32* %a |
| %bval = load i32, i32* %b |
| %add = add i32 2, %aval |
| %mul = mul i32 2, %bval |
| br label %block_4 |
| block_4: |
| store i32 %add, i32* %output, align 4 |
| store i32 %mul, i32* %result, align 4 |
| br label %block_6 |
| block_5: |
| store i32 %add2, i32* %output, align 4 |
| store i32 %mul2, i32* %result, align 4 |
| br label %block_6 |
| dummy: |
| ret void |
| block_6: |
| %diff = phi i32 [%aval, %block_4], [%a2val, %block_5] |
| ret void |
| } |
| |
| define void @outline_outputs2() #0 { |
| entry: |
| %output = alloca i32, align 4 |
| %result = alloca i32, align 4 |
| %output2 = alloca i32, align 4 |
| %result2 = alloca i32, align 4 |
| %a = alloca i32, align 4 |
| %b = alloca i32, align 4 |
| br label %block_2 |
| block_1: |
| %a2 = alloca i32, align 4 |
| %b2 = alloca i32, align 4 |
| br label %block_2 |
| block_2: |
| %a2val = load i32, i32* %a |
| %b2val = load i32, i32* %b |
| %add2 = add i32 2, %a2val |
| %mul2 = mul i32 2, %b2val |
| br label %block_5 |
| block_3: |
| %aval = load i32, i32* %a |
| %bval = load i32, i32* %b |
| %add = add i32 2, %aval |
| %mul = mul i32 2, %bval |
| br label %block_4 |
| block_4: |
| store i32 %add, i32* %output, align 4 |
| store i32 %mul, i32* %result, align 4 |
| br label %block_6 |
| block_5: |
| store i32 %add2, i32* %output, align 4 |
| store i32 %mul2, i32* %result, align 4 |
| br label %block_6 |
| dummy: |
| ret void |
| block_6: |
| %diff = phi i32 [%aval, %block_4], [%a2val, %block_5] |
| ret void |
| } |
| |
| ; CHECK-LABEL: @outline_outputs1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[DIFF_CE_LOC:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: br label [[BLOCK_2:%.*]] |
| ; CHECK: block_1: |
| ; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: br label [[BLOCK_2]] |
| ; CHECK: block_2: |
| ; CHECK-NEXT: [[LT_CAST:%.*]] = bitcast i32* [[DIFF_CE_LOC]] to i8* |
| ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST]]) |
| ; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[OUTPUT]], i32* [[RESULT]], i32* [[DIFF_CE_LOC]]) |
| ; CHECK-NEXT: [[DIFF_CE_RELOAD:%.*]] = load i32, i32* [[DIFF_CE_LOC]], align 4 |
| ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST]]) |
| ; CHECK-NEXT: br label [[BLOCK_6:%.*]] |
| ; CHECK: dummy: |
| ; CHECK-NEXT: ret void |
| ; CHECK: block_6: |
| ; CHECK-NEXT: [[DIFF:%.*]] = phi i32 [ [[DIFF_CE_RELOAD]], [[BLOCK_2]] ] |
| ; CHECK-NEXT: ret void |
| ; |
| ; |
| ; CHECK-LABEL: @outline_outputs2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[DIFF_CE_LOC:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: br label [[BLOCK_2:%.*]] |
| ; CHECK: block_1: |
| ; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: br label [[BLOCK_2]] |
| ; CHECK: block_2: |
| ; CHECK-NEXT: [[LT_CAST:%.*]] = bitcast i32* [[DIFF_CE_LOC]] to i8* |
| ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST]]) |
| ; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[OUTPUT]], i32* [[RESULT]], i32* [[DIFF_CE_LOC]]) |
| ; CHECK-NEXT: [[DIFF_CE_RELOAD:%.*]] = load i32, i32* [[DIFF_CE_LOC]], align 4 |
| ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST]]) |
| ; CHECK-NEXT: br label [[BLOCK_6:%.*]] |
| ; CHECK: dummy: |
| ; CHECK-NEXT: ret void |
| ; CHECK: block_6: |
| ; CHECK-NEXT: [[DIFF:%.*]] = phi i32 [ [[DIFF_CE_RELOAD]], [[BLOCK_2]] ] |
| ; CHECK-NEXT: ret void |
| ; |
| ; |
| ; CHECK: define internal void @outlined_ir_func_0( |
| ; CHECK-NEXT: newFuncRoot: |
| ; CHECK-NEXT: br label [[BLOCK_2_TO_OUTLINE:%.*]] |
| ; CHECK: block_2_to_outline: |
| ; CHECK-NEXT: [[A2VAL:%.*]] = load i32, i32* [[TMP0:%.*]], align 4 |
| ; CHECK-NEXT: [[B2VAL:%.*]] = load i32, i32* [[TMP1:%.*]], align 4 |
| ; CHECK-NEXT: [[ADD2:%.*]] = add i32 2, [[A2VAL]] |
| ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 2, [[B2VAL]] |
| ; CHECK-NEXT: br label [[BLOCK_5:%.*]] |
| ; CHECK: block_3: |
| ; CHECK-NEXT: [[AVAL:%.*]] = load i32, i32* [[TMP0]], align 4 |
| ; CHECK-NEXT: [[BVAL:%.*]] = load i32, i32* [[TMP1]], align 4 |
| ; CHECK-NEXT: [[ADD:%.*]] = add i32 2, [[AVAL]] |
| ; CHECK-NEXT: [[MUL:%.*]] = mul i32 2, [[BVAL]] |
| ; CHECK-NEXT: br label [[BLOCK_4:%.*]] |
| ; CHECK: block_4: |
| ; CHECK-NEXT: store i32 [[ADD]], i32* [[TMP2:%.*]], align 4 |
| ; CHECK-NEXT: store i32 [[MUL]], i32* [[TMP3:%.*]], align 4 |
| ; CHECK-NEXT: br label [[BLOCK_6_SPLIT:%.*]] |
| ; CHECK: block_5: |
| ; CHECK-NEXT: store i32 [[ADD2]], i32* [[TMP2]], align 4 |
| ; CHECK-NEXT: store i32 [[MUL2]], i32* [[TMP3]], align 4 |
| ; CHECK-NEXT: br label [[BLOCK_6_SPLIT]] |
| ; CHECK: block_6.split: |
| ; CHECK-NEXT: [[DIFF_CE:%.*]] = phi i32 [ [[AVAL]], [[BLOCK_4]] ], [ [[A2VAL]], [[BLOCK_5]] ] |
| ; CHECK-NEXT: br label [[BLOCK_6_EXITSTUB:%.*]] |
| ; CHECK: block_6.exitStub: |
| ; CHECK-NEXT: store i32 [[DIFF_CE]], i32* [[TMP4:%.*]], align 4 |
| ; CHECK-NEXT: ret void |
| ; |