diff options
Diffstat (limited to 'contrib/llvm/lib/Transforms/Scalar/MakeGuardsExplicit.cpp')
| -rw-r--r-- | contrib/llvm/lib/Transforms/Scalar/MakeGuardsExplicit.cpp | 119 |
1 files changed, 0 insertions, 119 deletions
diff --git a/contrib/llvm/lib/Transforms/Scalar/MakeGuardsExplicit.cpp b/contrib/llvm/lib/Transforms/Scalar/MakeGuardsExplicit.cpp deleted file mode 100644 index 789232e0f5ce..000000000000 --- a/contrib/llvm/lib/Transforms/Scalar/MakeGuardsExplicit.cpp +++ /dev/null @@ -1,119 +0,0 @@ -//===- MakeGuardsExplicit.cpp - Turn guard intrinsics into guard branches -===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This pass lowers the @llvm.experimental.guard intrinsic to the new form of -// guard represented as widenable explicit branch to the deopt block. The -// difference between this pass and LowerGuardIntrinsic is that after this pass -// the guard represented as intrinsic: -// -// call void(i1, ...) @llvm.experimental.guard(i1 %old_cond) [ "deopt"() ] -// -// transforms to a guard represented as widenable explicit branch: -// -// %widenable_cond = call i1 @llvm.experimental.widenable.condition() -// br i1 (%old_cond & %widenable_cond), label %guarded, label %deopt -// -// Here: -// - The semantics of @llvm.experimental.widenable.condition allows to replace -// %widenable_cond with the construction (%widenable_cond & %any_other_cond) -// without loss of correctness; -// - %guarded is the lower part of old guard intrinsic's parent block split by -// the intrinsic call; -// - %deopt is a block containing a sole call to @llvm.experimental.deoptimize -// intrinsic. -// -// Therefore, this branch preserves the property of widenability. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Transforms/Scalar/MakeGuardsExplicit.h" -#include "llvm/Analysis/GuardUtils.h" -#include "llvm/IR/InstIterator.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/Pass.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/GuardUtils.h" - -using namespace llvm; - -namespace { -struct MakeGuardsExplicitLegacyPass : public FunctionPass { - static char ID; - MakeGuardsExplicitLegacyPass() : FunctionPass(ID) { - initializeMakeGuardsExplicitLegacyPassPass(*PassRegistry::getPassRegistry()); - } - - bool runOnFunction(Function &F) override; -}; -} - -static void turnToExplicitForm(CallInst *Guard, Function *DeoptIntrinsic) { - // Replace the guard with an explicit branch (just like in GuardWidening). - BasicBlock *BB = Guard->getParent(); - makeGuardControlFlowExplicit(DeoptIntrinsic, Guard); - BranchInst *ExplicitGuard = cast<BranchInst>(BB->getTerminator()); - assert(ExplicitGuard->isConditional() && "Must be!"); - - // We want the guard to be expressed as explicit control flow, but still be - // widenable. For that, we add Widenable Condition intrinsic call to the - // guard's condition. - IRBuilder<> B(ExplicitGuard); - auto *WidenableCondition = - B.CreateIntrinsic(Intrinsic::experimental_widenable_condition, - {}, {}, nullptr, "widenable_cond"); - WidenableCondition->setCallingConv(Guard->getCallingConv()); - auto *NewCond = - B.CreateAnd(ExplicitGuard->getCondition(), WidenableCondition); - NewCond->setName("exiplicit_guard_cond"); - ExplicitGuard->setCondition(NewCond); - Guard->eraseFromParent(); -} - -static bool explicifyGuards(Function &F) { - // Check if we can cheaply rule out the possibility of not having any work to - // do. - auto *GuardDecl = F.getParent()->getFunction( - Intrinsic::getName(Intrinsic::experimental_guard)); - if (!GuardDecl || GuardDecl->use_empty()) - return false; - - SmallVector<CallInst *, 8> GuardIntrinsics; - for (auto &I : instructions(F)) - if (isGuard(&I)) - GuardIntrinsics.push_back(cast<CallInst>(&I)); - - if (GuardIntrinsics.empty()) - return false; - - auto *DeoptIntrinsic = Intrinsic::getDeclaration( - F.getParent(), Intrinsic::experimental_deoptimize, {F.getReturnType()}); - DeoptIntrinsic->setCallingConv(GuardDecl->getCallingConv()); - - for (auto *Guard : GuardIntrinsics) - turnToExplicitForm(Guard, DeoptIntrinsic); - - return true; -} - -bool MakeGuardsExplicitLegacyPass::runOnFunction(Function &F) { - return explicifyGuards(F); -} - -char MakeGuardsExplicitLegacyPass::ID = 0; -INITIALIZE_PASS(MakeGuardsExplicitLegacyPass, "make-guards-explicit", - "Lower the guard intrinsic to explicit control flow form", - false, false) - -PreservedAnalyses MakeGuardsExplicitPass::run(Function &F, - FunctionAnalysisManager &) { - if (explicifyGuards(F)) - return PreservedAnalyses::none(); - return PreservedAnalyses::all(); -} |
