146 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs2; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s3 4; Show that we do not extract similar regions that would involve the splitting5; of phi nodes on exit.6 7define void @function1(ptr %a, ptr %b) {8entry:9 %0 = alloca i32, align 410 %c = load i32, ptr %0, align 411 br label %test112test1:13 %e = load i32, ptr %0, align 414 br i1 true, label %first, label %test15test:16 %d = load i32, ptr %0, align 417 br i1 true, label %first, label %next18first:19 %1 = phi i32 [ %c, %test ], [ %e, %test1 ]20 ret void21next:22 %2 = add i32 %d, 123 %3 = add i32 %e, 124 ret void25}26 27define void @function2(ptr %a, ptr %b) {28entry:29 %0 = alloca i32, align 430 %c = load i32, ptr %0, align 431 br label %test132test1:33 %e = load i32, ptr %0, align 434 br i1 true, label %first, label %test35test:36 %d = load i32, ptr %0, align 437 br i1 true, label %first, label %next38first:39 ret void40next:41 %1 = add i32 %d, 142 %2 = add i32 %e, 143 ret void44}45; CHECK-LABEL: @function1(46; CHECK-NEXT: entry:47; CHECK-NEXT: [[DOTCE_LOC:%.*]] = alloca i32, align 448; CHECK-NEXT: [[D_LOC:%.*]] = alloca i32, align 449; CHECK-NEXT: [[E_LOC:%.*]] = alloca i32, align 450; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 451; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[E_LOC]])52; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[D_LOC]])53; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTCE_LOC]])54; CHECK-NEXT: [[TMP1:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], ptr [[E_LOC]], ptr [[D_LOC]], ptr [[DOTCE_LOC]], i32 0)55; CHECK-NEXT: [[E_RELOAD:%.*]] = load i32, ptr [[E_LOC]], align 456; CHECK-NEXT: [[D_RELOAD:%.*]] = load i32, ptr [[D_LOC]], align 457; CHECK-NEXT: [[DOTCE_RELOAD:%.*]] = load i32, ptr [[DOTCE_LOC]], align 458; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[E_LOC]])59; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[D_LOC]])60; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTCE_LOC]])61; CHECK-NEXT: br i1 [[TMP1]], label [[FIRST:%.*]], label [[NEXT:%.*]]62; CHECK: first:63; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[DOTCE_RELOAD]], [[ENTRY:%.*]] ]64; CHECK-NEXT: ret void65; CHECK: next:66; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[D_RELOAD]], i32 [[E_RELOAD]])67; CHECK-NEXT: ret void68;69;70; CHECK-LABEL: @function2(71; CHECK-NEXT: entry:72; CHECK-NEXT: [[D_LOC:%.*]] = alloca i32, align 473; CHECK-NEXT: [[E_LOC:%.*]] = alloca i32, align 474; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 475; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[E_LOC]])76; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[D_LOC]])77; CHECK-NEXT: [[TMP1:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], ptr [[E_LOC]], ptr [[D_LOC]], ptr null, i32 1)78; CHECK-NEXT: [[E_RELOAD:%.*]] = load i32, ptr [[E_LOC]], align 479; CHECK-NEXT: [[D_RELOAD:%.*]] = load i32, ptr [[D_LOC]], align 480; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[E_LOC]])81; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[D_LOC]])82; CHECK-NEXT: br i1 [[TMP1]], label [[FIRST:%.*]], label [[NEXT:%.*]]83; CHECK: first:84; CHECK-NEXT: ret void85; CHECK: next:86; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[D_RELOAD]], i32 [[E_RELOAD]])87; CHECK-NEXT: ret void88;89;90; CHECK-LABEL: define internal i1 @outlined_ir_func_0(91; CHECK-NEXT: newFuncRoot:92; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]93; CHECK: entry_to_outline:94; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0:%.*]], align 495; CHECK-NEXT: br label [[TEST1:%.*]]96; CHECK: test1:97; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0]], align 498; CHECK-NEXT: br i1 true, label [[FIRST_SPLIT:%.*]], label [[TEST:%.*]]99; CHECK: test:100; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP0]], align 4101; CHECK-NEXT: br i1 true, label [[FIRST_SPLIT]], label [[NEXT_EXITSTUB:%.*]]102; CHECK: first.split:103; CHECK-NEXT: [[DOTCE:%.*]] = phi i32 [ [[C]], [[TEST]] ], [ [[E]], [[TEST1]] ]104; CHECK-NEXT: br label [[FIRST_EXITSTUB:%.*]]105; CHECK: first.exitStub:106; CHECK-NEXT: switch i32 [[TMP4:%.*]], label [[FINAL_BLOCK_1:%.*]] [107; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_1:%.*]]108; CHECK-NEXT: i32 1, label [[OUTPUT_BLOCK_1_1:%.*]]109; CHECK-NEXT: ]110; CHECK: next.exitStub:111; CHECK-NEXT: switch i32 [[TMP4]], label [[FINAL_BLOCK_0:%.*]] [112; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_0:%.*]]113; CHECK-NEXT: i32 1, label [[OUTPUT_BLOCK_1_0:%.*]]114; CHECK-NEXT: ]115; CHECK: output_block_0_0:116; CHECK-NEXT: store i32 [[E]], ptr [[TMP1:%.*]], align 4117; CHECK-NEXT: store i32 [[D]], ptr [[TMP2:%.*]], align 4118; CHECK-NEXT: br label [[FINAL_BLOCK_0]]119; CHECK: output_block_0_1:120; CHECK-NEXT: store i32 [[E]], ptr [[TMP1]], align 4121; CHECK-NEXT: store i32 [[DOTCE]], ptr [[TMP3:%.*]], align 4122; CHECK-NEXT: br label [[FINAL_BLOCK_1]]123; CHECK: output_block_1_0:124; CHECK-NEXT: store i32 [[E]], ptr [[TMP1]], align 4125; CHECK-NEXT: store i32 [[D]], ptr [[TMP2]], align 4126; CHECK-NEXT: br label [[FINAL_BLOCK_0]]127; CHECK: output_block_1_1:128; CHECK-NEXT: store i32 [[E]], ptr [[TMP1]], align 4129; CHECK-NEXT: br label [[FINAL_BLOCK_1]]130; CHECK: final_block_0:131; CHECK-NEXT: ret i1 false132; CHECK: final_block_1:133; CHECK-NEXT: ret i1 true134;135;136; CHECK-LABEL: @outlined_ir_func_1(137; CHECK-NEXT: newFuncRoot:138; CHECK-NEXT: br label [[NEXT_TO_OUTLINE:%.*]]139; CHECK: next_to_outline:140; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP0:%.*]], 1141; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP1:%.*]], 1142; CHECK-NEXT: br label [[NEXT_AFTER_OUTLINE_EXITSTUB:%.*]]143; CHECK: next_after_outline.exitStub:144; CHECK-NEXT: ret void145;146