cl::init(0));
static cl::opt<bool>
-EnableFMFInDAG("enable-fmf-dag", cl::init(false), cl::Hidden,
+EnableFMFInDAG("enable-fmf-dag", cl::init(true), cl::Hidden,
cl::desc("Enable fast-math-flags for DAG nodes"));
// Limit the width of DAG chains. This is important in general to prevent
void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) {
// Update machine-CFG edge.
- MachineBasicBlock *PadMBB = FuncInfo.MBB;
MachineBasicBlock *TargetMBB = FuncInfo.MBBMap[I.getSuccessor()];
- PadMBB->addSuccessor(TargetMBB);
+ FuncInfo.MBB->addSuccessor(TargetMBB);
// Create the terminator node.
SDValue Ret = DAG.getNode(ISD::CATCHRET, getCurSDLoc(), MVT::Other,
}
void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {
- report_fatal_error("visitCleanupPad not yet implemented!");
+ // Don't emit any special code for the cleanuppad instruction. It just marks
+ // the start of a funclet.
+ FuncInfo.MBB->setIsEHFuncletEntry();
+ FuncInfo.MBB->setIsCleanupFuncletEntry();
+}
+
+/// When an invoke or a cleanupret unwinds to the next EH pad, there are
+/// many places it could ultimately go. In the IR, we have a single unwind
+/// 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;
+ while (EHPadBB) {
+ const Instruction *Pad = EHPadBB->getFirstNonPHI();
+ if (isa<LandingPadInst>(Pad)) {
+ // Stop on landingpads. They are not funclets.
+ UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
+ break;
+ } else if (isa<CleanupPadInst>(Pad) || isa<LandingPadInst>(Pad)) {
+ // Stop on cleanup pads. Cleanups are always funclet entries for all known
+ // personalities.
+ UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
+ UnwindDests.back()->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()]);
+ // 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();
+ }
+ }
}
void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) {
- report_fatal_error("visitCleanupRet not yet implemented!");
+ // 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);
+ }
+
+ // Create the terminator node.
+ SDValue Ret =
+ DAG.getNode(ISD::CLEANUPRET, getCurSDLoc(), MVT::Other, getControlRoot());
+ DAG.setRoot(Ret);
}
void SelectionDAGBuilder::visitCleanupEndPad(const CleanupEndPadInst &I) {
CopyToExportRegsIfNeeded(&I);
}
- // Stop when we hit a pad that generates real code or we unwind to caller.
- // Catchpads are conditional branches that add real MBB destinations and
- // continue the loop. EH "end" pads are not real BBs and simply continue.
SmallVector<MachineBasicBlock *, 1> UnwindDests;
- bool IsMSVCCXX = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn()) ==
- EHPersonality::MSVC_CXX;
- while (EHPadBB) {
- const Instruction *Pad = EHPadBB->getFirstNonPHI();
- if (isa<LandingPadInst>(Pad)) {
- // Stop on landingpads. They are not funclets.
- UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
- break;
- } else if (isa<CleanupPadInst>(Pad) || isa<LandingPadInst>(Pad)) {
- // Stop on cleanup pads. Cleanups are always funclet entries for all known
- // personalities.
- UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
- UnwindDests.back()->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()]);
- // 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();
- }
- }
+ findUnwindDestinations(FuncInfo, EHPadBB, UnwindDests);
// Update successor info.
// FIXME: The weights for catchpads will be wrong.
getValue(I.getAddress())));
}
-void SelectionDAGBuilder::visitUnreachable(const UnreachableInst &I) {
- if (DAG.getTarget().Options.TrapUnreachable)
- DAG.setRoot(DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, DAG.getRoot()));
-}
+void SelectionDAGBuilder::visitUnreachable(const UnreachableInst &I) {}
void SelectionDAGBuilder::visitFSub(const User &I) {
// -0.0 - X --> fneg
SDValue Op1 = getValue(I.getOperand(0));
SDValue Op2 = getValue(I.getOperand(1));
ISD::CondCode Condition = getFCmpCondCode(predicate);
+
+ // FIXME: Fcmp instructions have fast-math-flags in IR, so we should use them.
+ // FIXME: We should propagate the fast-math-flags to the DAG node itself for
+ // further optimization, but currently FMF is only applicable to binary nodes.
if (TM.Options.NoNaNsFPMath)
Condition = getFCmpCodeWithoutNaN(Condition);
EVT DestVT = DAG.getTargetLoweringInfo().getValueType(DAG.getDataLayout(),
static SDValue getLimitedPrecisionExp2(SDValue t0, SDLoc dl,
SelectionDAG &DAG) {
+ // TODO: What fast-math-flags should be set on the floating-point nodes?
+
// IntegerPartOfX = ((int32_t)(t0);
SDValue IntegerPartOfX = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, t0);
//
// #define LOG2OFe 1.4426950f
// t0 = Op * LOG2OFe
+
+ // TODO: What fast-math-flags should be set here?
SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, Op,
getF32Constant(DAG, 0x3fb8aa3b, dl));
return getLimitedPrecisionExp2(t0, dl, DAG);
/// limited-precision mode.
static SDValue expandLog(SDLoc dl, SDValue Op, SelectionDAG &DAG,
const TargetLowering &TLI) {
+
+ // TODO: What fast-math-flags should be set on the floating-point nodes?
+
if (Op.getValueType() == MVT::f32 &&
LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) {
SDValue Op1 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op);
/// limited-precision mode.
static SDValue expandLog2(SDLoc dl, SDValue Op, SelectionDAG &DAG,
const TargetLowering &TLI) {
+
+ // TODO: What fast-math-flags should be set on the floating-point nodes?
+
if (Op.getValueType() == MVT::f32 &&
LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) {
SDValue Op1 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op);
/// limited-precision mode.
static SDValue expandLog10(SDLoc dl, SDValue Op, SelectionDAG &DAG,
const TargetLowering &TLI) {
+
+ // TODO: What fast-math-flags should be set on the floating-point nodes?
+
if (Op.getValueType() == MVT::f32 &&
LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) {
SDValue Op1 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op);
}
}
+ // TODO: What fast-math-flags should be set on the FMUL node?
if (IsExp10) {
// Put the exponent in the right bit position for later addition to the
// final result:
// the benefit of being both really simple and much better than a libcall.
SDValue Res; // Logically starts equal to 1.0
SDValue CurSquare = LHS;
+ // TODO: Intrinsics should have fast-math-flags that propagate to these
+ // nodes.
while (Val) {
if (Val & 1) {
if (Res.getNode())
N);
return nullptr;
}
- } else if (AI)
+ } else {
SDV = DAG.getDbgValue(Variable, Expression, N.getNode(), N.getResNo(),
true, 0, dl, SDNodeOrder);
- else {
- // Can't do anything with other non-AI cases yet.
- DEBUG(dbgs() << "Dropping debug info for " << DI << "\n");
- DEBUG(dbgs() << "non-AllocaInst issue for Address: \n\t");
- DEBUG(Address->dump());
- return nullptr;
}
DAG.AddDbgValue(SDV, N.getNode(), isParameter);
} else {
getValue(I.getArgOperand(1)),
getValue(I.getArgOperand(2))));
} else {
+ // TODO: Intrinsic calls should have fast-math-flags.
SDValue Mul = DAG.getNode(ISD::FMUL, sdl,
getValue(I.getArgOperand(0)).getValueType(),
getValue(I.getArgOperand(0)),
DAG.setRoot(DAG.getEHLabel(getCurSDLoc(), getRoot(), EndLabel));
// Inform MachineModuleInfo of range.
- MMI.addInvoke(FuncInfo.MBBMap[EHPadBB], BeginLabel, EndLabel);
+ if (MMI.hasEHFunclets()) {
+ WinEHFuncInfo &EHInfo =
+ MMI.getWinEHFuncInfo(DAG.getMachineFunction().getFunction());
+ EHInfo.addIPToStateRange(EHPadBB, BeginLabel, EndLabel);
+ } else {
+ MMI.addInvoke(FuncInfo.MBBMap[EHPadBB], BeginLabel, EndLabel);
+ }
}
return Result;
SDISelAsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput];
if (OpInfo.ConstraintVT != Input.ConstraintVT) {
- const TargetRegisterInfo *TRI = DAG.getSubtarget().getRegisterInfo();
+ const TargetRegisterInfo *TRI = DAG.getSubtarget().getRegisterInfo();
std::pair<unsigned, const TargetRegisterClass *> MatchRC =
TLI.getRegForInlineAsmConstraint(TRI, OpInfo.ConstraintCode,
OpInfo.ConstraintVT);
uint32_t JumpWeight = I->Weight;
uint32_t FallthroughWeight = UnhandledWeights;
- // If Fallthrough is a target of the jump table, we evenly distribute
- // the weight on the edge to Fallthrough to successors of CurMBB.
- // Also update the weight on the edge from JumpMBB to Fallthrough.
+ // If the default statement is a target of the jump table, we evenly
+ // distribute the default weight to successors of CurMBB. Also update
+ // the weight on the edge from JumpMBB to Fallthrough.
for (MachineBasicBlock::succ_iterator SI = JumpMBB->succ_begin(),
SE = JumpMBB->succ_end();
SI != SE; ++SI) {
- if (*SI == Fallthrough) {
+ if (*SI == DefaultMBB) {
JumpWeight += DefaultWeight / 2;
FallthroughWeight -= DefaultWeight / 2;
JumpMBB->setSuccWeight(SI, DefaultWeight / 2);