Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Scalar/LowerConstantIntrinsics.cpp
35269 views
//===- LowerConstantIntrinsics.cpp - Lower constant intrinsic calls -------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This pass lowers all remaining 'objectsize' 'is.constant' intrinsic calls9// and provides constant propagation and basic CFG cleanup on the result.10//11//===----------------------------------------------------------------------===//1213#include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h"14#include "llvm/ADT/PostOrderIterator.h"15#include "llvm/ADT/SetVector.h"16#include "llvm/ADT/Statistic.h"17#include "llvm/Analysis/DomTreeUpdater.h"18#include "llvm/Analysis/GlobalsModRef.h"19#include "llvm/Analysis/InstructionSimplify.h"20#include "llvm/Analysis/MemoryBuiltins.h"21#include "llvm/Analysis/TargetLibraryInfo.h"22#include "llvm/IR/BasicBlock.h"23#include "llvm/IR/Constants.h"24#include "llvm/IR/Dominators.h"25#include "llvm/IR/Function.h"26#include "llvm/IR/Instructions.h"27#include "llvm/IR/IntrinsicInst.h"28#include "llvm/IR/PatternMatch.h"29#include "llvm/InitializePasses.h"30#include "llvm/Pass.h"31#include "llvm/Support/Debug.h"32#include "llvm/Transforms/Scalar.h"33#include "llvm/Transforms/Utils/Local.h"34#include <optional>3536using namespace llvm;37using namespace llvm::PatternMatch;3839#define DEBUG_TYPE "lower-is-constant-intrinsic"4041STATISTIC(IsConstantIntrinsicsHandled,42"Number of 'is.constant' intrinsic calls handled");43STATISTIC(ObjectSizeIntrinsicsHandled,44"Number of 'objectsize' intrinsic calls handled");4546static Value *lowerIsConstantIntrinsic(IntrinsicInst *II) {47if (auto *C = dyn_cast<Constant>(II->getOperand(0)))48if (C->isManifestConstant())49return ConstantInt::getTrue(II->getType());50return ConstantInt::getFalse(II->getType());51}5253static bool replaceConditionalBranchesOnConstant(Instruction *II,54Value *NewValue,55DomTreeUpdater *DTU) {56bool HasDeadBlocks = false;57SmallSetVector<Instruction *, 8> UnsimplifiedUsers;58replaceAndRecursivelySimplify(II, NewValue, nullptr, nullptr, nullptr,59&UnsimplifiedUsers);60// UnsimplifiedUsers can contain PHI nodes that may be removed when61// replacing the branch instructions, so use a value handle worklist62// to handle those possibly removed instructions.63SmallVector<WeakVH, 8> Worklist(UnsimplifiedUsers.begin(),64UnsimplifiedUsers.end());6566for (auto &VH : Worklist) {67BranchInst *BI = dyn_cast_or_null<BranchInst>(VH);68if (!BI)69continue;70if (BI->isUnconditional())71continue;7273BasicBlock *Target, *Other;74if (match(BI->getOperand(0), m_Zero())) {75Target = BI->getSuccessor(1);76Other = BI->getSuccessor(0);77} else if (match(BI->getOperand(0), m_One())) {78Target = BI->getSuccessor(0);79Other = BI->getSuccessor(1);80} else {81Target = nullptr;82Other = nullptr;83}84if (Target && Target != Other) {85BasicBlock *Source = BI->getParent();86Other->removePredecessor(Source);8788Instruction *NewBI = BranchInst::Create(Target, Source);89NewBI->setDebugLoc(BI->getDebugLoc());90BI->eraseFromParent();9192if (DTU)93DTU->applyUpdates({{DominatorTree::Delete, Source, Other}});94if (pred_empty(Other))95HasDeadBlocks = true;96}97}98return HasDeadBlocks;99}100101static bool lowerConstantIntrinsics(Function &F, const TargetLibraryInfo &TLI,102DominatorTree *DT) {103std::optional<DomTreeUpdater> DTU;104if (DT)105DTU.emplace(DT, DomTreeUpdater::UpdateStrategy::Lazy);106107bool HasDeadBlocks = false;108const auto &DL = F.getDataLayout();109SmallVector<WeakTrackingVH, 8> Worklist;110111ReversePostOrderTraversal<Function *> RPOT(&F);112for (BasicBlock *BB : RPOT) {113for (Instruction &I: *BB) {114IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);115if (!II)116continue;117switch (II->getIntrinsicID()) {118default:119break;120case Intrinsic::is_constant:121case Intrinsic::objectsize:122Worklist.push_back(WeakTrackingVH(&I));123break;124}125}126}127for (WeakTrackingVH &VH: Worklist) {128// Items on the worklist can be mutated by earlier recursive replaces.129// This can remove the intrinsic as dead (VH == null), but also replace130// the intrinsic in place.131if (!VH)132continue;133IntrinsicInst *II = dyn_cast<IntrinsicInst>(&*VH);134if (!II)135continue;136Value *NewValue;137switch (II->getIntrinsicID()) {138default:139continue;140case Intrinsic::is_constant:141NewValue = lowerIsConstantIntrinsic(II);142LLVM_DEBUG(dbgs() << "Folding " << *II << " to " << *NewValue << "\n");143IsConstantIntrinsicsHandled++;144break;145case Intrinsic::objectsize:146NewValue = lowerObjectSizeCall(II, DL, &TLI, true);147LLVM_DEBUG(dbgs() << "Folding " << *II << " to " << *NewValue << "\n");148ObjectSizeIntrinsicsHandled++;149break;150}151HasDeadBlocks |= replaceConditionalBranchesOnConstant(152II, NewValue, DTU ? &*DTU : nullptr);153}154if (HasDeadBlocks)155removeUnreachableBlocks(F, DTU ? &*DTU : nullptr);156return !Worklist.empty();157}158159PreservedAnalyses160LowerConstantIntrinsicsPass::run(Function &F, FunctionAnalysisManager &AM) {161if (lowerConstantIntrinsics(F, AM.getResult<TargetLibraryAnalysis>(F),162AM.getCachedResult<DominatorTreeAnalysis>(F))) {163PreservedAnalyses PA;164PA.preserve<DominatorTreeAnalysis>();165return PA;166}167168return PreservedAnalyses::all();169}170171namespace {172/// Legacy pass for lowering is.constant intrinsics out of the IR.173///174/// When this pass is run over a function it converts is.constant intrinsics175/// into 'true' or 'false'. This complements the normal constant folding176/// to 'true' as part of Instruction Simplify passes.177class LowerConstantIntrinsics : public FunctionPass {178public:179static char ID;180LowerConstantIntrinsics() : FunctionPass(ID) {181initializeLowerConstantIntrinsicsPass(*PassRegistry::getPassRegistry());182}183184bool runOnFunction(Function &F) override {185const TargetLibraryInfo &TLI =186getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);187DominatorTree *DT = nullptr;188if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())189DT = &DTWP->getDomTree();190return lowerConstantIntrinsics(F, TLI, DT);191}192193void getAnalysisUsage(AnalysisUsage &AU) const override {194AU.addRequired<TargetLibraryInfoWrapperPass>();195AU.addPreserved<GlobalsAAWrapperPass>();196AU.addPreserved<DominatorTreeWrapperPass>();197}198};199} // namespace200201char LowerConstantIntrinsics::ID = 0;202INITIALIZE_PASS_BEGIN(LowerConstantIntrinsics, "lower-constant-intrinsics",203"Lower constant intrinsics", false, false)204INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)205INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)206INITIALIZE_PASS_END(LowerConstantIntrinsics, "lower-constant-intrinsics",207"Lower constant intrinsics", false, false)208209FunctionPass *llvm::createLowerConstantIntrinsicsPass() {210return new LowerConstantIntrinsics();211}212213214