#include "llvm/Target/TargetSelectionDAGInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <algorithm>
+#include <utility>
using namespace llvm;
#define DEBUG_TYPE "isel"
}
void SelectionDAGBuilder::visitCatchPad(const CatchPadInst &I) {
- llvm_unreachable("should never codegen catchpads");
+ auto Pers = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn());
+ bool IsMSVCCXX = Pers == EHPersonality::MSVC_CXX;
+ bool IsSEH = isAsynchronousEHPersonality(Pers);
+ bool IsCoreCLR = Pers == EHPersonality::CoreCLR;
+ MachineBasicBlock *CatchPadMBB = FuncInfo.MBB;
+ // In MSVC C++ and CoreCLR, catchblocks are funclets and need prologues.
+ if (IsMSVCCXX || IsCoreCLR)
+ CatchPadMBB->setIsEHFuncletEntry();
+
+ MachineBasicBlock *NormalDestMBB = FuncInfo.MBBMap[I.getNormalDest()];
+
+ // Update machine-CFG edge.
+ FuncInfo.MBB->addSuccessor(NormalDestMBB);
+
+ // CatchPads in SEH are not funclets, they are merely markers which indicate
+ // where to insert register restoration code.
+ if (IsSEH) {
+ DAG.setRoot(DAG.getNode(ISD::CATCHRET, getCurSDLoc(), MVT::Other,
+ getControlRoot(), DAG.getBasicBlock(NormalDestMBB),
+ DAG.getBasicBlock(FuncInfo.MF->begin())));
+ return;
+ }
+
+ // If this is not a fall-through branch or optimizations are switched off,
+ // emit the branch.
+ if (NormalDestMBB != NextBlock(CatchPadMBB) ||
+ TM.getOptLevel() == CodeGenOpt::None)
+ DAG.setRoot(DAG.getNode(ISD::BR, getCurSDLoc(), MVT::Other,
+ getControlRoot(),
+ DAG.getBasicBlock(NormalDestMBB)));
}
void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) {
MachineBasicBlock *TargetMBB = FuncInfo.MBBMap[I.getSuccessor()];
FuncInfo.MBB->addSuccessor(TargetMBB);
+ auto Pers = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn());
+ bool IsSEH = isAsynchronousEHPersonality(Pers);
+ if (IsSEH) {
+ // If this is not a fall-through branch or optimizations are switched off,
+ // emit the branch.
+ if (TargetMBB != NextBlock(FuncInfo.MBB) ||
+ TM.getOptLevel() == CodeGenOpt::None)
+ DAG.setRoot(DAG.getNode(ISD::BR, getCurSDLoc(), MVT::Other,
+ getControlRoot(), DAG.getBasicBlock(TargetMBB)));
+ return;
+ }
+
+ // Figure out the funclet membership for the catchret's successor.
+ // This will be used by the FuncletLayout pass to determine how to order the
+ // BB's.
+ MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI();
+ WinEHFuncInfo &EHInfo =
+ MMI.getWinEHFuncInfo(DAG.getMachineFunction().getFunction());
+ const BasicBlock *SuccessorColor = EHInfo.CatchRetSuccessorColorMap[&I];
+ assert(SuccessorColor && "No parent funclet for catchret!");
+ MachineBasicBlock *SuccessorColorMBB = FuncInfo.MBBMap[SuccessorColor];
+ assert(SuccessorColorMBB && "No MBB for SuccessorColor!");
+
// Create the terminator node.
SDValue Ret = DAG.getNode(ISD::CATCHRET, getCurSDLoc(), MVT::Other,
- getControlRoot(), DAG.getBasicBlock(TargetMBB));
+ getControlRoot(), DAG.getBasicBlock(TargetMBB),
+ DAG.getBasicBlock(SuccessorColorMBB));
DAG.setRoot(Ret);
}
/// destination, but in the machine CFG, we enumerate all the possible blocks.
/// This function skips over imaginary basic blocks that hold catchpad,
/// terminatepad, or catchendpad instructions, and finds all the "real" machine
-/// basic block destinations.
-static void
-findUnwindDestinations(FunctionLoweringInfo &FuncInfo,
- const BasicBlock *EHPadBB,
- SmallVectorImpl<MachineBasicBlock *> &UnwindDests) {
- bool IsMSVCCXX = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn()) ==
- EHPersonality::MSVC_CXX;
+/// basic block destinations. As those destinations may not be successors of
+/// EHPadBB, here we also calculate the edge weight to those destinations. The
+/// passed-in Weight is the edge weight to EHPadBB.
+static void findUnwindDestinations(
+ FunctionLoweringInfo &FuncInfo, const BasicBlock *EHPadBB, uint32_t Weight,
+ SmallVectorImpl<std::pair<MachineBasicBlock *, uint32_t>> &UnwindDests) {
+ EHPersonality Personality =
+ classifyEHPersonality(FuncInfo.Fn->getPersonalityFn());
+ bool IsMSVCCXX = Personality == EHPersonality::MSVC_CXX;
+ bool IsCoreCLR = Personality == EHPersonality::CoreCLR;
+
while (EHPadBB) {
const Instruction *Pad = EHPadBB->getFirstNonPHI();
+ BasicBlock *NewEHPadBB = nullptr;
if (isa<LandingPadInst>(Pad)) {
// Stop on landingpads. They are not funclets.
- UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
+ UnwindDests.emplace_back(FuncInfo.MBBMap[EHPadBB], Weight);
break;
- } else if (isa<CleanupPadInst>(Pad) || isa<LandingPadInst>(Pad)) {
+ } else if (isa<CleanupPadInst>(Pad)) {
// Stop on cleanup pads. Cleanups are always funclet entries for all known
// personalities.
- UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
- UnwindDests.back()->setIsEHFuncletEntry();
+ UnwindDests.emplace_back(FuncInfo.MBBMap[EHPadBB], Weight);
+ UnwindDests.back().first->setIsEHFuncletEntry();
break;
} else if (const auto *CPI = dyn_cast<CatchPadInst>(Pad)) {
// Add the catchpad handler to the possible destinations.
- UnwindDests.push_back(FuncInfo.MBBMap[CPI->getNormalDest()]);
+ UnwindDests.emplace_back(FuncInfo.MBBMap[EHPadBB], Weight);
// In MSVC C++, catchblocks are funclets and need prologues.
- if (IsMSVCCXX)
- UnwindDests.back()->setIsEHFuncletEntry();
- EHPadBB = CPI->getUnwindDest();
- } else if (const auto *CEPI = dyn_cast<CatchEndPadInst>(Pad)) {
- EHPadBB = CEPI->getUnwindDest();
- } else if (const auto *CEPI = dyn_cast<CleanupEndPadInst>(Pad)) {
- EHPadBB = CEPI->getUnwindDest();
+ if (IsMSVCCXX || IsCoreCLR)
+ UnwindDests.back().first->setIsEHFuncletEntry();
+ NewEHPadBB = CPI->getUnwindDest();
+ } else if (const auto *CEPI = dyn_cast<CatchEndPadInst>(Pad))
+ NewEHPadBB = CEPI->getUnwindDest();
+ else if (const auto *CEPI = dyn_cast<CleanupEndPadInst>(Pad))
+ NewEHPadBB = CEPI->getUnwindDest();
+ else
+ continue;
+
+ BranchProbabilityInfo *BPI = FuncInfo.BPI;
+ if (BPI && NewEHPadBB) {
+ // When BPI is available, the calculated weight cannot be zero as zero
+ // will be turned to a default weight in MachineBlockFrequencyInfo.
+ Weight = std::max<uint32_t>(
+ BPI->getEdgeProbability(EHPadBB, NewEHPadBB).scale(Weight), 1);
}
+ EHPadBB = NewEHPadBB;
}
}
void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) {
// Update successor info.
- // FIXME: The weights for catchpads will be wrong.
- SmallVector<MachineBasicBlock *, 1> UnwindDests;
- findUnwindDestinations(FuncInfo, I.getUnwindDest(), UnwindDests);
- for (MachineBasicBlock *UnwindDest : UnwindDests) {
- UnwindDest->setIsEHPad();
- addSuccessorWithWeight(FuncInfo.MBB, UnwindDest);
+ SmallVector<std::pair<MachineBasicBlock *, uint32_t>, 1> UnwindDests;
+ auto UnwindDest = I.getUnwindDest();
+ BranchProbabilityInfo *BPI = FuncInfo.BPI;
+ uint32_t UnwindDestWeight =
+ BPI ? BPI->getEdgeWeight(FuncInfo.MBB->getBasicBlock(), UnwindDest) : 0;
+ findUnwindDestinations(FuncInfo, UnwindDest, UnwindDestWeight, UnwindDests);
+ for (auto &UnwindDest : UnwindDests) {
+ UnwindDest.first->setIsEHPad();
+ addSuccessorWithWeight(FuncInfo.MBB, UnwindDest.first, UnwindDest.second);
}
// Create the terminator node.
CopyToExportRegsIfNeeded(&I);
}
- SmallVector<MachineBasicBlock *, 1> UnwindDests;
- findUnwindDestinations(FuncInfo, EHPadBB, UnwindDests);
+ SmallVector<std::pair<MachineBasicBlock *, uint32_t>, 1> UnwindDests;
+ BranchProbabilityInfo *BPI = FuncInfo.BPI;
+ uint32_t EHPadBBWeight =
+ BPI ? BPI->getEdgeWeight(InvokeMBB->getBasicBlock(), EHPadBB) : 0;
+ findUnwindDestinations(FuncInfo, EHPadBB, EHPadBBWeight, UnwindDests);
// Update successor info.
- // FIXME: The weights for catchpads will be wrong.
addSuccessorWithWeight(InvokeMBB, Return);
- for (MachineBasicBlock *UnwindDest : UnwindDests) {
- UnwindDest->setIsEHPad();
- addSuccessorWithWeight(InvokeMBB, UnwindDest);
+ for (auto &UnwindDest : UnwindDests) {
+ UnwindDest.first->setIsEHPad();
+ addSuccessorWithWeight(InvokeMBB, UnwindDest.first, UnwindDest.second);
}
// Drop into normal successor.
void SelectionDAGBuilder::visitUnreachable(const UnreachableInst &I) {
if (DAG.getTarget().Options.TrapUnreachable)
- DAG.setRoot(DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, DAG.getRoot()));
+ DAG.setRoot(
+ DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, DAG.getRoot()));
}
void SelectionDAGBuilder::visitFSub(const User &I) {
return DAG.getNode(ISD::FPOWI, DL, LHS.getValueType(), LHS, RHS);
}
-// getTruncatedArgReg - Find underlying register used for an truncated
-// argument.
-static unsigned getTruncatedArgReg(const SDValue &N) {
- if (N.getOpcode() != ISD::TRUNCATE)
+// getUnderlyingArgReg - Find underlying register used for a truncated or
+// bitcasted argument.
+static unsigned getUnderlyingArgReg(const SDValue &N) {
+ switch (N.getOpcode()) {
+ case ISD::CopyFromReg:
+ return cast<RegisterSDNode>(N.getOperand(1))->getReg();
+ case ISD::BITCAST:
+ case ISD::AssertZext:
+ case ISD::AssertSext:
+ case ISD::TRUNCATE:
+ return getUnderlyingArgReg(N.getOperand(0));
+ default:
return 0;
-
- const SDValue &Ext = N.getOperand(0);
- if (Ext.getOpcode() == ISD::AssertZext ||
- Ext.getOpcode() == ISD::AssertSext) {
- const SDValue &CFR = Ext.getOperand(0);
- if (CFR.getOpcode() == ISD::CopyFromReg)
- return cast<RegisterSDNode>(CFR.getOperand(1))->getReg();
- if (CFR.getOpcode() == ISD::TRUNCATE)
- return getTruncatedArgReg(CFR);
}
- return 0;
}
/// EmitFuncArgumentDbgValue - If the DbgValueInst is a dbg_value of a function
Op = MachineOperand::CreateFI(FI);
if (!Op && N.getNode()) {
- unsigned Reg;
- if (N.getOpcode() == ISD::CopyFromReg)
- Reg = cast<RegisterSDNode>(N.getOperand(1))->getReg();
- else
- Reg = getTruncatedArgReg(N);
+ unsigned Reg = getUnderlyingArgReg(N);
if (Reg && TargetRegisterInfo::isVirtualRegister(Reg)) {
MachineRegisterInfo &RegInfo = MF.getRegInfo();
unsigned PR = RegInfo.getLiveInPhysReg(Reg);
}
case Intrinsic::clear_cache:
return TLI.getClearCacheBuiltinName();
- case Intrinsic::eh_actions:
- setValue(&I, DAG.getUNDEF(TLI.getPointerTy(DAG.getDataLayout())));
- return nullptr;
case Intrinsic::donothing:
// ignore
return nullptr;
return nullptr;
}
- case Intrinsic::eh_begincatch:
- case Intrinsic::eh_endcatch:
- llvm_unreachable("begin/end catch intrinsics not lowered in codegen");
+
+ case Intrinsic::eh_exceptionpointer:
case Intrinsic::eh_exceptioncode: {
- unsigned Reg = TLI.getExceptionPointerRegister();
- assert(Reg && "cannot get exception code on this platform");
+ // Get the exception pointer vreg, copy from it, and resize it to fit.
+ const auto *CPI = cast<CatchPadInst>(I.getArgOperand(0));
MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
const TargetRegisterClass *PtrRC = TLI.getRegClassFor(PtrVT);
- assert(FuncInfo.MBB->isEHPad() && "eh.exceptioncode in non-lpad");
- unsigned VReg = FuncInfo.MBB->addLiveIn(Reg, PtrRC);
+ unsigned VReg = FuncInfo.getCatchPadExceptionPointerVReg(CPI, PtrRC);
SDValue N =
DAG.getCopyFromReg(DAG.getEntryNode(), getCurSDLoc(), VReg, PtrVT);
N = DAG.getZExtOrTrunc(N, getCurSDLoc(), MVT::i32);