Introduce @llvm.experimental.deoptimize
Summary:
This intrinsic, together with deoptimization operand bundles, allow
frontends to express transfer of control and frame-local state from
one (typically more specialized, hence faster) version of a function
into another (typically more generic, hence slower) version.
In languages with a fully integrated managed runtime this intrinsic can
be used to implement "uncommon trap" like functionality. In unmanaged
languages like C and C++, this intrinsic can be used to represent the
slow paths of specialized functions.
Note: this change does not address how `@llvm.experimental_deoptimize`
is lowered. That will be done in a later change.
Reviewers: chandlerc, rnk, atrick, reames
Subscribers: llvm-commits, kmod, mjacob, maksfb, mcrosier, JosephTremoulet
Differential Revision: http://reviews.llvm.org/D17732
llvm-svn: 263281
2016-03-12 03:08:34 +08:00
|
|
|
; RUN: not opt -verify < %s 2>&1 | FileCheck %s
|
|
|
|
|
|
|
|
declare i8 @llvm.experimental.deoptimize.i8(...)
|
|
|
|
declare void @llvm.experimental.deoptimize.isVoid(...)
|
2016-05-12 09:17:38 +08:00
|
|
|
declare cc40 void @llvm.experimental.deoptimize.double(...)
|
Introduce @llvm.experimental.deoptimize
Summary:
This intrinsic, together with deoptimization operand bundles, allow
frontends to express transfer of control and frame-local state from
one (typically more specialized, hence faster) version of a function
into another (typically more generic, hence slower) version.
In languages with a fully integrated managed runtime this intrinsic can
be used to implement "uncommon trap" like functionality. In unmanaged
languages like C and C++, this intrinsic can be used to represent the
slow paths of specialized functions.
Note: this change does not address how `@llvm.experimental_deoptimize`
is lowered. That will be done in a later change.
Reviewers: chandlerc, rnk, atrick, reames
Subscribers: llvm-commits, kmod, mjacob, maksfb, mcrosier, JosephTremoulet
Differential Revision: http://reviews.llvm.org/D17732
llvm-svn: 263281
2016-03-12 03:08:34 +08:00
|
|
|
|
|
|
|
declare void @unknown()
|
|
|
|
|
|
|
|
define void @f_notail() {
|
|
|
|
entry:
|
|
|
|
call void(...) @llvm.experimental.deoptimize.isVoid(i32 0) [ "deopt"() ]
|
|
|
|
; CHECK: calls to experimental_deoptimize must be followed by a return
|
|
|
|
call void @unknown()
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
define void @f_nodeopt() {
|
|
|
|
entry:
|
|
|
|
call void(...) @llvm.experimental.deoptimize.isVoid()
|
|
|
|
; CHECK: experimental_deoptimize must have exactly one "deopt" operand bundle
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
define void @f_invoke() personality i8 3 {
|
|
|
|
entry:
|
|
|
|
invoke void(...) @llvm.experimental.deoptimize.isVoid(i32 0, float 0.0) to label %ok unwind label %not_ok
|
|
|
|
; CHECK: experimental_deoptimize cannot be invoked
|
|
|
|
|
|
|
|
ok:
|
|
|
|
ret void
|
|
|
|
|
|
|
|
not_ok:
|
|
|
|
%0 = landingpad { i8*, i32 }
|
|
|
|
filter [0 x i8*] zeroinitializer
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @f_incorrect_return() {
|
|
|
|
entry:
|
|
|
|
%val = call i8(...) @llvm.experimental.deoptimize.i8() [ "deopt"() ]
|
|
|
|
; CHECK: calls to experimental_deoptimize must be followed by a return of the value computed by experimental_deoptimize
|
|
|
|
ret i8 0
|
|
|
|
}
|
2016-05-12 09:17:38 +08:00
|
|
|
|
|
|
|
; CHECK: All llvm.experimental.deoptimize declarations must have the same calling convention
|