forked from OSchip/llvm-project
[LowerGuardIntrinsics] Keep track of !make.implicit metadata
If a guard call being lowered by LowerGuardIntrinsics has the `!make.implicit` metadata attached, then reattach the metadata to the branch in the resulting expanded form of the intrinsic. This allows us to implement null checks as guards and still get the benefit of implicit null checks. llvm-svn: 268148
This commit is contained in:
parent
1befea2bdc
commit
47cf2affbd
|
@ -12375,7 +12375,7 @@ equivalent to:
|
|||
|
||||
define void @llvm.experimental.guard(i1 %pred, <args...>) {
|
||||
%realPred = and i1 %pred, undef
|
||||
br i1 %realPred, label %continue, label %leave
|
||||
br i1 %realPred, label %continue, label %leave [, !make.implicit !{}]
|
||||
|
||||
leave:
|
||||
call void @llvm.experimental.deoptimize(<args...>) [ "deopt"() ]
|
||||
|
@ -12385,6 +12385,11 @@ equivalent to:
|
|||
ret void
|
||||
}
|
||||
|
||||
|
||||
with the optional ``[, !make.implicit !{}]`` present if and only if it
|
||||
is present on the call site. For more details on ``!make.implicit``,
|
||||
see :doc:`FaultMaps`.
|
||||
|
||||
In words, ``@llvm.experimental.guard`` executes the attached
|
||||
``"deopt"`` continuation if (but **not** only if) its first argument
|
||||
is ``false``. Since the optimizer is allowed to replace the ``undef``
|
||||
|
|
|
@ -56,6 +56,9 @@ static void MakeGuardControlFlowExplicit(Function *DeoptIntrinsic,
|
|||
CheckBI->getSuccessor(0)->setName("guarded");
|
||||
CheckBI->getSuccessor(1)->setName("deopt");
|
||||
|
||||
if (auto *MD = CI->getMetadata(LLVMContext::MD_make_implicit))
|
||||
CheckBI->setMetadata(LLVMContext::MD_make_implicit, MD);
|
||||
|
||||
IRBuilder<> B(DeoptBlockTerm);
|
||||
auto *DeoptCall = B.CreateCall(DeoptIntrinsic, Args, {DeoptOB}, "");
|
||||
|
||||
|
|
|
@ -60,3 +60,15 @@ define i32 @f_zero_args(i1* %c_ptr) {
|
|||
; CHECK: guarded:
|
||||
; CHECK-NEXT: ret i32 500
|
||||
}
|
||||
|
||||
define i8 @f_with_make_implicit_md(i32* %ptr) {
|
||||
; CHECK-LABEL: @f_with_make_implicit_md(
|
||||
; CHECK: br i1 %notNull, label %guarded, label %deopt, !make.implicit !0
|
||||
; CHECK: deopt:
|
||||
; CHECK-NEXT: %deoptcall = call i8 (...) @llvm.experimental.deoptimize.i8(i32 1) [ "deopt"(i32 1) ]
|
||||
; CHECK-NEXT: ret i8 %deoptcall
|
||||
|
||||
%notNull = icmp ne i32* %ptr, null
|
||||
call void(i1, ...) @llvm.experimental.guard(i1 %notNull, i32 1) [ "deopt"(i32 1) ], !make.implicit !{}
|
||||
ret i8 5
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue