1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs 2; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s 3 4; When consolidating PHINodes, the outliner replaces the incoming value with 5; a corresponding value from the first outlined section. When this replaced 6; value is passed in as an argument, the corresponding value is found outside 7; of the outlined region, and must be replaced with an argument to avoid 8; dominating value errors. This checks that we use the argument to replace 9; the incoming value. 10 11define void @func1(i32 %0, i32 %1) local_unnamed_addr #0 { 12bb1: 13 br label %bb5 14 15bb2: 16 %a = add i32 %0, %1 17 %b = add i32 %0, %1 18 %c = icmp eq i32 %b, %a 19 br i1 %c, label %bb5, label %bb3 20 21bb3: 22 %d = add i32 %0, %1 23 br label %bb5 24 25bb4: 26 %e = sub i32 %0, %1 27 br label %bb2 28 29bb5: 30 ret void 31} 32 33define void @func2(i32 %0, i32 %1) local_unnamed_addr #0 { 34bb1: 35 br label %bb5 36 37bb2: 38 %a = sub i32 %0, %1 39 %b = add i32 %0, %1 40 %c = icmp eq i32 %b, 1 41 br i1 %c, label %bb5, label %bb3 42 43bb3: 44 %d = add i32 %0, %1 45 br label %bb5 46 47bb4: 48 %e = add i32 %0, %1 49 br label %bb2 50 51bb5: 52 %f = phi i32 [ 0, %bb1 ], [ 1, %bb2 ], [ 1, %bb3 ] 53 ret void 54} 55; CHECK-LABEL: @func1( 56; CHECK-NEXT: bb1: 57; CHECK-NEXT: br label [[BB5:%.*]] 58; CHECK: bb2: 59; CHECK-NEXT: [[A:%.*]] = add i32 [[TMP0:%.*]], [[TMP1:%.*]] 60; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[TMP0]], i32 [[TMP1]], i32 [[A]], ptr null, i32 -1) 61; CHECK-NEXT: br label [[BB5]] 62; CHECK: bb4: 63; CHECK-NEXT: [[E:%.*]] = sub i32 [[TMP0]], [[TMP1]] 64; CHECK-NEXT: br label [[BB2:%.*]] 65; CHECK: bb5: 66; CHECK-NEXT: ret void 67; 68; 69; CHECK-LABEL: @func2( 70; CHECK-NEXT: bb1: 71; CHECK-NEXT: [[F_CE_LOC:%.*]] = alloca i32, align 4 72; CHECK-NEXT: br label [[BB5:%.*]] 73; CHECK: bb2: 74; CHECK-NEXT: [[A:%.*]] = sub i32 [[TMP0:%.*]], [[TMP1:%.*]] 75; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 -1, ptr [[F_CE_LOC]]) 76; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[TMP0]], i32 [[TMP1]], i32 1, ptr [[F_CE_LOC]], i32 0) 77; CHECK-NEXT: [[F_CE_RELOAD:%.*]] = load i32, ptr [[F_CE_LOC]], align 4 78; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[F_CE_LOC]]) 79; CHECK-NEXT: br label [[BB5]] 80; CHECK: bb4: 81; CHECK-NEXT: [[E:%.*]] = add i32 [[TMP0]], [[TMP1]] 82; CHECK-NEXT: br label [[BB2:%.*]] 83; CHECK: bb5: 84; CHECK-NEXT: [[F:%.*]] = phi i32 [ 0, [[BB1:%.*]] ], [ [[F_CE_RELOAD]], [[BB2]] ] 85; CHECK-NEXT: ret void 86; 87; 88; CHECK-LABEL: define internal void @outlined_ir_func_0( 89; CHECK-NEXT: newFuncRoot: 90; CHECK-NEXT: br label [[BB2_TO_OUTLINE:%.*]] 91; CHECK: bb2_to_outline: 92; CHECK-NEXT: [[B:%.*]] = add i32 [[TMP0:%.*]], [[TMP1:%.*]] 93; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[B]], [[TMP2:%.*]] 94; CHECK-NEXT: br i1 [[C]], label [[PHI_BLOCK:%.*]], label [[BB3:%.*]] 95; CHECK: bb3: 96; CHECK-NEXT: [[D:%.*]] = add i32 [[TMP0]], [[TMP1]] 97; CHECK-NEXT: br label [[PHI_BLOCK]] 98; CHECK: bb5.exitStub: 99; CHECK-NEXT: switch i32 [[TMP4:%.*]], label [[FINAL_BLOCK_0:%.*]] [ 100; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_1_0:%.*]] 101; CHECK-NEXT: ] 102; CHECK: output_block_1_0: 103; CHECK-NEXT: store i32 [[TMP5:%.*]], ptr [[TMP3:%.*]], align 4 104; CHECK-NEXT: br label [[FINAL_BLOCK_0]] 105; CHECK: phi_block: 106; CHECK-NEXT: [[TMP5]] = phi i32 [ [[TMP2]], [[BB2_TO_OUTLINE]] ], [ [[TMP2]], [[BB3]] ] 107; CHECK-NEXT: br label [[BB5_EXITSTUB:%.*]] 108; CHECK: final_block_0: 109; CHECK-NEXT: ret void 110; 111