When outlining a phi node, if the the incoming branch is a block contained in the region and the branch from that block is not outlined, we create broken code. The fix is to recognize when that branch from the included incoming block is not contained, and ignore the region. Reviewer: paquette Differential Revision: https://reviews.llvm.org/D121311
101 lines
3.7 KiB
LLVM
101 lines
3.7 KiB
LLVM
; 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
|
|
|
|
; Show that we do not outline when all of the phi nodes in the beginning
|
|
; block are included not in the region.
|
|
|
|
define void @function1(i32* %a, i32* %b) {
|
|
entry:
|
|
%0 = alloca i32, align 4
|
|
%c = load i32, i32* %0, align 4
|
|
%y = add i32 %c, %c
|
|
br label %test1
|
|
dummy:
|
|
ret void
|
|
test1:
|
|
%1 = phi i32 [ %e, %test1 ], [ %y, %entry ]
|
|
%2 = phi i32 [ %e, %test1 ], [ %y, %entry ]
|
|
%e = load i32, i32* %0, align 4
|
|
%3 = add i32 %c, %c
|
|
%4 = sub i32 %c, %c
|
|
br i1 true, label %first, label %test1
|
|
first:
|
|
ret void
|
|
}
|
|
|
|
define void @function2(i32* %a, i32* %b) {
|
|
entry:
|
|
%0 = alloca i32, align 4
|
|
%c = load i32, i32* %0, align 4
|
|
%y = mul i32 %c, %c
|
|
br label %test1
|
|
dummy:
|
|
ret void
|
|
test1:
|
|
%1 = phi i32 [ %e, %test1 ], [ %y, %entry ]
|
|
%2 = phi i32 [ %y, %entry ], [ %e, %test1 ]
|
|
%e = load i32, i32* %0, align 4
|
|
%3 = add i32 %c, %c
|
|
%4 = mul i32 %c, %c
|
|
br i1 true, label %first, label %test1
|
|
first:
|
|
ret void
|
|
}
|
|
; CHECK-LABEL: @function1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[E_LOC:%.*]] = alloca i32, align 4
|
|
; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
|
|
; CHECK-NEXT: [[C:%.*]] = load i32, i32* [[TMP0]], align 4
|
|
; CHECK-NEXT: [[Y:%.*]] = add i32 [[C]], [[C]]
|
|
; CHECK-NEXT: br label [[TEST1:%.*]]
|
|
; CHECK: dummy:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: test1:
|
|
; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[E_RELOAD:%.*]], [[TEST1]] ], [ [[Y]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[E_RELOAD]], [[TEST1]] ], [ [[Y]], [[ENTRY]] ]
|
|
; CHECK-NEXT: [[LT_CAST:%.*]] = bitcast i32* [[E_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* [[TMP0]], i32 [[C]], i32* [[E_LOC]])
|
|
; CHECK-NEXT: [[E_RELOAD]] = load i32, i32* [[E_LOC]], align 4
|
|
; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST]])
|
|
; CHECK-NEXT: [[TMP3:%.*]] = sub i32 [[C]], [[C]]
|
|
; CHECK-NEXT: br i1 true, label [[FIRST:%.*]], label [[TEST1]]
|
|
; CHECK: first:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
;
|
|
; CHECK-LABEL: @function2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[E_LOC:%.*]] = alloca i32, align 4
|
|
; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
|
|
; CHECK-NEXT: [[C:%.*]] = load i32, i32* [[TMP0]], align 4
|
|
; CHECK-NEXT: [[Y:%.*]] = mul i32 [[C]], [[C]]
|
|
; CHECK-NEXT: br label [[TEST1:%.*]]
|
|
; CHECK: dummy:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: test1:
|
|
; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[E_RELOAD:%.*]], [[TEST1]] ], [ [[Y]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[Y]], [[ENTRY]] ], [ [[E_RELOAD]], [[TEST1]] ]
|
|
; CHECK-NEXT: [[LT_CAST:%.*]] = bitcast i32* [[E_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* [[TMP0]], i32 [[C]], i32* [[E_LOC]])
|
|
; CHECK-NEXT: [[E_RELOAD]] = load i32, i32* [[E_LOC]], align 4
|
|
; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST]])
|
|
; CHECK-NEXT: [[TMP3:%.*]] = mul i32 [[C]], [[C]]
|
|
; CHECK-NEXT: br i1 true, label [[FIRST:%.*]], label [[TEST1]]
|
|
; CHECK: first:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
;
|
|
; CHECK-LABEL: define internal void @outlined_ir_func_0(
|
|
; CHECK-NEXT: newFuncRoot:
|
|
; CHECK-NEXT: br label [[TEST1_TO_OUTLINE:%.*]]
|
|
; CHECK: test1_to_outline:
|
|
; CHECK-NEXT: [[E:%.*]] = load i32, i32* [[TMP0:%.*]], align 4
|
|
; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP1:%.*]], [[TMP1]]
|
|
; CHECK-NEXT: br label [[TEST1_AFTER_OUTLINE_EXITSTUB:%.*]]
|
|
; CHECK: test1_after_outline.exitStub:
|
|
; CHECK-NEXT: store i32 [[E]], i32* [[TMP2:%.*]], align 4
|
|
; CHECK-NEXT: ret void
|
|
;
|