This reverts commit8fdac7cb7a. The issue causing the revert has been fixed a while ago in60b852092c. Original message: Now that SCEVExpander can preserve LCSSA form, we do not have to worry about LCSSA form when trying to look through PHIs. SCEVExpander will take care of inserting LCSSA PHI nodes as required. This increases precision of the analysis in some cases. Reviewed By: mkazantsev, bmahjour Differential Revision: https://reviews.llvm.org/D71539
370 lines
14 KiB
LLVM
370 lines
14 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -loop-reduce -S | FileCheck %s
|
|
|
|
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
|
|
target triple = "i686-pc-windows-msvc"
|
|
|
|
declare i32 @_except_handler3(...)
|
|
declare i32 @__CxxFrameHandler3(...)
|
|
|
|
declare void @external(i32*)
|
|
declare void @reserve()
|
|
|
|
define void @f() personality i32 (...)* @_except_handler3 {
|
|
; CHECK-LABEL: @f(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[THROW:%.*]]
|
|
; CHECK: throw:
|
|
; CHECK-NEXT: invoke void @reserve()
|
|
; CHECK-NEXT: to label [[THROW]] unwind label [[PAD:%.*]]
|
|
; CHECK: pad:
|
|
; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label %unreachable] unwind label [[BLAH2:%.*]]
|
|
; CHECK: unreachable:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] []
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: blah2:
|
|
; CHECK-NEXT: [[CLEANUPPADI4_I_I_I:%.*]] = cleanuppad within none []
|
|
; CHECK-NEXT: br label [[LOOP_BODY:%.*]]
|
|
; CHECK: loop_body:
|
|
; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[ITER:%.*]] ], [ 0, [[BLAH2]] ]
|
|
; CHECK-NEXT: [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV]], -1
|
|
; CHECK-NEXT: [[LSR_IV_NEXT1:%.*]] = inttoptr i32 [[LSR_IV_NEXT]] to i8*
|
|
; CHECK-NEXT: [[TMP100:%.*]] = icmp eq i8* [[LSR_IV_NEXT1]], null
|
|
; CHECK-NEXT: br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
|
|
; CHECK: iter:
|
|
; CHECK-NEXT: br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
|
|
; CHECK: unwind_out:
|
|
; CHECK-NEXT: cleanupret from [[CLEANUPPADI4_I_I_I]] unwind to caller
|
|
;
|
|
entry:
|
|
br label %throw
|
|
|
|
throw: ; preds = %throw, %entry
|
|
%tmp96 = getelementptr inbounds i8, i8* undef, i32 1
|
|
invoke void @reserve()
|
|
to label %throw unwind label %pad
|
|
|
|
pad: ; preds = %throw
|
|
%phi2 = phi i8* [ %tmp96, %throw ]
|
|
%cs = catchswitch within none [label %unreachable] unwind label %blah2
|
|
|
|
unreachable:
|
|
catchpad within %cs []
|
|
unreachable
|
|
|
|
blah2:
|
|
%cleanuppadi4.i.i.i = cleanuppad within none []
|
|
br label %loop_body
|
|
|
|
loop_body: ; preds = %iter, %pad
|
|
%tmp99 = phi i8* [ %tmp101, %iter ], [ %phi2, %blah2 ]
|
|
%tmp100 = icmp eq i8* %tmp99, undef
|
|
br i1 %tmp100, label %unwind_out, label %iter
|
|
|
|
iter: ; preds = %loop_body
|
|
%tmp101 = getelementptr inbounds i8, i8* %tmp99, i32 1
|
|
br i1 undef, label %unwind_out, label %loop_body
|
|
|
|
unwind_out: ; preds = %iter, %loop_body
|
|
cleanupret from %cleanuppadi4.i.i.i unwind to caller
|
|
}
|
|
|
|
define void @g() personality i32 (...)* @_except_handler3 {
|
|
; CHECK-LABEL: @g(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[THROW:%.*]]
|
|
; CHECK: throw:
|
|
; CHECK-NEXT: invoke void @reserve()
|
|
; CHECK-NEXT: to label [[THROW]] unwind label [[PAD:%.*]]
|
|
; CHECK: pad:
|
|
; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label [[UNREACHABLE:%.*]], label %blah] unwind to caller
|
|
; CHECK: unreachable:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] []
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: blah:
|
|
; CHECK-NEXT: [[CATCHPAD:%.*]] = catchpad within [[CS]] []
|
|
; CHECK-NEXT: br label [[LOOP_BODY:%.*]]
|
|
; CHECK: unwind_out:
|
|
; CHECK-NEXT: catchret from [[CATCHPAD]] to label [[LEAVE:%.*]]
|
|
; CHECK: leave:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: loop_body:
|
|
; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[ITER:%.*]] ], [ 0, [[BLAH:%.*]] ]
|
|
; CHECK-NEXT: [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV]], -1
|
|
; CHECK-NEXT: [[LSR_IV_NEXT1:%.*]] = inttoptr i32 [[LSR_IV_NEXT]] to i8*
|
|
; CHECK-NEXT: [[TMP100:%.*]] = icmp eq i8* [[LSR_IV_NEXT1]], null
|
|
; CHECK-NEXT: br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
|
|
; CHECK: iter:
|
|
; CHECK-NEXT: br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
|
|
;
|
|
entry:
|
|
br label %throw
|
|
|
|
throw: ; preds = %throw, %entry
|
|
%tmp96 = getelementptr inbounds i8, i8* undef, i32 1
|
|
invoke void @reserve()
|
|
to label %throw unwind label %pad
|
|
|
|
pad:
|
|
%phi2 = phi i8* [ %tmp96, %throw ]
|
|
%cs = catchswitch within none [label %unreachable, label %blah] unwind to caller
|
|
|
|
unreachable:
|
|
catchpad within %cs []
|
|
unreachable
|
|
|
|
blah:
|
|
%catchpad = catchpad within %cs []
|
|
br label %loop_body
|
|
|
|
unwind_out:
|
|
catchret from %catchpad to label %leave
|
|
|
|
leave:
|
|
ret void
|
|
|
|
loop_body: ; preds = %iter, %pad
|
|
%tmp99 = phi i8* [ %tmp101, %iter ], [ %phi2, %blah ]
|
|
%tmp100 = icmp eq i8* %tmp99, undef
|
|
br i1 %tmp100, label %unwind_out, label %iter
|
|
|
|
iter: ; preds = %loop_body
|
|
%tmp101 = getelementptr inbounds i8, i8* %tmp99, i32 1
|
|
br i1 undef, label %unwind_out, label %loop_body
|
|
}
|
|
|
|
define void @h() personality i32 (...)* @_except_handler3 {
|
|
; CHECK-LABEL: @h(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[THROW:%.*]]
|
|
; CHECK: throw:
|
|
; CHECK-NEXT: invoke void @reserve()
|
|
; CHECK-NEXT: to label [[THROW]] unwind label [[PAD:%.*]]
|
|
; CHECK: pad:
|
|
; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label [[UNREACHABLE:%.*]], label %blug] unwind to caller
|
|
; CHECK: unreachable:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] []
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: blug:
|
|
; CHECK-NEXT: [[CATCHPAD:%.*]] = catchpad within [[CS]] []
|
|
; CHECK-NEXT: br label [[LOOP_BODY:%.*]]
|
|
; CHECK: unwind_out:
|
|
; CHECK-NEXT: catchret from [[CATCHPAD]] to label [[LEAVE:%.*]]
|
|
; CHECK: leave:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: loop_body:
|
|
; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[ITER:%.*]] ], [ 0, [[BLUG:%.*]] ]
|
|
; CHECK-NEXT: [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV]], -1
|
|
; CHECK-NEXT: [[LSR_IV_NEXT1:%.*]] = inttoptr i32 [[LSR_IV_NEXT]] to i8*
|
|
; CHECK-NEXT: [[TMP100:%.*]] = icmp eq i8* [[LSR_IV_NEXT1]], null
|
|
; CHECK-NEXT: br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
|
|
; CHECK: iter:
|
|
; CHECK-NEXT: br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
|
|
;
|
|
entry:
|
|
br label %throw
|
|
|
|
throw: ; preds = %throw, %entry
|
|
%tmp96 = getelementptr inbounds i8, i8* undef, i32 1
|
|
invoke void @reserve()
|
|
to label %throw unwind label %pad
|
|
|
|
pad:
|
|
%cs = catchswitch within none [label %unreachable, label %blug] unwind to caller
|
|
|
|
unreachable:
|
|
catchpad within %cs []
|
|
unreachable
|
|
|
|
blug:
|
|
%phi2 = phi i8* [ %tmp96, %pad ]
|
|
%catchpad = catchpad within %cs []
|
|
br label %loop_body
|
|
|
|
unwind_out:
|
|
catchret from %catchpad to label %leave
|
|
|
|
leave:
|
|
ret void
|
|
|
|
loop_body: ; preds = %iter, %pad
|
|
%tmp99 = phi i8* [ %tmp101, %iter ], [ %phi2, %blug ]
|
|
%tmp100 = icmp eq i8* %tmp99, undef
|
|
br i1 %tmp100, label %unwind_out, label %iter
|
|
|
|
iter: ; preds = %loop_body
|
|
%tmp101 = getelementptr inbounds i8, i8* %tmp99, i32 1
|
|
br i1 undef, label %unwind_out, label %loop_body
|
|
}
|
|
|
|
define void @i() personality i32 (...)* @_except_handler3 {
|
|
; CHECK-LABEL: @i(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[THROW:%.*]]
|
|
; CHECK: throw:
|
|
; CHECK-NEXT: invoke void @reserve()
|
|
; CHECK-NEXT: to label [[THROW]] unwind label [[CATCHPAD:%.*]]
|
|
; CHECK: catchpad:
|
|
; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label %cp_body] unwind label [[CLEANUPPAD:%.*]]
|
|
; CHECK: cp_body:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] []
|
|
; CHECK-NEXT: br label [[LOOP_HEAD:%.*]]
|
|
; CHECK: cleanuppad:
|
|
; CHECK-NEXT: [[TMP1:%.*]] = cleanuppad within none []
|
|
; CHECK-NEXT: br label [[LOOP_HEAD]]
|
|
; CHECK: loop_head:
|
|
; CHECK-NEXT: br label [[LOOP_BODY:%.*]]
|
|
; CHECK: loop_body:
|
|
; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[ITER:%.*]] ], [ 0, [[LOOP_HEAD]] ]
|
|
; CHECK-NEXT: [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV]], -1
|
|
; CHECK-NEXT: [[LSR_IV_NEXT1:%.*]] = inttoptr i32 [[LSR_IV_NEXT]] to i8*
|
|
; CHECK-NEXT: [[TMP100:%.*]] = icmp eq i8* [[LSR_IV_NEXT1]], null
|
|
; CHECK-NEXT: br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
|
|
; CHECK: iter:
|
|
; CHECK-NEXT: br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
|
|
; CHECK: unwind_out:
|
|
; CHECK-NEXT: unreachable
|
|
;
|
|
entry:
|
|
br label %throw
|
|
|
|
throw: ; preds = %throw, %entry
|
|
%tmp96 = getelementptr inbounds i8, i8* undef, i32 1
|
|
invoke void @reserve()
|
|
to label %throw unwind label %catchpad
|
|
|
|
catchpad: ; preds = %throw
|
|
%phi2 = phi i8* [ %tmp96, %throw ]
|
|
%cs = catchswitch within none [label %cp_body] unwind label %cleanuppad
|
|
|
|
cp_body:
|
|
catchpad within %cs []
|
|
br label %loop_head
|
|
|
|
cleanuppad:
|
|
cleanuppad within none []
|
|
br label %loop_head
|
|
|
|
loop_head:
|
|
br label %loop_body
|
|
|
|
loop_body: ; preds = %iter, %catchpad
|
|
%tmp99 = phi i8* [ %tmp101, %iter ], [ %phi2, %loop_head ]
|
|
%tmp100 = icmp eq i8* %tmp99, undef
|
|
br i1 %tmp100, label %unwind_out, label %iter
|
|
|
|
iter: ; preds = %loop_body
|
|
%tmp101 = getelementptr inbounds i8, i8* %tmp99, i32 1
|
|
br i1 undef, label %unwind_out, label %loop_body
|
|
|
|
unwind_out: ; preds = %iter, %loop_body
|
|
unreachable
|
|
}
|
|
|
|
define void @test1(i32* %b, i32* %c) personality i32 (...)* @__CxxFrameHandler3 {
|
|
; CHECK-LABEL: @test1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_COND:%.*]]
|
|
; CHECK: for.cond:
|
|
; CHECK-NEXT: [[D_0:%.*]] = phi i32* [ [[B:%.*]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR:%.*]], [[FOR_INC:%.*]] ]
|
|
; CHECK-NEXT: invoke void @external(i32* [[D_0]])
|
|
; CHECK-NEXT: to label [[FOR_INC]] unwind label [[CATCH_DISPATCH:%.*]]
|
|
; CHECK: for.inc:
|
|
; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i32, i32* [[D_0]], i32 1
|
|
; CHECK-NEXT: br label [[FOR_COND]]
|
|
; CHECK: catch.dispatch:
|
|
; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label %catch] unwind label [[CATCH_DISPATCH_2:%.*]]
|
|
; CHECK: catch:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] [i8* null, i32 64, i8* null]
|
|
; CHECK-NEXT: catchret from [[TMP0]] to label [[TRY_CONT:%.*]]
|
|
; CHECK: try.cont:
|
|
; CHECK-NEXT: invoke void @external(i32* [[C:%.*]])
|
|
; CHECK-NEXT: to label [[TRY_CONT_7:%.*]] unwind label [[CATCH_DISPATCH_2]]
|
|
; CHECK: catch.dispatch.2:
|
|
; CHECK-NEXT: [[E_0:%.*]] = phi i32* [ [[C]], [[TRY_CONT]] ], [ [[B]], [[CATCH_DISPATCH]] ]
|
|
; CHECK-NEXT: [[CS2:%.*]] = catchswitch within none [label %catch.4] unwind to caller
|
|
; CHECK: catch.4:
|
|
; CHECK-NEXT: [[TMP1:%.*]] = catchpad within [[CS2]] [i8* null, i32 64, i8* null]
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: try.cont.7:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.inc, %entry
|
|
%d.0 = phi i32* [ %b, %entry ], [ %incdec.ptr, %for.inc ]
|
|
invoke void @external(i32* %d.0)
|
|
to label %for.inc unwind label %catch.dispatch
|
|
|
|
for.inc: ; preds = %for.cond
|
|
%incdec.ptr = getelementptr inbounds i32, i32* %d.0, i32 1
|
|
br label %for.cond
|
|
|
|
catch.dispatch: ; preds = %for.cond
|
|
%cs = catchswitch within none [label %catch] unwind label %catch.dispatch.2
|
|
|
|
catch: ; preds = %catch.dispatch
|
|
%0 = catchpad within %cs [i8* null, i32 64, i8* null]
|
|
catchret from %0 to label %try.cont
|
|
|
|
try.cont: ; preds = %catch
|
|
invoke void @external(i32* %c)
|
|
to label %try.cont.7 unwind label %catch.dispatch.2
|
|
|
|
catch.dispatch.2: ; preds = %try.cont, %catchendblock
|
|
%e.0 = phi i32* [ %c, %try.cont ], [ %b, %catch.dispatch ]
|
|
%cs2 = catchswitch within none [label %catch.4] unwind to caller
|
|
|
|
catch.4: ; preds = %catch.dispatch.2
|
|
catchpad within %cs2 [i8* null, i32 64, i8* null]
|
|
unreachable
|
|
|
|
try.cont.7: ; preds = %try.cont
|
|
ret void
|
|
}
|
|
|
|
define i32 @test2() personality i32 (...)* @_except_handler3 {
|
|
; CHECK-LABEL: @test2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: invoke void @reserve()
|
|
; CHECK-NEXT: to label [[FOR_INC]] unwind label [[CATCH_DISPATCH:%.*]]
|
|
; CHECK: catch.dispatch:
|
|
; CHECK-NEXT: [[TMP18:%.*]] = catchswitch within none [label %catch.handler] unwind to caller
|
|
; CHECK: catch.handler:
|
|
; CHECK-NEXT: [[PHI_LCSSA:%.*]] = phi i32 [ [[PHI]], [[CATCH_DISPATCH]] ]
|
|
; CHECK-NEXT: [[TMP19:%.*]] = catchpad within [[TMP18]] [i8* null]
|
|
; CHECK-NEXT: catchret from [[TMP19]] to label [[DONE:%.*]]
|
|
; CHECK: done:
|
|
; CHECK-NEXT: ret i32 [[PHI_LCSSA]]
|
|
; CHECK: for.inc:
|
|
; CHECK-NEXT: [[INC]] = add i32 [[PHI]], 1
|
|
; CHECK-NEXT: br label [[FOR_BODY]]
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %for.inc, %entry
|
|
%phi = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
|
|
invoke void @reserve()
|
|
to label %for.inc unwind label %catch.dispatch
|
|
|
|
catch.dispatch: ; preds = %for.body
|
|
%tmp18 = catchswitch within none [label %catch.handler] unwind to caller
|
|
|
|
catch.handler: ; preds = %catch.dispatch
|
|
%phi.lcssa = phi i32 [ %phi, %catch.dispatch ]
|
|
%tmp19 = catchpad within %tmp18 [i8* null]
|
|
catchret from %tmp19 to label %done
|
|
|
|
done:
|
|
ret i32 %phi.lcssa
|
|
|
|
for.inc: ; preds = %for.body
|
|
%inc = add i32 %phi, 1
|
|
br label %for.body
|
|
}
|