[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:
Sanjoy Das 2016-04-30 00:55:59 +00:00
parent 1befea2bdc
commit 47cf2affbd
3 changed files with 21 additions and 1 deletions

View File

@ -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``

View File

@ -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}, "");

View File

@ -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
}