mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-21 21:29:41 +00:00
same basic block, and it's not safe to insert code in the successor blocks if the edges are critical edges. Splitting those edges is possible, but undesirable, especially on the unwind side. Instead, make the bottom-up code motion to consider invokes to be part of their successor blocks, rather than part of their parent blocks, so that it doesn't push code past them and onto the edges. This fixes PR12307. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153343 91177308-0d34-0410-b5e6-96231b3b80d8
176 lines
5.4 KiB
LLVM
176 lines
5.4 KiB
LLVM
; RUN: opt -S -objc-arc < %s | FileCheck %s
|
|
|
|
declare i8* @objc_retain(i8*)
|
|
declare void @objc_release(i8*)
|
|
declare i8* @objc_retainAutoreleasedReturnValue(i8*)
|
|
declare i8* @objc_msgSend(i8*, i8*, ...)
|
|
declare void @use_pointer(i8*)
|
|
declare void @callee()
|
|
|
|
; ARCOpt shouldn't try to move the releases to the block containing the invoke.
|
|
|
|
; CHECK: define void @test0(
|
|
; CHECK: invoke.cont:
|
|
; CHECK: call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
|
|
; CHECK: ret void
|
|
; CHECK: lpad:
|
|
; CHECK: call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
|
|
; CHECK: ret void
|
|
define void @test0(i8* %zipFile) {
|
|
entry:
|
|
call i8* @objc_retain(i8* %zipFile) nounwind
|
|
call void @use_pointer(i8* %zipFile)
|
|
invoke void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*)*)(i8* %zipFile)
|
|
to label %invoke.cont unwind label %lpad
|
|
|
|
invoke.cont: ; preds = %entry
|
|
call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
|
|
ret void
|
|
|
|
lpad: ; preds = %entry
|
|
%exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
|
|
cleanup
|
|
call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
|
|
ret void
|
|
}
|
|
|
|
; ARCOpt should move the release before the callee calls.
|
|
|
|
; CHECK: define void @test1(
|
|
; CHECK: invoke.cont:
|
|
; CHECK: call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
|
|
; CHECK: call void @callee()
|
|
; CHECK: br label %done
|
|
; CHECK: lpad:
|
|
; CHECK: call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
|
|
; CHECK: call void @callee()
|
|
; CHECK: br label %done
|
|
; CHECK: done:
|
|
; CHECK-NEXT: ret void
|
|
define void @test1(i8* %zipFile) {
|
|
entry:
|
|
call i8* @objc_retain(i8* %zipFile) nounwind
|
|
call void @use_pointer(i8* %zipFile)
|
|
invoke void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*)*)(i8* %zipFile)
|
|
to label %invoke.cont unwind label %lpad
|
|
|
|
invoke.cont: ; preds = %entry
|
|
call void @callee()
|
|
br label %done
|
|
|
|
lpad: ; preds = %entry
|
|
%exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
|
|
cleanup
|
|
call void @callee()
|
|
br label %done
|
|
|
|
done:
|
|
call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
|
|
ret void
|
|
}
|
|
|
|
; The optimizer should ignore invoke unwind paths consistently.
|
|
; PR12265
|
|
|
|
; CHECK: define void @test2() {
|
|
; CHECK: invoke.cont:
|
|
; CHECK-NEXT: call i8* @objc_retain
|
|
; CHEK-NOT: @objc
|
|
; CHECK: finally.cont:
|
|
; CHECK-NEXT: call void @objc_release
|
|
; CHEK-NOT: @objc
|
|
; CHECK: finally.rethrow:
|
|
; CHEK-NOT: @objc
|
|
; CHECK: }
|
|
define void @test2() {
|
|
entry:
|
|
%call = invoke i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* ()*)()
|
|
to label %invoke.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
|
|
|
|
invoke.cont: ; preds = %entry
|
|
%tmp1 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
|
|
call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void ()*)(), !clang.arc.no_objc_arc_exceptions !0
|
|
invoke void @use_pointer(i8* %call)
|
|
to label %finally.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
|
|
|
|
finally.cont: ; preds = %invoke.cont
|
|
tail call void @objc_release(i8* %call) nounwind, !clang.imprecise_release !0
|
|
ret void
|
|
|
|
finally.rethrow: ; preds = %invoke.cont, %entry
|
|
%tmp2 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
|
|
catch i8* null
|
|
unreachable
|
|
}
|
|
|
|
; Don't try to place code on invoke critical edges.
|
|
|
|
; CHECK: define void @test3(
|
|
; CHECK: if.end:
|
|
; CHECK-NEXT: call void @objc_release(i8* %p) nounwind
|
|
; CHECK-NEXT: ret void
|
|
define void @test3(i8* %p, i1 %b) {
|
|
entry:
|
|
%0 = call i8* @objc_retain(i8* %p)
|
|
call void @callee()
|
|
br i1 %b, label %if.else, label %if.then
|
|
|
|
if.then:
|
|
invoke void @use_pointer(i8* %p)
|
|
to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
|
|
|
|
if.else:
|
|
invoke void @use_pointer(i8* %p)
|
|
to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
|
|
|
|
lpad:
|
|
%r = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
|
|
cleanup
|
|
ret void
|
|
|
|
if.end:
|
|
call void @objc_release(i8* %p)
|
|
ret void
|
|
}
|
|
|
|
; Like test3, but with ARC-relevant exception handling.
|
|
|
|
; CHECK: define void @test4(
|
|
; CHECK: lpad:
|
|
; CHECK-NEXT: %r = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
|
|
; CHECK-NEXT: cleanup
|
|
; CHECK-NEXT: call void @objc_release(i8* %p) nounwind
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: if.end:
|
|
; CHECK-NEXT: call void @objc_release(i8* %p) nounwind
|
|
; CHECK-NEXT: ret void
|
|
define void @test4(i8* %p, i1 %b) {
|
|
entry:
|
|
%0 = call i8* @objc_retain(i8* %p)
|
|
call void @callee()
|
|
br i1 %b, label %if.else, label %if.then
|
|
|
|
if.then:
|
|
invoke void @use_pointer(i8* %p)
|
|
to label %if.end unwind label %lpad
|
|
|
|
if.else:
|
|
invoke void @use_pointer(i8* %p)
|
|
to label %if.end unwind label %lpad
|
|
|
|
lpad:
|
|
%r = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
|
|
cleanup
|
|
call void @objc_release(i8* %p)
|
|
ret void
|
|
|
|
if.end:
|
|
call void @objc_release(i8* %p)
|
|
ret void
|
|
}
|
|
|
|
declare i32 @__gxx_personality_v0(...)
|
|
declare i32 @__objc_personality_v0(...)
|
|
|
|
!0 = metadata !{}
|