llvm/llvm/lib/CodeGen/CallBrPrepare.cpp

//===-- CallBrPrepare - Prepare callbr for code generation ----------------===//
//
// 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 callbrs in LLVM IR in order to to assist SelectionDAG's
// codegen.
//
// In particular, this pass assists in inserting register copies for the output
// values of a callbr along the edges leading to the indirect target blocks.
// Though the output SSA value is defined by the callbr instruction itself in
// the IR representation, the value cannot be copied to the appropriate virtual
// registers prior to jumping to an indirect label, since the jump occurs
// within the user-provided assembly blob.
//
// Instead, those copies must occur separately at the beginning of each
// indirect target. That requires that we create a separate SSA definition in
// each of them (via llvm.callbr.landingpad), and may require splitting
// critical edges so we have a location to place the intrinsic. Finally, we
// remap users of the original callbr output SSA value to instead point to the
// appropriate llvm.callbr.landingpad value.
//
// Ideally, this could be done inside SelectionDAG, or in the
// MachineInstruction representation, without the use of an IR-level intrinsic.
// But, within the current framework, it’s simpler to implement as an IR pass.
// (If support for callbr in GlobalISel is implemented, it’s worth considering
// whether this is still required.)
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/CallBrPrepare.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/SSAUpdater.h"

usingnamespacellvm;

#define DEBUG_TYPE

static bool SplitCriticalEdges(ArrayRef<CallBrInst *> CBRs, DominatorTree &DT);
static bool InsertIntrinsicCalls(ArrayRef<CallBrInst *> CBRs,
                                 DominatorTree &DT);
static void UpdateSSA(DominatorTree &DT, CallBrInst *CBR, CallInst *Intrinsic,
                      SSAUpdater &SSAUpdate);
static SmallVector<CallBrInst *, 2> FindCallBrs(Function &Fn);

namespace {

class CallBrPrepare : public FunctionPass {};

} // end anonymous namespace

PreservedAnalyses CallBrPreparePass::run(Function &Fn,
                                         FunctionAnalysisManager &FAM) {}

char CallBrPrepare::ID =;
INITIALIZE_PASS_BEGIN(CallBrPrepare, "callbrprepare", "Prepare callbr", false,
                      false)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_END(CallBrPrepare, "callbrprepare", "Prepare callbr", false,
                    false)

FunctionPass *llvm::createCallBrPass() {}

void CallBrPrepare::getAnalysisUsage(AnalysisUsage &AU) const {}

SmallVector<CallBrInst *, 2> FindCallBrs(Function &Fn) {}

bool SplitCriticalEdges(ArrayRef<CallBrInst *> CBRs, DominatorTree &DT) {}

bool InsertIntrinsicCalls(ArrayRef<CallBrInst *> CBRs, DominatorTree &DT) {}

static bool IsInSameBasicBlock(const Use &U, const BasicBlock *BB) {}

#ifndef NDEBUG
static void PrintDebugDomInfo(const DominatorTree &DT, const Use &U,
                              const BasicBlock *BB, bool IsDefaultDest) {
  if (!isa<Instruction>(U.getUser()))
    return;
  LLVM_DEBUG(dbgs() << "Use: " << *U.getUser() << ", in block "
                    << cast<Instruction>(U.getUser())->getParent()->getName()
                    << ", is " << (DT.dominates(BB, U) ? "" : "NOT ")
                    << "dominated by " << BB->getName() << " ("
                    << (IsDefaultDest ? "in" : "") << "direct)\n");
}
#endif

void UpdateSSA(DominatorTree &DT, CallBrInst *CBR, CallInst *Intrinsic,
               SSAUpdater &SSAUpdate) {}

bool CallBrPrepare::runOnFunction(Function &Fn) {}