X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=docs%2FFaultMaps.rst;h=4ecdd86d7693c4bb31b38630176200c6cd757389;hb=f7e51b209e3c7c4013b0346396ab344130bb9c6a;hp=d6274fa0a2ce803b7e296b5c2cacac6cc06cd651;hpb=1991e2a4dfc771c1e8d944cbbd8ac44d0592cedd;p=oota-llvm.git diff --git a/docs/FaultMaps.rst b/docs/FaultMaps.rst index d6274fa0a2c..4ecdd86d769 100644 --- a/docs/FaultMaps.rst +++ b/docs/FaultMaps.rst @@ -47,8 +47,81 @@ The format of this section is uint32 : NumFaultingPCs uint32 : Reserved (expected to be 0) FunctionFaultInfo[NumFaultingPCs] { - uint32 : FaultType = FaultMaps::FaultingLoad (only legal value currently) + uint32 : FaultKind = FaultMaps::FaultingLoad (only legal value currently) uint32 : FaultingPCOffset - uint32 : handlerPCOffset + uint32 : HandlerPCOffset } } + + +The ``ImplicitNullChecks`` pass +=============================== + +The ``ImplicitNullChecks`` pass transforms explicit control flow for +checking if a pointer is ``null``, like: + +.. code-block:: llvm + + %ptr = call i32* @get_ptr() + %ptr_is_null = icmp i32* %ptr, null + br i1 %ptr_is_null, label %is_null, label %not_null, !make.implicit !0 + + not_null: + %t = load i32, i32* %ptr + br label %do_something_with_t + + is_null: + call void @HFC() + unreachable + + !0 = !{} + +to control flow implicit in the instruction loading or storing through +the pointer being null checked: + +.. code-block:: llvm + + %ptr = call i32* @get_ptr() + %t = load i32, i32* %ptr ;; handler-pc = label %is_null + br label %do_something_with_t + + is_null: + call void @HFC() + unreachable + +This transform happens at the ``MachineInstr`` level, not the LLVM IR +level (so the above example is only representative, not literal). The +``ImplicitNullChecks`` pass runs during codegen, if +``-enable-implicit-null-checks`` is passed to ``llc``. + +The ``ImplicitNullChecks`` pass adds entries to the +``__llvm_faultmaps`` section described above as needed. + +``make.implicit`` metadata +-------------------------- + +Making null checks implicit is an aggressive optimization, and it can +be a net performance pessimization if too many memory operations end +up faulting because of it. A language runtime typically needs to +ensure that only a negligible number of implicit null checks actually +fault once the application has reached a steady state. A standard way +of doing this is by healing failed implicit null checks into explicit +null checks via code patching or recompilation. It follows that there +are two requirements an explicit null check needs to satisfy for it to +be profitable to convert it to an implicit null check: + + 1. The case where the pointer is actually null (i.e. the "failing" + case) is extremely rare. + + 2. The failing path heals the implicit null check into an explicit + null check so that the application does not repeatedly page + fault. + +The frontend is expected to mark branches that satisfy (1) and (2) +using a ``!make.implicit`` metadata node (the actual content of the +metadata node is ignored). Only branches that are marked with +``!make.implicit`` metadata are considered as candidates for +conversion into implicit null checks. + +(Note that while we could deal with (1) using profiling data, dealing +with (2) requires some information not present in branch profiles.)