diff options
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/CodeGen/ImplicitNullChecks.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MIRParser/MILexer.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MIRParser/MILexer.h | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MIRParser/MIParser.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MIRPrinter.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MachineCSE.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MachineInstr.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MachinePipeliner.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/CodeGen/PeepholeOptimizer.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/CodeGen/ScheduleDAGInstrs.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 18 | ||||
-rw-r--r-- | llvm/lib/CodeGen/TargetInstrInfo.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/CodeGen/TargetLoweringBase.cpp | 28 |
16 files changed, 81 insertions, 19 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp index ca6d8640531..2ad35b3a72c 100644 --- a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp @@ -78,6 +78,6 @@ bool InstructionSelector::isObviouslySafeToFold(MachineInstr &MI, std::next(MI.getIterator()) == IntoMI.getIterator()) return true; - return !MI.mayLoadOrStore() && !MI.hasUnmodeledSideEffects() && - empty(MI.implicit_operands()); + return !MI.mayLoadOrStore() && !MI.mayRaiseFPException() && + !MI.hasUnmodeledSideEffects() && empty(MI.implicit_operands()); } diff --git a/llvm/lib/CodeGen/ImplicitNullChecks.cpp b/llvm/lib/CodeGen/ImplicitNullChecks.cpp index dff6d02b06e..1e82ea65961 100644 --- a/llvm/lib/CodeGen/ImplicitNullChecks.cpp +++ b/llvm/lib/CodeGen/ImplicitNullChecks.cpp @@ -229,7 +229,8 @@ public: } // end anonymous namespace bool ImplicitNullChecks::canHandle(const MachineInstr *MI) { - if (MI->isCall() || MI->hasUnmodeledSideEffects()) + if (MI->isCall() || MI->mayRaiseFPException() || + MI->hasUnmodeledSideEffects()) return false; auto IsRegMask = [](const MachineOperand &MO) { return MO.isRegMask(); }; (void)IsRegMask; diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp index c274e282f59..4899bd3f581 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp +++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp @@ -204,6 +204,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) { .Case("nuw" , MIToken::kw_nuw) .Case("nsw" , MIToken::kw_nsw) .Case("exact" , MIToken::kw_exact) + .Case("fpexcept", MIToken::kw_fpexcept) .Case("debug-location", MIToken::kw_debug_location) .Case("same_value", MIToken::kw_cfi_same_value) .Case("offset", MIToken::kw_cfi_offset) diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h index 1fccf98633b..0fe3f9f706d 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.h +++ b/llvm/lib/CodeGen/MIRParser/MILexer.h @@ -73,6 +73,7 @@ struct MIToken { kw_nuw, kw_nsw, kw_exact, + kw_fpexcept, kw_debug_location, kw_cfi_same_value, kw_cfi_offset, diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 92b238f75ff..c0b800a0b87 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -1136,7 +1136,8 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) { Token.is(MIToken::kw_reassoc) || Token.is(MIToken::kw_nuw) || Token.is(MIToken::kw_nsw) || - Token.is(MIToken::kw_exact)) { + Token.is(MIToken::kw_exact) || + Token.is(MIToken::kw_fpexcept)) { // Mine frame and fast math flags if (Token.is(MIToken::kw_frame_setup)) Flags |= MachineInstr::FrameSetup; @@ -1162,6 +1163,8 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) { Flags |= MachineInstr::NoSWrap; if (Token.is(MIToken::kw_exact)) Flags |= MachineInstr::IsExact; + if (Token.is(MIToken::kw_fpexcept)) + Flags |= MachineInstr::FPExcept; lex(); } diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index 1d95187d597..e6f5890b513 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -713,6 +713,8 @@ void MIPrinter::print(const MachineInstr &MI) { OS << "nsw "; if (MI.getFlag(MachineInstr::IsExact)) OS << "exact "; + if (MI.getFlag(MachineInstr::FPExcept)) + OS << "fpexcept "; OS << TII->getName(MI.getOpcode()); if (I < E) diff --git a/llvm/lib/CodeGen/MachineCSE.cpp b/llvm/lib/CodeGen/MachineCSE.cpp index ff15875af9d..519cb4703ca 100644 --- a/llvm/lib/CodeGen/MachineCSE.cpp +++ b/llvm/lib/CodeGen/MachineCSE.cpp @@ -382,7 +382,7 @@ bool MachineCSE::isCSECandidate(MachineInstr *MI) { // Ignore stuff that we obviously can't move. if (MI->mayStore() || MI->isCall() || MI->isTerminator() || - MI->hasUnmodeledSideEffects()) + MI->mayRaiseFPException() || MI->hasUnmodeledSideEffects()) return false; if (MI->mayLoad()) { diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index 894d0abea3e..e5c398a2d10 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -1178,7 +1178,7 @@ bool MachineInstr::isSafeToMove(AliasAnalysis *AA, bool &SawStore) const { } if (isPosition() || isDebugInstr() || isTerminator() || - hasUnmodeledSideEffects()) + mayRaiseFPException() || hasUnmodeledSideEffects()) return false; // See if this instruction does a load. If so, we have to guarantee that the @@ -1544,6 +1544,8 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST, OS << "nsw "; if (getFlag(MachineInstr::IsExact)) OS << "exact "; + if (getFlag(MachineInstr::FPExcept)) + OS << "fpexcept "; // Print the opcode name. if (TII) diff --git a/llvm/lib/CodeGen/MachinePipeliner.cpp b/llvm/lib/CodeGen/MachinePipeliner.cpp index 604b3187b71..639d124804c 100644 --- a/llvm/lib/CodeGen/MachinePipeliner.cpp +++ b/llvm/lib/CodeGen/MachinePipeliner.cpp @@ -579,7 +579,8 @@ static bool isSuccOrder(SUnit *SUa, SUnit *SUb) { /// Return true if the instruction causes a chain between memory /// references before and after it. static bool isDependenceBarrier(MachineInstr &MI, AliasAnalysis *AA) { - return MI.isCall() || MI.hasUnmodeledSideEffects() || + return MI.isCall() || MI.mayRaiseFPException() || + MI.hasUnmodeledSideEffects() || (MI.hasOrderedMemoryRef() && (!MI.mayLoad() || !MI.isDereferenceableInvariantLoad(AA))); } @@ -3238,6 +3239,7 @@ bool SwingSchedulerDAG::isLoopCarriedDep(SUnit *Source, const SDep &Dep, // Assume ordered loads and stores may have a loop carried dependence. if (SI->hasUnmodeledSideEffects() || DI->hasUnmodeledSideEffects() || + SI->mayRaiseFPException() || DI->mayRaiseFPException() || SI->hasOrderedMemoryRef() || DI->hasOrderedMemoryRef()) return true; diff --git a/llvm/lib/CodeGen/PeepholeOptimizer.cpp b/llvm/lib/CodeGen/PeepholeOptimizer.cpp index 2307e9972ec..a3f1b83b157 100644 --- a/llvm/lib/CodeGen/PeepholeOptimizer.cpp +++ b/llvm/lib/CodeGen/PeepholeOptimizer.cpp @@ -1825,7 +1825,7 @@ ValueTrackerResult ValueTracker::getNextSourceFromBitcast() { assert(Def->isBitcast() && "Invalid definition"); // Bail if there are effects that a plain copy will not expose. - if (Def->hasUnmodeledSideEffects()) + if (Def->mayRaiseFPException() || Def->hasUnmodeledSideEffects()) return ValueTrackerResult(); // Bitcasts with more than one def are not supported. diff --git a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp index 3b431e71db0..40ed1b90b7d 100644 --- a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -712,6 +712,7 @@ void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA, AAForDep = UseAA ? AA : nullptr; BarrierChain = nullptr; + SUnit *FPBarrierChain = nullptr; this->TrackLaneMasks = TrackLaneMasks; MISUnitMap.clear(); @@ -871,9 +872,21 @@ void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA, addBarrierChain(NonAliasStores); addBarrierChain(NonAliasLoads); + // Add dependency against previous FP barrier and reset FP barrier. + if (FPBarrierChain) + FPBarrierChain->addPredBarrier(BarrierChain); + FPBarrierChain = BarrierChain; + continue; } + // Instructions that may raise FP exceptions depend on each other. + if (MI.mayRaiseFPException()) { + if (FPBarrierChain) + FPBarrierChain->addPredBarrier(SU); + FPBarrierChain = SU; + } + // If it's not a store or a variant load, we're done. if (!MI.mayStore() && !(MI.mayLoad() && !MI.isDereferenceableInvariantLoad(AA))) diff --git a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index 8533a94c48a..9bc07d35dfc 100644 --- a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -883,6 +883,9 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, if (Flags.hasExact()) MI->setFlag(MachineInstr::MIFlag::IsExact); + + if (Flags.hasFPExcept()) + MI->setFlag(MachineInstr::MIFlag::FPExcept); } // Emit all of the actual operands of this instruction, adding them to the diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 07d6ac83e03..e7d3c9798d1 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6955,6 +6955,13 @@ void SelectionDAGBuilder::visitConstrainedFPIntrinsic( { Chain, getValue(FPI.getArgOperand(0)), getValue(FPI.getArgOperand(1)) }); + if (FPI.getExceptionBehavior() != + ConstrainedFPIntrinsic::ExceptionBehavior::ebIgnore) { + SDNodeFlags Flags; + Flags.setFPExcept(true); + Result->setFlags(Flags); + } + assert(Result.getNode()->getNumValues() == 2); SDValue OutChain = Result.getValue(1); DAG.setRoot(OutChain); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 6f55f98c51f..64df34e4c1e 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -1122,16 +1122,14 @@ void SelectionDAGISel::DoInstructionSelection() { #endif // When we are using non-default rounding modes or FP exception behavior - // FP operations are represented by StrictFP pseudo-operations. They - // need to be simplified here so that the target-specific instruction - // selectors know how to handle them. - // - // If the current node is a strict FP pseudo-op, the isStrictFPOp() - // function will provide the corresponding normal FP opcode to which the - // node should be mutated. - // - // FIXME: The backends need a way to handle FP constraints. - if (Node->isStrictFPOpcode()) + // FP operations are represented by StrictFP pseudo-operations. For + // targets that do not (yet) understand strict FP operations directly, + // we convert them to normal FP opcodes instead at this point. This + // will allow them to be handled by existing target-specific instruction + // selectors. + if (Node->isStrictFPOpcode() && + (TLI->getOperationAction(Node->getOpcode(), Node->getValueType(0)) + != TargetLowering::Legal)) Node = CurDAG->mutateStrictFPToFP(Node); LLVM_DEBUG(dbgs() << "\nISEL: Starting selection on root node: "; diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp index ab13d3482c1..95d64155cf2 100644 --- a/llvm/lib/CodeGen/TargetInstrInfo.cpp +++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp @@ -899,7 +899,8 @@ bool TargetInstrInfo::isReallyTriviallyReMaterializableGeneric( return true; // Avoid instructions obviously unsafe for remat. - if (MI.isNotDuplicable() || MI.mayStore() || MI.hasUnmodeledSideEffects()) + if (MI.isNotDuplicable() || MI.mayStore() || MI.mayRaiseFPException() || + MI.hasUnmodeledSideEffects()) return false; // Don't remat inline asm. We have no idea how expensive it is diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp index 888d420a441..7c42ed2ef5b 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -663,6 +663,34 @@ void TargetLoweringBase::initActions() { setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, VT, Expand); } + // Constrained floating-point operations default to expand. + setOperationAction(ISD::STRICT_FADD, VT, Expand); + setOperationAction(ISD::STRICT_FSUB, VT, Expand); + setOperationAction(ISD::STRICT_FMUL, VT, Expand); + setOperationAction(ISD::STRICT_FDIV, VT, Expand); + setOperationAction(ISD::STRICT_FREM, VT, Expand); + setOperationAction(ISD::STRICT_FMA, VT, Expand); + setOperationAction(ISD::STRICT_FSQRT, VT, Expand); + setOperationAction(ISD::STRICT_FPOW, VT, Expand); + setOperationAction(ISD::STRICT_FPOWI, VT, Expand); + setOperationAction(ISD::STRICT_FSIN, VT, Expand); + setOperationAction(ISD::STRICT_FCOS, VT, Expand); + setOperationAction(ISD::STRICT_FEXP, VT, Expand); + setOperationAction(ISD::STRICT_FEXP2, VT, Expand); + setOperationAction(ISD::STRICT_FLOG, VT, Expand); + setOperationAction(ISD::STRICT_FLOG10, VT, Expand); + setOperationAction(ISD::STRICT_FLOG2, VT, Expand); + setOperationAction(ISD::STRICT_FRINT, VT, Expand); + setOperationAction(ISD::STRICT_FNEARBYINT, VT, Expand); + setOperationAction(ISD::STRICT_FCEIL, VT, Expand); + setOperationAction(ISD::STRICT_FFLOOR, VT, Expand); + setOperationAction(ISD::STRICT_FROUND, VT, Expand); + setOperationAction(ISD::STRICT_FTRUNC, VT, Expand); + setOperationAction(ISD::STRICT_FMAXNUM, VT, Expand); + setOperationAction(ISD::STRICT_FMINNUM, VT, Expand); + setOperationAction(ISD::STRICT_FP_ROUND, VT, Expand); + setOperationAction(ISD::STRICT_FP_EXTEND, VT, Expand); + // For most targets @llvm.get.dynamic.area.offset just returns 0. setOperationAction(ISD::GET_DYNAMIC_AREA_OFFSET, VT, Expand); |