63 lines · cpp
1//===- LowerGuardIntrinsic.cpp - Lower the guard intrinsic ---------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This pass lowers the llvm.experimental.guard intrinsic to a conditional call10// to @llvm.experimental.deoptimize. Once this happens, the guard can no longer11// be widened.12//13//===----------------------------------------------------------------------===//14 15#include "llvm/Transforms/Scalar/LowerGuardIntrinsic.h"16#include "llvm/ADT/SmallVector.h"17#include "llvm/IR/Function.h"18#include "llvm/IR/Instructions.h"19#include "llvm/IR/Intrinsics.h"20#include "llvm/Transforms/Utils/GuardUtils.h"21 22using namespace llvm;23 24static bool lowerGuardIntrinsic(Function &F) {25 // Check if we can cheaply rule out the possibility of not having any work to26 // do.27 auto *GuardDecl = Intrinsic::getDeclarationIfExists(28 F.getParent(), Intrinsic::experimental_guard);29 if (!GuardDecl || GuardDecl->use_empty())30 return false;31 32 SmallVector<CallInst *, 8> ToLower;33 // Traverse through the users of GuardDecl.34 // This is presumably cheaper than traversing all instructions in the35 // function.36 for (auto *U : GuardDecl->users())37 if (auto *CI = dyn_cast<CallInst>(U))38 if (CI->getFunction() == &F)39 ToLower.push_back(CI);40 41 if (ToLower.empty())42 return false;43 44 auto *DeoptIntrinsic = Intrinsic::getOrInsertDeclaration(45 F.getParent(), Intrinsic::experimental_deoptimize, {F.getReturnType()});46 DeoptIntrinsic->setCallingConv(GuardDecl->getCallingConv());47 48 for (auto *CI : ToLower) {49 makeGuardControlFlowExplicit(DeoptIntrinsic, CI, false);50 CI->eraseFromParent();51 }52 53 return true;54}55 56PreservedAnalyses LowerGuardIntrinsicPass::run(Function &F,57 FunctionAnalysisManager &AM) {58 if (lowerGuardIntrinsic(F))59 return PreservedAnalyses::none();60 61 return PreservedAnalyses::all();62}63