diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
| commit | e6d1592492a3a379186bfb02bd0f4eda0669c0d5 (patch) | |
| tree | 599ab169a01f1c86eda9adc774edaedde2f2db5b /include/llvm/CodeGen | |
| parent | 1a56a5ead7a2e84bee8240f5f6b033b5f1707154 (diff) | |
Notes
Diffstat (limited to 'include/llvm/CodeGen')
162 files changed, 4228 insertions, 1529 deletions
diff --git a/include/llvm/CodeGen/AccelTable.h b/include/llvm/CodeGen/AccelTable.h index 13928582f2dd..734531a65d50 100644 --- a/include/llvm/CodeGen/AccelTable.h +++ b/include/llvm/CodeGen/AccelTable.h @@ -1,9 +1,8 @@ //==- include/llvm/CodeGen/AccelTable.h - Accelerator Tables -----*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -327,14 +326,8 @@ public: void emit(AsmPrinter *Asm) const override; -#ifndef _MSC_VER - // The line below is rejected by older versions (TBD) of MSVC. static constexpr Atom Atoms[] = { Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; -#else - // FIXME: Erase this path once the minimum MSCV version has been bumped. - static const SmallVector<Atom, 4> Atoms; -#endif #ifndef NDEBUG void print(raw_ostream &OS) const override; @@ -352,16 +345,10 @@ public: void emit(AsmPrinter *Asm) const override; -#ifndef _MSC_VER - // The line below is rejected by older versions (TBD) of MSVC. static constexpr Atom Atoms[] = { Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; -#else - // FIXME: Erase this path once the minimum MSCV version has been bumped. - static const SmallVector<Atom, 4> Atoms; -#endif #ifndef NDEBUG void print(raw_ostream &OS) const override; @@ -376,14 +363,8 @@ public: void emit(AsmPrinter *Asm) const override; -#ifndef _MSC_VER - // The line below is rejected by older versions (TBD) of MSVC. static constexpr Atom Atoms[] = { Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; -#else - // FIXME: Erase this path once the minimum MSCV version has been bumped. - static const SmallVector<Atom, 4> Atoms; -#endif #ifndef NDEBUG void print(raw_ostream &OS) const override; @@ -407,16 +388,10 @@ public: void emit(AsmPrinter *Asm) const override; -#ifndef _MSC_VER - // The line below is rejected by older versions (TBD) of MSVC. static constexpr Atom Atoms[] = { Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), Atom(5, dwarf::DW_FORM_data1), Atom(6, dwarf::DW_FORM_data4)}; -#else - // FIXME: Erase this path once the minimum MSCV version has been bumped. - static const SmallVector<Atom, 4> Atoms; -#endif #ifndef NDEBUG void print(raw_ostream &OS) const override; diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index d77aee66ed76..0be0ac22a74d 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -1,9 +1,8 @@ //===- CodeGen/Analysis.h - CodeGen LLVM IR Analysis Utilities --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -26,6 +25,7 @@ namespace llvm { class GlobalValue; +class LLT; class MachineBasicBlock; class MachineFunction; class TargetLoweringBase; @@ -74,6 +74,25 @@ void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, SmallVectorImpl<uint64_t> *Offsets = nullptr, uint64_t StartingOffset = 0); +/// Variant of ComputeValueVTs that also produces the memory VTs. +void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, + SmallVectorImpl<EVT> &ValueVTs, + SmallVectorImpl<EVT> *MemVTs, + SmallVectorImpl<uint64_t> *Offsets = nullptr, + uint64_t StartingOffset = 0); + +/// computeValueLLTs - Given an LLVM IR type, compute a sequence of +/// LLTs that represent all the individual underlying +/// non-aggregate types that comprise it. +/// +/// If Offsets is non-null, it points to a vector to be filled in +/// with the in-memory offsets of each of the individual values. +/// +void computeValueLLTs(const DataLayout &DL, Type &Ty, + SmallVectorImpl<LLT> &ValueTys, + SmallVectorImpl<uint64_t> *Offsets = nullptr, + uint64_t StartingOffset = 0); + /// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V. GlobalValue *ExtractTypeInfo(Value *V); diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 413901d218f9..d110f8b01cb5 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/AsmPrinter.h - AsmPrinter Framework ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -20,6 +19,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/CodeGen/AsmPrinterHandler.h" #include "llvm/CodeGen/DwarfStringPoolEntry.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/IR/InlineAsm.h" @@ -33,7 +33,6 @@ namespace llvm { -class AsmPrinterHandler; class BasicBlock; class BlockAddress; class Constant; @@ -122,9 +121,6 @@ public: using GOTEquivUsePair = std::pair<const GlobalVariable *, unsigned>; MapVector<const MCSymbol *, GOTEquivUsePair> GlobalGOTEquivs; - /// Enable print [latency:throughput] in output. - bool EnablePrintSchedInfo = false; - private: MCSymbol *CurrentFnBegin = nullptr; MCSymbol *CurrentFnEnd = nullptr; @@ -142,16 +138,16 @@ protected: /// Protected struct HandlerInfo and Handlers permit target extended /// AsmPrinter adds their own handlers. struct HandlerInfo { - AsmPrinterHandler *Handler; + std::unique_ptr<AsmPrinterHandler> Handler; const char *TimerName; const char *TimerDescription; const char *TimerGroupName; const char *TimerGroupDescription; - HandlerInfo(AsmPrinterHandler *Handler, const char *TimerName, - const char *TimerDescription, const char *TimerGroupName, - const char *TimerGroupDescription) - : Handler(Handler), TimerName(TimerName), + HandlerInfo(std::unique_ptr<AsmPrinterHandler> Handler, + const char *TimerName, const char *TimerDescription, + const char *TimerGroupName, const char *TimerGroupDescription) + : Handler(std::move(Handler)), TimerName(TimerName), TimerDescription(TimerDescription), TimerGroupName(TimerGroupName), TimerGroupDescription(TimerGroupDescription) {} }; @@ -227,6 +223,9 @@ public: void EmitToStreamer(MCStreamer &S, const MCInst &Inst); + /// Emits inital debug location directive. + void emitInitialRawDwarfLocDirective(const MachineFunction &MF); + /// Return the current section we are emitting to. const MCSection *getCurrentSection() const; @@ -316,6 +315,8 @@ public: void emitStackSizeSection(const MachineFunction &MF); + void emitRemarksSection(Module &M); + enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug }; CFIMoveType needsCFIMoves() const; @@ -511,7 +512,7 @@ public: void EmitSLEB128(int64_t Value, const char *Desc = nullptr) const; /// Emit the specified unsigned leb128 value. - void EmitULEB128(uint64_t Value, const char *Desc = nullptr) const; + void EmitULEB128(uint64_t Value, const char *Desc = nullptr, unsigned PadTo = 0) const; /// Emit a .byte 42 directive that corresponds to an encoding. If verbose /// assembly output is enabled, we output comments describing the encoding. @@ -542,6 +543,12 @@ public: emitDwarfStringOffset(S.getEntry()); } + /// Emit reference to a call site with a specified encoding + void EmitCallSiteOffset(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Encoding) const; + /// Emit an integer value corresponding to the call site encoding + void EmitCallSiteValue(uint64_t Value, unsigned Encoding) const; + /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified. virtual unsigned getISAEncoding() { return 0; } @@ -589,20 +596,22 @@ public: virtual void PrintSpecial(const MachineInstr *MI, raw_ostream &OS, const char *Code) const; + /// Print the MachineOperand as a symbol. Targets with complex handling of + /// symbol references should override the base implementation. + virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS); + /// Print the specified operand of MI, an INLINEASM instruction, using the /// specified assembler variant. Targets should override this to format as /// appropriate. This method can return true if the operand is erroneous. virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &OS); + const char *ExtraCode, raw_ostream &OS); /// Print the specified operand of MI, an INLINEASM instruction, using the /// specified assembler variant as an address. Targets should override this to /// format as appropriate. This method can return true if the operand is /// erroneous. virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &OS); + const char *ExtraCode, raw_ostream &OS); /// Let the target do anything it needs to do before emitting inlineasm. /// \p StartInfo - the subtarget info before parsing inline asm @@ -617,6 +626,15 @@ public: virtual void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, const MCSubtargetInfo *EndInfo) const; + /// This emits visibility information about symbol, if this is supported by + /// the target. + void EmitVisibility(MCSymbol *Sym, unsigned Visibility, + bool IsDefinition = true) const; + + /// This emits linkage information about \p GVSym based on \p GV, if this is + /// supported by the target. + void EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const; + private: /// Private state for PrintSpecial() // Assign a unique ID to this machine instruction. @@ -647,13 +665,6 @@ private: // Internal Implementation Details //===------------------------------------------------------------------===// - /// This emits visibility information about symbol, if this is supported by - /// the target. - void EmitVisibility(MCSymbol *Sym, unsigned Visibility, - bool IsDefinition = true) const; - - void EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const; - void EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid) const; void EmitLLVMUsedList(const ConstantArray *InitList); diff --git a/include/llvm/CodeGen/AsmPrinterHandler.h b/include/llvm/CodeGen/AsmPrinterHandler.h index a8b13200dd4e..affb558f2fa6 100644 --- a/include/llvm/CodeGen/AsmPrinterHandler.h +++ b/include/llvm/CodeGen/AsmPrinterHandler.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/AsmPrinterHandler.h -----------------------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/AtomicExpandUtils.h b/include/llvm/CodeGen/AtomicExpandUtils.h index b1adf66e7ff4..8a46c6e00d22 100644 --- a/include/llvm/CodeGen/AtomicExpandUtils.h +++ b/include/llvm/CodeGen/AtomicExpandUtils.h @@ -1,9 +1,8 @@ //===- AtomicExpandUtils.h - Utilities for expanding atomic instructions --===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h index f105d887c397..70bf670fdf0b 100644 --- a/include/llvm/CodeGen/BasicTTIImpl.h +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -1,9 +1,8 @@ //===- BasicTTIImpl.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -197,11 +196,12 @@ protected: public: /// \name Scalar TTI Implementations /// @{ - bool allowsMisalignedMemoryAccesses(LLVMContext &Context, - unsigned BitWidth, unsigned AddressSpace, - unsigned Alignment, bool *Fast) const { + bool allowsMisalignedMemoryAccesses(LLVMContext &Context, unsigned BitWidth, + unsigned AddressSpace, unsigned Alignment, + bool *Fast) const { EVT E = EVT::getIntegerVT(Context, BitWidth); - return getTLI()->allowsMisalignedMemoryAccesses(E, AddressSpace, Alignment, Fast); + return getTLI()->allowsMisalignedMemoryAccesses( + E, AddressSpace, Alignment, MachineMemOperand::MONone, Fast); } bool hasBranchDivergence() { return false; } @@ -293,12 +293,12 @@ public: } unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<const Value *> Arguments) { - return BaseT::getIntrinsicCost(IID, RetTy, Arguments); + ArrayRef<const Value *> Arguments, const User *U) { + return BaseT::getIntrinsicCost(IID, RetTy, Arguments, U); } unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<Type *> ParamTys) { + ArrayRef<Type *> ParamTys, const User *U) { if (IID == Intrinsic::cttz) { if (getTLI()->isCheapToSpeculateCttz()) return TargetTransformInfo::TCC_Basic; @@ -311,7 +311,7 @@ public: return TargetTransformInfo::TCC_Expensive; } - return BaseT::getIntrinsicCost(IID, RetTy, ParamTys); + return BaseT::getIntrinsicCost(IID, RetTy, ParamTys, U); } unsigned getEstimatedNumberOfCaseClusters(const SwitchInst &SI, @@ -414,6 +414,12 @@ public: if (TLI->isZExtFree(OpTy, Ty)) return TargetTransformInfo::TCC_Free; return TargetTransformInfo::TCC_Basic; + + case Instruction::AddrSpaceCast: + if (TLI->isFreeAddrSpaceCast(OpTy->getPointerAddressSpace(), + Ty->getPointerAddressSpace())) + return TargetTransformInfo::TCC_Free; + return TargetTransformInfo::TCC_Basic; } return BaseT::getOperationCost(Opcode, Ty, OpTy); @@ -421,6 +427,8 @@ public: unsigned getInliningThresholdMultiplier() { return 1; } + int getInlinerVectorBonusPercent() { return 150; } + void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP) { // This unrolling functionality is target independent, but to provide some @@ -486,6 +494,13 @@ public: UP.BEInsns = 2; } + bool isHardwareLoopProfitable(Loop *L, ScalarEvolution &SE, + AssumptionCache &AC, + TargetLibraryInfo *LibInfo, + HardwareLoopInfo &HWLoopInfo) { + return BaseT::isHardwareLoopProfitable(L, SE, AC, LibInfo, HWLoopInfo); + } + int getInstructionLatency(const Instruction *I) { if (isa<LoadInst>(I)) return getST()->getSchedModel().DefaultLoadLatency; @@ -657,7 +672,7 @@ public: return 0; if (Opcode == Instruction::AddrSpaceCast && - TLI->isNoopAddrSpaceCast(Src->getPointerAddressSpace(), + TLI->isFreeAddrSpaceCast(Src->getPointerAddressSpace(), Dst->getPointerAddressSpace())) return 0; @@ -997,7 +1012,7 @@ public: // inside the loop. if (UseMaskForGaps) Cost += static_cast<T *>(this)->getArithmeticInstrCost( - BinaryOperator::And, MaskVT); + BinaryOperator::And, MaskVT); return Cost; } @@ -1058,8 +1073,8 @@ public: case Intrinsic::experimental_vector_reduce_and: case Intrinsic::experimental_vector_reduce_or: case Intrinsic::experimental_vector_reduce_xor: - case Intrinsic::experimental_vector_reduce_fadd: - case Intrinsic::experimental_vector_reduce_fmul: + case Intrinsic::experimental_vector_reduce_v2_fadd: + case Intrinsic::experimental_vector_reduce_v2_fmul: case Intrinsic::experimental_vector_reduce_smax: case Intrinsic::experimental_vector_reduce_smin: case Intrinsic::experimental_vector_reduce_fmax: @@ -1116,6 +1131,9 @@ public: unsigned getIntrinsicInstrCost( Intrinsic::ID IID, Type *RetTy, ArrayRef<Type *> Tys, FastMathFlags FMF, unsigned ScalarizationCostPassed = std::numeric_limits<unsigned>::max()) { + unsigned RetVF = (RetTy->isVectorTy() ? RetTy->getVectorNumElements() : 1); + auto *ConcreteTTI = static_cast<T *>(this); + SmallVector<unsigned, 2> ISDs; unsigned SingleCallCost = 10; // Library call cost. Make it expensive. switch (IID) { @@ -1144,8 +1162,8 @@ public: if (ScalarCalls == 1) return 1; // Return cost of a scalar intrinsic. Assume it to be cheap. - unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost( - IID, ScalarRetTy, ScalarTys, FMF); + unsigned ScalarCost = + ConcreteTTI->getIntrinsicInstrCost(IID, ScalarRetTy, ScalarTys, FMF); return ScalarCalls * ScalarCost + ScalarizationCost; } @@ -1227,44 +1245,181 @@ public: case Intrinsic::sideeffect: return 0; case Intrinsic::masked_store: - return static_cast<T *>(this) - ->getMaskedMemoryOpCost(Instruction::Store, Tys[0], 0, 0); + return ConcreteTTI->getMaskedMemoryOpCost(Instruction::Store, Tys[0], 0, + 0); case Intrinsic::masked_load: - return static_cast<T *>(this) - ->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0); + return ConcreteTTI->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0); case Intrinsic::experimental_vector_reduce_add: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::Add, Tys[0], /*IsPairwiseForm=*/false); + return ConcreteTTI->getArithmeticReductionCost(Instruction::Add, Tys[0], + /*IsPairwiseForm=*/false); case Intrinsic::experimental_vector_reduce_mul: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::Mul, Tys[0], /*IsPairwiseForm=*/false); + return ConcreteTTI->getArithmeticReductionCost(Instruction::Mul, Tys[0], + /*IsPairwiseForm=*/false); case Intrinsic::experimental_vector_reduce_and: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::And, Tys[0], /*IsPairwiseForm=*/false); + return ConcreteTTI->getArithmeticReductionCost(Instruction::And, Tys[0], + /*IsPairwiseForm=*/false); case Intrinsic::experimental_vector_reduce_or: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::Or, Tys[0], /*IsPairwiseForm=*/false); + return ConcreteTTI->getArithmeticReductionCost(Instruction::Or, Tys[0], + /*IsPairwiseForm=*/false); case Intrinsic::experimental_vector_reduce_xor: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::Xor, Tys[0], /*IsPairwiseForm=*/false); - case Intrinsic::experimental_vector_reduce_fadd: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::FAdd, Tys[0], /*IsPairwiseForm=*/false); - case Intrinsic::experimental_vector_reduce_fmul: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::FMul, Tys[0], /*IsPairwiseForm=*/false); + return ConcreteTTI->getArithmeticReductionCost(Instruction::Xor, Tys[0], + /*IsPairwiseForm=*/false); + case Intrinsic::experimental_vector_reduce_v2_fadd: + return ConcreteTTI->getArithmeticReductionCost( + Instruction::FAdd, Tys[0], + /*IsPairwiseForm=*/false); // FIXME: Add new flag for cost of strict + // reductions. + case Intrinsic::experimental_vector_reduce_v2_fmul: + return ConcreteTTI->getArithmeticReductionCost( + Instruction::FMul, Tys[0], + /*IsPairwiseForm=*/false); // FIXME: Add new flag for cost of strict + // reductions. case Intrinsic::experimental_vector_reduce_smax: case Intrinsic::experimental_vector_reduce_smin: case Intrinsic::experimental_vector_reduce_fmax: case Intrinsic::experimental_vector_reduce_fmin: - return static_cast<T *>(this)->getMinMaxReductionCost( + return ConcreteTTI->getMinMaxReductionCost( Tys[0], CmpInst::makeCmpResultType(Tys[0]), /*IsPairwiseForm=*/false, - /*IsSigned=*/true); + /*IsUnsigned=*/true); case Intrinsic::experimental_vector_reduce_umax: case Intrinsic::experimental_vector_reduce_umin: - return static_cast<T *>(this)->getMinMaxReductionCost( + return ConcreteTTI->getMinMaxReductionCost( Tys[0], CmpInst::makeCmpResultType(Tys[0]), /*IsPairwiseForm=*/false, - /*IsSigned=*/false); + /*IsUnsigned=*/false); + case Intrinsic::sadd_sat: + case Intrinsic::ssub_sat: { + Type *CondTy = Type::getInt1Ty(RetTy->getContext()); + if (RetVF > 1) + CondTy = VectorType::get(CondTy, RetVF); + + Type *OpTy = StructType::create({RetTy, CondTy}); + Intrinsic::ID OverflowOp = IID == Intrinsic::sadd_sat + ? Intrinsic::sadd_with_overflow + : Intrinsic::ssub_with_overflow; + + // SatMax -> Overflow && SumDiff < 0 + // SatMin -> Overflow && SumDiff >= 0 + unsigned Cost = 0; + Cost += ConcreteTTI->getIntrinsicInstrCost( + OverflowOp, OpTy, {RetTy, RetTy}, FMF, ScalarizationCostPassed); + Cost += ConcreteTTI->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, + CondTy, nullptr); + Cost += 2 * ConcreteTTI->getCmpSelInstrCost(BinaryOperator::Select, RetTy, + CondTy, nullptr); + return Cost; + } + case Intrinsic::uadd_sat: + case Intrinsic::usub_sat: { + Type *CondTy = Type::getInt1Ty(RetTy->getContext()); + if (RetVF > 1) + CondTy = VectorType::get(CondTy, RetVF); + + Type *OpTy = StructType::create({RetTy, CondTy}); + Intrinsic::ID OverflowOp = IID == Intrinsic::uadd_sat + ? Intrinsic::uadd_with_overflow + : Intrinsic::usub_with_overflow; + + unsigned Cost = 0; + Cost += ConcreteTTI->getIntrinsicInstrCost( + OverflowOp, OpTy, {RetTy, RetTy}, FMF, ScalarizationCostPassed); + Cost += ConcreteTTI->getCmpSelInstrCost(BinaryOperator::Select, RetTy, + CondTy, nullptr); + return Cost; + } + case Intrinsic::smul_fix: + case Intrinsic::umul_fix: { + unsigned ExtSize = RetTy->getScalarSizeInBits() * 2; + Type *ExtTy = Type::getIntNTy(RetTy->getContext(), ExtSize); + if (RetVF > 1) + ExtTy = VectorType::get(ExtTy, RetVF); + + unsigned ExtOp = + IID == Intrinsic::smul_fix ? Instruction::SExt : Instruction::ZExt; + + unsigned Cost = 0; + Cost += 2 * ConcreteTTI->getCastInstrCost(ExtOp, ExtTy, RetTy); + Cost += ConcreteTTI->getArithmeticInstrCost(Instruction::Mul, ExtTy); + Cost += + 2 * ConcreteTTI->getCastInstrCost(Instruction::Trunc, RetTy, ExtTy); + Cost += ConcreteTTI->getArithmeticInstrCost(Instruction::LShr, RetTy, + TTI::OK_AnyValue, + TTI::OK_UniformConstantValue); + Cost += ConcreteTTI->getArithmeticInstrCost(Instruction::Shl, RetTy, + TTI::OK_AnyValue, + TTI::OK_UniformConstantValue); + Cost += ConcreteTTI->getArithmeticInstrCost(Instruction::Or, RetTy); + return Cost; + } + case Intrinsic::sadd_with_overflow: + case Intrinsic::ssub_with_overflow: { + Type *SumTy = RetTy->getContainedType(0); + Type *OverflowTy = RetTy->getContainedType(1); + unsigned Opcode = IID == Intrinsic::sadd_with_overflow + ? BinaryOperator::Add + : BinaryOperator::Sub; + + // LHSSign -> LHS >= 0 + // RHSSign -> RHS >= 0 + // SumSign -> Sum >= 0 + // + // Add: + // Overflow -> (LHSSign == RHSSign) && (LHSSign != SumSign) + // Sub: + // Overflow -> (LHSSign != RHSSign) && (LHSSign != SumSign) + unsigned Cost = 0; + Cost += ConcreteTTI->getArithmeticInstrCost(Opcode, SumTy); + Cost += 3 * ConcreteTTI->getCmpSelInstrCost(BinaryOperator::ICmp, SumTy, + OverflowTy, nullptr); + Cost += 2 * ConcreteTTI->getCmpSelInstrCost( + BinaryOperator::ICmp, OverflowTy, OverflowTy, nullptr); + Cost += + ConcreteTTI->getArithmeticInstrCost(BinaryOperator::And, OverflowTy); + return Cost; + } + case Intrinsic::uadd_with_overflow: + case Intrinsic::usub_with_overflow: { + Type *SumTy = RetTy->getContainedType(0); + Type *OverflowTy = RetTy->getContainedType(1); + unsigned Opcode = IID == Intrinsic::uadd_with_overflow + ? BinaryOperator::Add + : BinaryOperator::Sub; + + unsigned Cost = 0; + Cost += ConcreteTTI->getArithmeticInstrCost(Opcode, SumTy); + Cost += ConcreteTTI->getCmpSelInstrCost(BinaryOperator::ICmp, SumTy, + OverflowTy, nullptr); + return Cost; + } + case Intrinsic::smul_with_overflow: + case Intrinsic::umul_with_overflow: { + Type *MulTy = RetTy->getContainedType(0); + Type *OverflowTy = RetTy->getContainedType(1); + unsigned ExtSize = MulTy->getScalarSizeInBits() * 2; + Type *ExtTy = Type::getIntNTy(RetTy->getContext(), ExtSize); + if (MulTy->isVectorTy()) + ExtTy = VectorType::get(ExtTy, MulTy->getVectorNumElements() ); + + unsigned ExtOp = + IID == Intrinsic::smul_fix ? Instruction::SExt : Instruction::ZExt; + + unsigned Cost = 0; + Cost += 2 * ConcreteTTI->getCastInstrCost(ExtOp, ExtTy, MulTy); + Cost += ConcreteTTI->getArithmeticInstrCost(Instruction::Mul, ExtTy); + Cost += + 2 * ConcreteTTI->getCastInstrCost(Instruction::Trunc, MulTy, ExtTy); + Cost += ConcreteTTI->getArithmeticInstrCost(Instruction::LShr, MulTy, + TTI::OK_AnyValue, + TTI::OK_UniformConstantValue); + + if (IID == Intrinsic::smul_with_overflow) + Cost += ConcreteTTI->getArithmeticInstrCost( + Instruction::AShr, MulTy, TTI::OK_AnyValue, + TTI::OK_UniformConstantValue); + + Cost += ConcreteTTI->getCmpSelInstrCost(BinaryOperator::ICmp, MulTy, + OverflowTy, nullptr); + return Cost; + } case Intrinsic::ctpop: ISDs.push_back(ISD::CTPOP); // In case of legalization use TCC_Expensive. This is cheaper than a @@ -1305,17 +1460,16 @@ public: if (MinLegalCostI != LegalCost.end()) return *MinLegalCostI; - auto MinCustomCostI = std::min_element(CustomCost.begin(), CustomCost.end()); + auto MinCustomCostI = + std::min_element(CustomCost.begin(), CustomCost.end()); if (MinCustomCostI != CustomCost.end()) return *MinCustomCostI; // If we can't lower fmuladd into an FMA estimate the cost as a floating // point mul followed by an add. if (IID == Intrinsic::fmuladd) - return static_cast<T *>(this) - ->getArithmeticInstrCost(BinaryOperator::FMul, RetTy) + - static_cast<T *>(this) - ->getArithmeticInstrCost(BinaryOperator::FAdd, RetTy); + return ConcreteTTI->getArithmeticInstrCost(BinaryOperator::FMul, RetTy) + + ConcreteTTI->getArithmeticInstrCost(BinaryOperator::FAdd, RetTy); // Else, assume that we need to scalarize this intrinsic. For math builtins // this will emit a costly libcall, adding call overhead and spills. Make it @@ -1333,7 +1487,7 @@ public: Ty = Ty->getScalarType(); ScalarTys.push_back(Ty); } - unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost( + unsigned ScalarCost = ConcreteTTI->getIntrinsicInstrCost( IID, RetTy->getScalarType(), ScalarTys, FMF); for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { if (Tys[i]->isVectorTy()) { diff --git a/include/llvm/CodeGen/BuiltinGCs.h b/include/llvm/CodeGen/BuiltinGCs.h index 1767922fb5ac..d44183dab0f7 100644 --- a/include/llvm/CodeGen/BuiltinGCs.h +++ b/include/llvm/CodeGen/BuiltinGCs.h @@ -1,9 +1,8 @@ //===-- BuiltinGCs.h - Garbage collector linkage hacks --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/CSEConfigBase.h b/include/llvm/CodeGen/CSEConfigBase.h new file mode 100644 index 000000000000..70b5e5c17eb1 --- /dev/null +++ b/include/llvm/CodeGen/CSEConfigBase.h @@ -0,0 +1,28 @@ +//===- CSEConfigBase.h - A CSEConfig interface ------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_CSECONFIG_BASE_H +#define LLVM_CODEGEN_CSECONFIG_BASE_H + +namespace llvm { +// Class representing some configuration that can be done during GlobalISel's +// CSEInfo analysis. We define it here because TargetPassConfig can't depend on +// the GlobalISel library, and so we use this in the interface between them +// so that the derived classes in GISel can reference generic opcodes. +class CSEConfigBase { +public: + virtual ~CSEConfigBase() = default; + // Hook for defining which Generic instructions should be CSEd. + // GISelCSEInfo currently only calls this hook when dealing with generic + // opcodes. + virtual bool shouldCSEOpc(unsigned Opc) { return false; } +}; + +} // namespace llvm + +#endif // LLVM_CODEGEN_CSECONFIG_BASE_H diff --git a/include/llvm/CodeGen/CalcSpillWeights.h b/include/llvm/CodeGen/CalcSpillWeights.h index f85767f1fc11..9b8b7324f30a 100644 --- a/include/llvm/CodeGen/CalcSpillWeights.h +++ b/include/llvm/CodeGen/CalcSpillWeights.h @@ -1,9 +1,8 @@ //===- lib/CodeGen/CalcSpillWeights.h ---------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index efcf80ba0b4e..aa339e1cc913 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -1,9 +1,8 @@ //===- llvm/CallingConvLower.h - Calling Conventions ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -146,7 +145,7 @@ public: bool needsCustom() const { return isCustom; } - unsigned getLocReg() const { assert(isRegLoc()); return Loc; } + Register getLocReg() const { assert(isRegLoc()); return Loc; } unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; } unsigned getExtraInfo() const { return Loc; } MVT getLocVT() const { return LocVT; } @@ -557,7 +556,7 @@ public: // Sort the locations of the arguments according to their original position. SmallVector<CCValAssign, 16> TmpArgLocs; - std::swap(TmpArgLocs, Locs); + TmpArgLocs.swap(Locs); auto B = TmpArgLocs.begin(), E = TmpArgLocs.end(); std::merge(B, B + NumFirstPassLocs, B + NumFirstPassLocs, E, std::back_inserter(Locs), diff --git a/include/llvm/CodeGen/CommandFlags.inc b/include/llvm/CodeGen/CommandFlags.inc index 568d329a5e8c..cb69e9f61405 100644 --- a/include/llvm/CodeGen/CommandFlags.inc +++ b/include/llvm/CodeGen/CommandFlags.inc @@ -1,9 +1,8 @@ //===-- CommandFlags.h - Command Line Flags Interface -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -272,6 +271,11 @@ static cl::opt<bool> EnableAddrsig("addrsig", cl::desc("Emit an address-significance table"), cl::init(false)); +static cl::opt<bool> + EnableDebugEntryValues("debug-entry-values", + cl::desc("Emit debug info about parameter's entry values"), + cl::init(false)); + // Common utility function tightly tied to the options listed here. Initializes // a TargetOptions object with CodeGen flags and returns it. static TargetOptions InitTargetOptionsFromCodeGenFlags() { @@ -301,6 +305,7 @@ static TargetOptions InitTargetOptionsFromCodeGenFlags() { Options.ExceptionModel = ExceptionModel; Options.EmitStackSizeSection = EnableStackSizeSection; Options.EmitAddrsig = EnableAddrsig; + Options.EnableDebugEntryValues = EnableDebugEntryValues; Options.MCOptions = InitMCTargetOptionsFromFlags(); diff --git a/include/llvm/CodeGen/CostTable.h b/include/llvm/CodeGen/CostTable.h index 48ad76971520..52f3bfaea180 100644 --- a/include/llvm/CodeGen/CostTable.h +++ b/include/llvm/CodeGen/CostTable.h @@ -1,9 +1,8 @@ //===-- CostTable.h - Instruction Cost Table handling -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/CodeGen/DAGCombine.h b/include/llvm/CodeGen/DAGCombine.h index 8b5919005451..944187341455 100644 --- a/include/llvm/CodeGen/DAGCombine.h +++ b/include/llvm/CodeGen/DAGCombine.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/DAGCombine.h ------- SelectionDAG Nodes ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/DFAPacketizer.h b/include/llvm/CodeGen/DFAPacketizer.h index d3aabe22f216..cf58ee0cabea 100644 --- a/include/llvm/CodeGen/DFAPacketizer.h +++ b/include/llvm/CodeGen/DFAPacketizer.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/DFAPacketizer.h - DFA Packetizer for VLIW ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 class implements a deterministic finite automaton (DFA) based diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h index 7d486b1df56d..684f9e40ca5a 100644 --- a/include/llvm/CodeGen/DIE.h +++ b/include/llvm/CodeGen/DIE.h @@ -1,9 +1,8 @@ //===- lib/CodeGen/DIE.h - DWARF Info Entries -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -39,6 +38,7 @@ namespace llvm { class AsmPrinter; class DIE; class DIEUnit; +class DwarfCompileUnit; class MCExpr; class MCSection; class MCSymbol; @@ -231,6 +231,25 @@ public: }; //===--------------------------------------------------------------------===// +/// A BaseTypeRef DIE. +class DIEBaseTypeRef { + const DwarfCompileUnit *CU; + const uint64_t Index; + static constexpr unsigned ULEB128PadSize = 4; + +public: + explicit DIEBaseTypeRef(const DwarfCompileUnit *TheCU, uint64_t Idx) + : CU(TheCU), Index(Idx) {} + + /// EmitValue - Emit base type reference. + void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + /// SizeOf - Determine size of the base type reference in bytes. + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; + + void print(raw_ostream &O) const; +}; + +//===--------------------------------------------------------------------===// /// A simple label difference DIE. /// class DIEDelta { @@ -350,7 +369,7 @@ private: /// should be stored by reference instead of by value. using ValTy = AlignedCharArrayUnion<DIEInteger, DIEString, DIEExpr, DIELabel, DIEDelta *, DIEEntry, DIEBlock *, - DIELoc *, DIELocList>; + DIELoc *, DIELocList, DIEBaseTypeRef *>; static_assert(sizeof(ValTy) <= sizeof(uint64_t) || sizeof(ValTy) <= sizeof(void *), @@ -502,6 +521,18 @@ struct IntrusiveBackListBase { } Last = &N; } + + void push_front(Node &N) { + assert(N.Next.getPointer() == &N && "Expected unlinked node"); + assert(N.Next.getInt() == true && "Expected unlinked node"); + + if (Last) { + N.Next.setPointerAndInt(Last->Next.getPointer(), false); + Last->Next.setPointerAndInt(&N, true); + } else { + Last = &N; + } + } }; template <class T> class IntrusiveBackList : IntrusiveBackListBase { @@ -509,8 +540,15 @@ public: using IntrusiveBackListBase::empty; void push_back(T &N) { IntrusiveBackListBase::push_back(N); } + void push_front(T &N) { IntrusiveBackListBase::push_front(N); } T &back() { return *static_cast<T *>(Last); } const T &back() const { return *static_cast<T *>(Last); } + T &front() { + return *static_cast<T *>(Last ? Last->Next.getPointer() : nullptr); + } + const T &front() const { + return *static_cast<T *>(Last ? Last->Next.getPointer() : nullptr); + } class const_iterator; class iterator @@ -760,7 +798,7 @@ public: /// /// \returns the DIEUnit that represents the compile or type unit that owns /// this DIE, or NULL if this DIE hasn't been added to a unit DIE. - const DIEUnit *getUnit() const; + DIEUnit *getUnit() const; void setOffset(unsigned O) { Offset = O; } void setSize(unsigned S) { Size = S; } @@ -773,6 +811,13 @@ public: return Children.back(); } + DIE &addChildFront(DIE *Child) { + assert(!Child->getParent() && "Child should be orphaned"); + Child->Owner = this; + Children.push_front(*Child); + return Children.front(); + } + /// Find a value in the DIE with the attribute given. /// /// Returns a default-constructed DIEValue (where \a DIEValue::getType() @@ -800,7 +845,7 @@ class DIEUnit { const uint16_t Version; /// The Dwarf version number for this unit. const uint8_t AddrSize; /// The size in bytes of an address for this unit. protected: - ~DIEUnit() = default; + virtual ~DIEUnit() = default; public: DIEUnit(uint16_t Version, uint8_t AddrSize, dwarf::Tag UnitTag); diff --git a/include/llvm/CodeGen/DIEValue.def b/include/llvm/CodeGen/DIEValue.def index a3fce9b1d20c..92afeb3868b4 100644 --- a/include/llvm/CodeGen/DIEValue.def +++ b/include/llvm/CodeGen/DIEValue.def @@ -1,9 +1,8 @@ //===- llvm/CodeGen/DIEValue.def - DIEValue types ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -35,6 +34,7 @@ HANDLE_DIEVALUE_SMALL(Integer) HANDLE_DIEVALUE_SMALL(String) HANDLE_DIEVALUE_SMALL(Expr) HANDLE_DIEVALUE_SMALL(Label) +HANDLE_DIEVALUE_LARGE(BaseTypeRef) HANDLE_DIEVALUE_LARGE(Delta) HANDLE_DIEVALUE_SMALL(Entry) HANDLE_DIEVALUE_LARGE(Block) diff --git a/include/llvm/CodeGen/DbgEntityHistoryCalculator.h b/include/llvm/CodeGen/DbgEntityHistoryCalculator.h index befc28f084e7..7eec75bc81bf 100644 --- a/include/llvm/CodeGen/DbgEntityHistoryCalculator.h +++ b/include/llvm/CodeGen/DbgEntityHistoryCalculator.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/DbgEntityHistoryCalculator.h ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -11,6 +10,7 @@ #define LLVM_CODEGEN_DBGVALUEHISTORYCALCULATOR_H #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/DebugInfoMetadata.h" #include <utility> @@ -22,35 +22,76 @@ class MachineFunction; class MachineInstr; class TargetRegisterInfo; -// For each user variable, keep a list of instruction ranges where this variable -// is accessible. The variables are listed in order of appearance. +/// For each user variable, keep a list of instruction ranges where this +/// variable is accessible. The variables are listed in order of appearance. class DbgValueHistoryMap { - // Each instruction range starts with a DBG_VALUE instruction, specifying the - // location of a variable, which is assumed to be valid until the end of the - // range. If end is not specified, location is valid until the start - // instruction of the next instruction range, or until the end of the - // function. public: - using InstrRange = std::pair<const MachineInstr *, const MachineInstr *>; - using InstrRanges = SmallVector<InstrRange, 4>; + /// Index in the entry vector. + typedef size_t EntryIndex; + + /// Special value to indicate that an entry is valid until the end of the + /// function. + static const EntryIndex NoEntry = std::numeric_limits<EntryIndex>::max(); + + /// Specifies a change in a variable's debug value history. + /// + /// There exist two types of entries: + /// + /// * Debug value entry: + /// + /// A new debug value becomes live. If the entry's \p EndIndex is \p NoEntry, + /// the value is valid until the end of the function. For other values, the + /// index points to the entry in the entry vector that ends this debug + /// value. The ending entry can either be an overlapping debug value, or + /// an instruction that clobbers the value. + /// + /// * Clobbering entry: + /// + /// This entry's instruction clobbers one or more preceding + /// register-described debug values that have their end index + /// set to this entry's position in the entry vector. + class Entry { + public: + enum EntryKind { DbgValue, Clobber }; + + Entry(const MachineInstr *Instr, EntryKind Kind) + : Instr(Instr, Kind), EndIndex(NoEntry) {} + + const MachineInstr *getInstr() const { return Instr.getPointer(); } + EntryIndex getEndIndex() const { return EndIndex; } + EntryKind getEntryKind() const { return Instr.getInt(); } + + bool isClobber() const { return getEntryKind() == Clobber; } + bool isDbgValue() const { return getEntryKind() == DbgValue; } + bool isClosed() const { return EndIndex != NoEntry; } + + void endEntry(EntryIndex EndIndex); + + private: + PointerIntPair<const MachineInstr *, 1, EntryKind> Instr; + EntryIndex EndIndex; + }; + using Entries = SmallVector<Entry, 4>; using InlinedEntity = std::pair<const DINode *, const DILocation *>; - using InstrRangesMap = MapVector<InlinedEntity, InstrRanges>; + using EntriesMap = MapVector<InlinedEntity, Entries>; private: - InstrRangesMap VarInstrRanges; + EntriesMap VarEntries; public: - void startInstrRange(InlinedEntity Var, const MachineInstr &MI); - void endInstrRange(InlinedEntity Var, const MachineInstr &MI); + bool startDbgValue(InlinedEntity Var, const MachineInstr &MI, + EntryIndex &NewIndex); + EntryIndex startClobber(InlinedEntity Var, const MachineInstr &MI); - // Returns register currently describing @Var. If @Var is currently - // unaccessible or is not described by a register, returns 0. - unsigned getRegisterForVar(InlinedEntity Var) const; + Entry &getEntry(InlinedEntity Var, EntryIndex Index) { + auto &Entries = VarEntries[Var]; + return Entries[Index]; + } - bool empty() const { return VarInstrRanges.empty(); } - void clear() { VarInstrRanges.clear(); } - InstrRangesMap::const_iterator begin() const { return VarInstrRanges.begin(); } - InstrRangesMap::const_iterator end() const { return VarInstrRanges.end(); } + bool empty() const { return VarEntries.empty(); } + void clear() { VarEntries.clear(); } + EntriesMap::const_iterator begin() const { return VarEntries.begin(); } + EntriesMap::const_iterator end() const { return VarEntries.end(); } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void dump() const; diff --git a/include/llvm/CodeGen/DebugHandlerBase.h b/include/llvm/CodeGen/DebugHandlerBase.h index 4f0d14d317f2..4008d597395e 100644 --- a/include/llvm/CodeGen/DebugHandlerBase.h +++ b/include/llvm/CodeGen/DebugHandlerBase.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/DebugHandlerBase.h -----------------------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -130,7 +129,7 @@ public: const MCExpr *getFunctionLocalOffsetAfterInsn(const MachineInstr *MI); /// If this type is derived from a base type then return base type size. - static uint64_t getBaseTypeSize(const DITypeRef TyRef); + static uint64_t getBaseTypeSize(const DIType *Ty); }; } diff --git a/include/llvm/CodeGen/DwarfStringPoolEntry.h b/include/llvm/CodeGen/DwarfStringPoolEntry.h index 8b1a7af17bbf..e189352a7b2d 100644 --- a/include/llvm/CodeGen/DwarfStringPoolEntry.h +++ b/include/llvm/CodeGen/DwarfStringPoolEntry.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/DwarfStringPoolEntry.h - String pool entry --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/EdgeBundles.h b/include/llvm/CodeGen/EdgeBundles.h index c31fad246c96..28cdf54e0575 100644 --- a/include/llvm/CodeGen/EdgeBundles.h +++ b/include/llvm/CodeGen/EdgeBundles.h @@ -1,9 +1,8 @@ //===-------- EdgeBundles.h - Bundles of CFG edges --------------*- c++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ExecutionDomainFix.h b/include/llvm/CodeGen/ExecutionDomainFix.h index 338c214dd073..6836678e2101 100644 --- a/include/llvm/CodeGen/ExecutionDomainFix.h +++ b/include/llvm/CodeGen/ExecutionDomainFix.h @@ -1,9 +1,8 @@ //==-- llvm/CodeGen/ExecutionDomainFix.h - Execution Domain Fix -*- C++ -*--==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ExpandReductions.h b/include/llvm/CodeGen/ExpandReductions.h index c6aaaad967b3..5dbed07873c1 100644 --- a/include/llvm/CodeGen/ExpandReductions.h +++ b/include/llvm/CodeGen/ExpandReductions.h @@ -1,9 +1,8 @@ //===----- ExpandReductions.h - Expand experimental reduction intrinsics --===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 865d8a88b8cc..f09b59daf4dd 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -1,9 +1,8 @@ //===- FastISel.h - Definition of the FastISel class ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -528,7 +527,7 @@ protected: /// Select and emit code for a binary operator instruction, which has /// an opcode which directly corresponds to the given ISD opcode. bool selectBinaryOp(const User *I, unsigned ISDOpcode); - bool selectFNeg(const User *I); + bool selectFNeg(const User *I, const Value *In); bool selectGetElementPtr(const User *I); bool selectStackmap(const CallInst *I); bool selectPatchpoint(const CallInst *I); diff --git a/include/llvm/CodeGen/FaultMaps.h b/include/llvm/CodeGen/FaultMaps.h index 55e25c9823b1..a1e2349c413e 100644 --- a/include/llvm/CodeGen/FaultMaps.h +++ b/include/llvm/CodeGen/FaultMaps.h @@ -1,9 +1,8 @@ //===- FaultMaps.h - The "FaultMaps" section --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 7c658515de09..fb60191abd3a 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -1,9 +1,8 @@ //===- FunctionLoweringInfo.h - Lower functions from LLVM IR ---*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -14,13 +13,14 @@ #ifndef LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H #define LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H - #include "llvm/ADT/APInt.h" +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/LegacyDivergenceAnalysis.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/TargetRegisterInfo.h" @@ -57,6 +57,7 @@ public: const TargetLowering *TLI; MachineRegisterInfo *RegInfo; BranchProbabilityInfo *BPI; + const LegacyDivergenceAnalysis *DA; /// CanLowerReturn - true iff the function's return value can be lowered to /// registers. bool CanLowerReturn; @@ -71,48 +72,6 @@ public: /// MBBMap - A mapping from LLVM basic blocks to their machine code entry. DenseMap<const BasicBlock*, MachineBasicBlock *> MBBMap; - /// A map from swifterror value in a basic block to the virtual register it is - /// currently represented by. - DenseMap<std::pair<const MachineBasicBlock *, const Value *>, unsigned> - SwiftErrorVRegDefMap; - - /// A list of upward exposed vreg uses that need to be satisfied by either a - /// copy def or a phi node at the beginning of the basic block representing - /// the predecessor(s) swifterror value. - DenseMap<std::pair<const MachineBasicBlock *, const Value *>, unsigned> - SwiftErrorVRegUpwardsUse; - - /// A map from instructions that define/use a swifterror value to the virtual - /// register that represents that def/use. - llvm::DenseMap<PointerIntPair<const Instruction *, 1, bool>, unsigned> - SwiftErrorVRegDefUses; - - /// The swifterror argument of the current function. - const Value *SwiftErrorArg; - - using SwiftErrorValues = SmallVector<const Value*, 1>; - /// A function can only have a single swifterror argument. And if it does - /// have a swifterror argument, it must be the first entry in - /// SwiftErrorVals. - SwiftErrorValues SwiftErrorVals; - - /// Get or create the swifterror value virtual register in - /// SwiftErrorVRegDefMap for this basic block. - unsigned getOrCreateSwiftErrorVReg(const MachineBasicBlock *, - const Value *); - - /// Set the swifterror virtual register in the SwiftErrorVRegDefMap for this - /// basic block. - void setCurrentSwiftErrorVReg(const MachineBasicBlock *MBB, const Value *, - unsigned); - - /// Get or create the swifterror value virtual register for a def of a - /// swifterror by an instruction. - std::pair<unsigned, bool> getOrCreateSwiftErrorVRegDefAt(const Instruction *); - std::pair<unsigned, bool> - getOrCreateSwiftErrorVRegUseAt(const Instruction *, const MachineBasicBlock *, - const Value *); - /// ValueMap - Since we emit code for the function a basic block at a time, /// we must remember which virtual registers hold the values for /// cross-basic-block values. @@ -175,6 +134,10 @@ public: /// function arguments that are inserted after scheduling is completed. SmallVector<MachineInstr*, 8> ArgDbgValues; + /// Bitvector with a bit set if corresponding argument is described in + /// ArgDbgValues. Using arg numbers according to Argument numbering. + BitVector DescribedArgs; + /// RegFixups - Registers which need to be replaced after isel is done. DenseMap<unsigned, unsigned> RegFixups; @@ -236,9 +199,11 @@ public: return ValueMap.count(V); } - unsigned CreateReg(MVT VT); + unsigned CreateReg(MVT VT, bool isDivergent = false); + + unsigned CreateRegs(const Value *V); - unsigned CreateRegs(Type *Ty); + unsigned CreateRegs(Type *Ty, bool isDivergent = false); unsigned InitializeRegForValue(const Value *V) { // Tokens never live in vregs. @@ -247,7 +212,7 @@ public: unsigned &R = ValueMap[V]; assert(R == 0 && "Already initialized this value register!"); assert(VirtReg2Value.empty()); - return R = CreateRegs(V->getType()); + return R = CreateRegs(V); } /// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index 7fb27202c122..77cd356c49dd 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -1,9 +1,8 @@ //===- GCMetadata.h - Garbage collector metadata ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h index 5f1efb2ce02c..f9527c9f8752 100644 --- a/include/llvm/CodeGen/GCMetadataPrinter.h +++ b/include/llvm/CodeGen/GCMetadataPrinter.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GCMetadataPrinter.h - Prints asm GC tables --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h index 5a60cd7cb823..c5731528da4e 100644 --- a/include/llvm/CodeGen/GCStrategy.h +++ b/include/llvm/CodeGen/GCStrategy.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GCStrategy.h - Garbage collection -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/GlobalISel/CSEInfo.h b/include/llvm/CodeGen/GlobalISel/CSEInfo.h index ce2d285a99e5..5a44e67992ad 100644 --- a/include/llvm/CodeGen/GlobalISel/CSEInfo.h +++ b/include/llvm/CodeGen/GlobalISel/CSEInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/CSEInfo.h ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -14,6 +13,7 @@ #define LLVM_CODEGEN_GLOBALISEL_CSEINFO_H #include "llvm/ADT/FoldingSet.h" +#include "llvm/CodeGen/CSEConfigBase.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/GISelWorkList.h" #include "llvm/CodeGen/GlobalISel/Utils.h" @@ -37,25 +37,27 @@ public: void Profile(FoldingSetNodeID &ID); }; -// Class representing some configuration that can be done during CSE analysis. -// Currently it only supports shouldCSE method that each pass can set. -class CSEConfig { +// A CSE config for fully optimized builds. +class CSEConfigFull : public CSEConfigBase { public: - virtual ~CSEConfig() = default; - // Hook for defining which Generic instructions should be CSEd. - // GISelCSEInfo currently only calls this hook when dealing with generic - // opcodes. - virtual bool shouldCSEOpc(unsigned Opc); + virtual ~CSEConfigFull() = default; + virtual bool shouldCSEOpc(unsigned Opc) override; }; -// TODO: Find a better place for this. // Commonly used for O0 config. -class CSEConfigConstantOnly : public CSEConfig { +class CSEConfigConstantOnly : public CSEConfigBase { public: virtual ~CSEConfigConstantOnly() = default; virtual bool shouldCSEOpc(unsigned Opc) override; }; +// Returns the standard expected CSEConfig for the given optimization level. +// We have this logic here so targets can make use of it from their derived +// TargetPassConfig, but can't put this logic into TargetPassConfig directly +// because the CodeGen library can't depend on GlobalISel. +std::unique_ptr<CSEConfigBase> +getStandardCSEConfigForOpt(CodeGenOpt::Level Level); + /// The CSE Analysis object. /// This installs itself as a delegate to the MachineFunction to track /// new instructions as well as deletions. It however will not be able to @@ -74,7 +76,7 @@ class GISelCSEInfo : public GISelChangeObserver { FoldingSet<UniqueMachineInstr> CSEMap; MachineRegisterInfo *MRI = nullptr; MachineFunction *MF = nullptr; - std::unique_ptr<CSEConfig> CSEOpt; + std::unique_ptr<CSEConfigBase> CSEOpt; /// Keep a cache of UniqueInstrs for each MachineInstr. In GISel, /// often instructions are mutated (while their ID has completely changed). /// Whenever mutation happens, invalidate the UniqueMachineInstr for the @@ -139,7 +141,9 @@ public: void releaseMemory(); - void setCSEConfig(std::unique_ptr<CSEConfig> Opt) { CSEOpt = std::move(Opt); } + void setCSEConfig(std::unique_ptr<CSEConfigBase> Opt) { + CSEOpt = std::move(Opt); + } bool shouldCSE(unsigned Opc) const; @@ -199,11 +203,12 @@ class GISelCSEAnalysisWrapper { bool AlreadyComputed = false; public: - /// Takes a CSEConfig object that defines what opcodes get CSEd. + /// Takes a CSEConfigBase object that defines what opcodes get CSEd. /// If CSEConfig is already set, and the CSE Analysis has been preserved, /// it will not use the new CSEOpt(use Recompute to force using the new /// CSEOpt). - GISelCSEInfo &get(std::unique_ptr<CSEConfig> CSEOpt, bool ReCompute = false); + GISelCSEInfo &get(std::unique_ptr<CSEConfigBase> CSEOpt, + bool ReCompute = false); void setMF(MachineFunction &MFunc) { MF = &MFunc; } void setComputed(bool Computed) { AlreadyComputed = Computed; } void releaseMemory() { Info.releaseMemory(); } diff --git a/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h b/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h index a8fb736ebbb5..4f95335db74b 100644 --- a/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h +++ b/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/GlobalISel/CSEMIRBuilder.h --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// \file diff --git a/include/llvm/CodeGen/GlobalISel/CallLowering.h b/include/llvm/CodeGen/GlobalISel/CallLowering.h index ab498e8f070b..d717121ad78e 100644 --- a/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ b/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/CallLowering.h - Call lowering ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -16,6 +15,7 @@ #define LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/TargetCallingConv.h" #include "llvm/IR/CallSite.h" @@ -27,6 +27,7 @@ namespace llvm { +class CCState; class DataLayout; class Function; class MachineIRBuilder; @@ -43,14 +44,19 @@ class CallLowering { virtual void anchor(); public: struct ArgInfo { - unsigned Reg; + SmallVector<Register, 4> Regs; Type *Ty; ISD::ArgFlagsTy Flags; bool IsFixed; - ArgInfo(unsigned Reg, Type *Ty, ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{}, - bool IsFixed = true) - : Reg(Reg), Ty(Ty), Flags(Flags), IsFixed(IsFixed) {} + ArgInfo(ArrayRef<Register> Regs, Type *Ty, + ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{}, bool IsFixed = true) + : Regs(Regs.begin(), Regs.end()), Ty(Ty), Flags(Flags), + IsFixed(IsFixed) { + // FIXME: We should have just one way of saying "no register". + assert((Ty->isVoidTy() == (Regs.empty() || Regs[0] == 0)) && + "only void types should have no register"); + } }; /// Argument handling is mostly uniform between the four places that @@ -66,24 +72,28 @@ public: virtual ~ValueHandler() = default; + /// Returns true if the handler is dealing with formal arguments, + /// not with return values etc. + virtual bool isArgumentHandler() const { return false; } + /// Materialize a VReg containing the address of the specified /// stack-based object. This is either based on a FrameIndex or /// direct SP manipulation, depending on the context. \p MPO /// should be initialized to an appropriate description of the /// address created. - virtual unsigned getStackAddress(uint64_t Size, int64_t Offset, + virtual Register getStackAddress(uint64_t Size, int64_t Offset, MachinePointerInfo &MPO) = 0; /// The specified value has been assigned to a physical register, /// handle the appropriate COPY (either to or from) and mark any /// relevant uses/defines as needed. - virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg, + virtual void assignValueToReg(Register ValVReg, Register PhysReg, CCValAssign &VA) = 0; /// The specified value has been assigned to a stack /// location. Load or store it there, with appropriate extension /// if necessary. - virtual void assignValueToAddress(unsigned ValVReg, unsigned Addr, + virtual void assignValueToAddress(Register ValVReg, Register Addr, uint64_t Size, MachinePointerInfo &MPO, CCValAssign &VA) = 0; @@ -98,7 +108,7 @@ public: llvm_unreachable("Custom values not supported"); } - unsigned extendRegister(unsigned ValReg, CCValAssign &VA); + Register extendRegister(Register ValReg, CCValAssign &VA); virtual bool assignArg(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, const ArgInfo &Info, @@ -130,39 +140,83 @@ protected: void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, const FuncInfoTy &FuncInfo) const; + /// Generate instructions for packing \p SrcRegs into one big register + /// corresponding to the aggregate type \p PackedTy. + /// + /// \param SrcRegs should contain one virtual register for each base type in + /// \p PackedTy, as returned by computeValueLLTs. + /// + /// \return The packed register. + Register packRegs(ArrayRef<Register> SrcRegs, Type *PackedTy, + MachineIRBuilder &MIRBuilder) const; + + /// Generate instructions for unpacking \p SrcReg into the \p DstRegs + /// corresponding to the aggregate type \p PackedTy. + /// + /// \param DstRegs should contain one virtual register for each base type in + /// \p PackedTy, as returned by computeValueLLTs. + void unpackRegs(ArrayRef<Register> DstRegs, Register SrcReg, Type *PackedTy, + MachineIRBuilder &MIRBuilder) const; + /// Invoke Handler::assignArg on each of the given \p Args and then use /// \p Callback to move them to the assigned locations. /// /// \return True if everything has succeeded, false otherwise. bool handleAssignments(MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args, ValueHandler &Handler) const; - + bool handleAssignments(CCState &CCState, + SmallVectorImpl<CCValAssign> &ArgLocs, + MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args, + ValueHandler &Handler) const; public: CallLowering(const TargetLowering *TLI) : TLI(TLI) {} virtual ~CallLowering() = default; + /// \return true if the target is capable of handling swifterror values that + /// have been promoted to a specified register. The extended versions of + /// lowerReturn and lowerCall should be implemented. + virtual bool supportSwiftError() const { + return false; + } + /// This hook must be implemented to lower outgoing return values, described /// by \p Val, into the specified virtual registers \p VRegs. /// This hook is used by GlobalISel. /// + /// \p SwiftErrorVReg is non-zero if the function has a swifterror parameter + /// that needs to be implicitly returned. + /// /// \return True if the lowering succeeds, false otherwise. virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, - ArrayRef<unsigned> VRegs) const { + ArrayRef<Register> VRegs, + Register SwiftErrorVReg) const { + if (!supportSwiftError()) { + assert(SwiftErrorVReg == 0 && "attempt to use unsupported swifterror"); + return lowerReturn(MIRBuilder, Val, VRegs); + } + return false; + } + + /// This hook behaves as the extended lowerReturn function, but for targets + /// that do not support swifterror value promotion. + virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, + ArrayRef<Register> VRegs) const { return false; } /// This hook must be implemented to lower the incoming (formal) - /// arguments, described by \p Args, for GlobalISel. Each argument - /// must end up in the related virtual register described by VRegs. - /// In other words, the first argument should end up in VRegs[0], - /// the second in VRegs[1], and so on. + /// arguments, described by \p VRegs, for GlobalISel. Each argument + /// must end up in the related virtual registers described by \p VRegs. + /// In other words, the first argument should end up in \c VRegs[0], + /// the second in \c VRegs[1], and so on. For each argument, there will be one + /// register for each non-aggregate type, as returned by \c computeValueLLTs. /// \p MIRBuilder is set to the proper insertion for the argument /// lowering. /// /// \return True if the lowering succeeded, false otherwise. virtual bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, - ArrayRef<unsigned> VRegs) const { + ArrayRef<ArrayRef<Register>> VRegs) const { return false; } @@ -174,20 +228,31 @@ public: /// \p Callee is the destination of the call. It should be either a register, /// globaladdress, or externalsymbol. /// - /// \p ResTy is the type returned by the function - /// - /// \p ResReg is the generic virtual register that the returned - /// value should be lowered into. + /// \p OrigRet is a descriptor for the return type of the function. /// - /// \p ArgTys is a list of the types each member of \p ArgRegs has; used by - /// the target to decide which register/stack slot should be allocated. + /// \p OrigArgs is a list of descriptors of the arguments passed to the + /// function. /// - /// \p ArgRegs is a list of virtual registers containing each argument that - /// needs to be passed. + /// \p SwiftErrorVReg is non-zero if the call has a swifterror inout + /// parameter, and contains the vreg that the swifterror should be copied into + /// after the call. /// /// \return true if the lowering succeeded, false otherwise. virtual bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, const MachineOperand &Callee, const ArgInfo &OrigRet, + ArrayRef<ArgInfo> OrigArgs, + Register SwiftErrorVReg) const { + if (!supportSwiftError()) { + assert(SwiftErrorVReg == 0 && "trying to use unsupported swifterror"); + return lowerCall(MIRBuilder, CallConv, Callee, OrigRet, OrigArgs); + } + return false; + } + + /// This hook behaves as the extended lowerCall function, but for targets that + /// do not support swifterror value promotion. + virtual bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, + const MachineOperand &Callee, const ArgInfo &OrigRet, ArrayRef<ArgInfo> OrigArgs) const { return false; } @@ -197,11 +262,18 @@ public: /// /// \p CI is the call/invoke instruction. /// - /// \p ResReg is a register where the call's return value should be stored (or - /// 0 if there is no return value). + /// \p ResRegs are the registers where the call's return value should be + /// stored (or 0 if there is no return value). There will be one register for + /// each non-aggregate type, as returned by \c computeValueLLTs. + /// + /// \p ArgRegs is a list of lists of virtual registers containing each + /// argument that needs to be passed (argument \c i should be placed in \c + /// ArgRegs[i]). For each argument, there will be one register for each + /// non-aggregate type, as returned by \c computeValueLLTs. /// - /// \p ArgRegs is a list of virtual registers containing each argument that - /// needs to be passed. + /// \p SwiftErrorVReg is non-zero if the call has a swifterror inout + /// parameter, and contains the vreg that the swifterror should be copied into + /// after the call. /// /// \p GetCalleeReg is a callback to materialize a register for the callee if /// the target determines it cannot jump to the destination based purely on \p @@ -210,7 +282,8 @@ public: /// /// \return true if the lowering succeeded, false otherwise. bool lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, - unsigned ResReg, ArrayRef<unsigned> ArgRegs, + ArrayRef<Register> ResRegs, + ArrayRef<ArrayRef<Register>> ArgRegs, Register SwiftErrorVReg, std::function<unsigned()> GetCalleeReg) const; }; diff --git a/include/llvm/CodeGen/GlobalISel/Combiner.h b/include/llvm/CodeGen/GlobalISel/Combiner.h index b097c7817762..efe8bdf93664 100644 --- a/include/llvm/CodeGen/GlobalISel/Combiner.h +++ b/include/llvm/CodeGen/GlobalISel/Combiner.h @@ -1,9 +1,8 @@ -//== ----- llvm/CodeGen/GlobalISel/Combiner.h --------------------- == // +//== ----- llvm/CodeGen/GlobalISel/Combiner.h -------------------*- C++ -*-== // // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/include/llvm/CodeGen/GlobalISel/CombinerHelper.h index 6e9ac01c1ee2..0c50c9c5e0cf 100644 --- a/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/GlobalISel/CombinerHelper.h --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===--------------------------------------------------------------------===// // @@ -18,6 +17,9 @@ #ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H #define LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H +#include "llvm/CodeGen/LowLevelType.h" +#include "llvm/CodeGen/Register.h" + namespace llvm { class GISelChangeObserver; @@ -26,6 +28,12 @@ class MachineRegisterInfo; class MachineInstr; class MachineOperand; +struct PreferredTuple { + LLT Ty; // The result type of the extend. + unsigned ExtendOpcode; // G_ANYEXT/G_SEXT/G_ZEXT + MachineInstr *MI; +}; + class CombinerHelper { MachineIRBuilder &Builder; MachineRegisterInfo &MRI; @@ -35,20 +43,27 @@ public: CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B); /// MachineRegisterInfo::replaceRegWith() and inform the observer of the changes - void replaceRegWith(MachineRegisterInfo &MRI, unsigned FromReg, unsigned ToReg) const; + void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const; /// Replace a single register operand with a new register and inform the /// observer of the changes. void replaceRegOpWith(MachineRegisterInfo &MRI, MachineOperand &FromRegOp, - unsigned ToReg) const; + Register ToReg) const; /// If \p MI is COPY, try to combine it. /// Returns true if MI changed. bool tryCombineCopy(MachineInstr &MI); + bool matchCombineCopy(MachineInstr &MI); + void applyCombineCopy(MachineInstr &MI); /// If \p MI is extend that consumes the result of a load, try to combine it. /// Returns true if MI changed. bool tryCombineExtendingLoads(MachineInstr &MI); + bool matchCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo); + void applyCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo); + + bool matchCombineBr(MachineInstr &MI); + bool tryCombineBr(MachineInstr &MI); /// Try to transform \p MI by using all of the above /// combine functions. Returns true if changed. diff --git a/include/llvm/CodeGen/GlobalISel/CombinerInfo.h b/include/llvm/CodeGen/GlobalISel/CombinerInfo.h index d21aa3f725d9..3b09a8e2b479 100644 --- a/include/llvm/CodeGen/GlobalISel/CombinerInfo.h +++ b/include/llvm/CodeGen/GlobalISel/CombinerInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/CombinerInfo.h ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h b/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h index 220a571b21db..e817d9b4550e 100644 --- a/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h +++ b/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// \file diff --git a/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h b/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h index c8e8a7a5a7cb..e5691cb35174 100644 --- a/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h +++ b/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h @@ -1,9 +1,8 @@ -//===----- llvm/CodeGen/GlobalISel/GISelChangeObserver.h ------------------===// +//===----- llvm/CodeGen/GlobalISel/GISelChangeObserver.h --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -34,10 +33,17 @@ public: /// An instruction is about to be erased. virtual void erasingInstr(MachineInstr &MI) = 0; - /// An instruction was created and inserted into the function. + + /// An instruction has been created and inserted into the function. + /// Note that the instruction might not be a fully fledged instruction at this + /// point and won't be if the MachineFunction::Delegate is calling it. This is + /// because the delegate only sees the construction of the MachineInstr before + /// operands have been added. virtual void createdInstr(MachineInstr &MI) = 0; + /// This instruction is about to be mutated in some way. virtual void changingInstr(MachineInstr &MI) = 0; + /// This instruction was mutated in some way. virtual void changedInstr(MachineInstr &MI) = 0; diff --git a/include/llvm/CodeGen/GlobalISel/GISelWorkList.h b/include/llvm/CodeGen/GlobalISel/GISelWorkList.h index 1571841a208d..b0bb519283b1 100644 --- a/include/llvm/CodeGen/GlobalISel/GISelWorkList.h +++ b/include/llvm/CodeGen/GlobalISel/GISelWorkList.h @@ -1,9 +1,8 @@ //===- GISelWorkList.h - Worklist for GISel passes ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -33,23 +32,61 @@ class GISelWorkList { SmallVector<MachineInstr *, N> Worklist; DenseMap<MachineInstr *, unsigned> WorklistMap; +#ifndef NDEBUG + bool Finalized = true; +#endif + public: - GISelWorkList() {} + GISelWorkList() : WorklistMap(N) {} bool empty() const { return WorklistMap.empty(); } unsigned size() const { return WorklistMap.size(); } + // Since we don't know ahead of time how many instructions we're going to add + // to the worklist, and migrating densemap's elements is quite expensive + // everytime we resize, only insert to the smallvector (typically during the + // initial phase of populating lists). Before the worklist can be used, + // finalize should be called. Also assert with NDEBUG if list is ever used + // without finalizing. Note that unlike insert, we won't check for duplicates + // - so the ideal place to use this is during the initial prepopulating phase + // of most passes. + void deferred_insert(MachineInstr *I) { + Worklist.push_back(I); +#ifndef NDEBUG + Finalized = false; +#endif + } + + // This should only be called when using deferred_insert. + // This asserts that the WorklistMap is empty, and then + // inserts all the elements in the Worklist into the map. + // It also asserts if there are any duplicate elements found. + void finalize() { + assert(WorklistMap.empty() && "Expecting empty worklistmap"); + if (Worklist.size() > N) + WorklistMap.reserve(Worklist.size()); + for (unsigned i = 0; i < Worklist.size(); ++i) + if (!WorklistMap.try_emplace(Worklist[i], i).second) + llvm_unreachable("Duplicate elements in the list"); +#ifndef NDEBUG + Finalized = true; +#endif + } + /// Add the specified instruction to the worklist if it isn't already in it. void insert(MachineInstr *I) { + assert(Finalized && "GISelWorkList used without finalizing"); if (WorklistMap.try_emplace(I, Worklist.size()).second) Worklist.push_back(I); } /// Remove I from the worklist if it exists. void remove(const MachineInstr *I) { + assert((Finalized || WorklistMap.empty()) && "Neither finalized nor empty"); auto It = WorklistMap.find(I); - if (It == WorklistMap.end()) return; // Not in worklist. + if (It == WorklistMap.end()) + return; // Not in worklist. // Don't bother moving everything down, just null out the slot. Worklist[It->second] = nullptr; @@ -63,6 +100,7 @@ public: } MachineInstr *pop_back_val() { + assert(Finalized && "GISelWorkList used without finalizing"); MachineInstr *I; do { I = Worklist.pop_back_val(); diff --git a/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/include/llvm/CodeGen/GlobalISel/IRTranslator.h index d1770bf6e4ce..8654ba83f08d 100644 --- a/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/IRTranslator.h - IRTranslator ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// \file @@ -23,7 +22,9 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h" #include "llvm/CodeGen/GlobalISel/Types.h" +#include "llvm/CodeGen/SwiftErrorValueTracking.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/SwitchLoweringUtils.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/Allocator.h" #include <memory> @@ -37,6 +38,7 @@ class CallInst; class CallLowering; class Constant; class DataLayout; +class FunctionLoweringInfo; class Instruction; class MachineBasicBlock; class MachineFunction; @@ -69,7 +71,7 @@ private: public: ValueToVRegInfo() = default; - using VRegListT = SmallVector<unsigned, 1>; + using VRegListT = SmallVector<Register, 1>; using OffsetListT = SmallVector<uint64_t, 1>; using const_vreg_iterator = @@ -164,6 +166,8 @@ private: /// this function. DenseMap<const AllocaInst *, int> FrameIndices; + SwiftErrorValueTracking SwiftError; + /// \name Methods for translating form LLVM IR to MachineInstr. /// \see ::translate for general information on the translate methods. /// @{ @@ -196,7 +200,7 @@ private: /// the function. /// /// \return true if the materialization succeeded. - bool translate(const Constant &C, unsigned Reg); + bool translate(const Constant &C, Register Reg); /// Translate an LLVM bitcast into generic IR. Either a COPY or a G_BITCAST is /// emitted. @@ -212,24 +216,27 @@ private: bool translateMemfunc(const CallInst &CI, MachineIRBuilder &MIRBuilder, unsigned ID); - void getStackGuard(unsigned DstReg, MachineIRBuilder &MIRBuilder); + void getStackGuard(Register DstReg, MachineIRBuilder &MIRBuilder); bool translateOverflowIntrinsic(const CallInst &CI, unsigned Op, MachineIRBuilder &MIRBuilder); + /// Helper function for translateSimpleIntrinsic. + /// \return The generic opcode for \p IntrinsicID if \p IntrinsicID is a + /// simple intrinsic (ceil, fabs, etc.). Otherwise, returns + /// Intrinsic::not_intrinsic. + unsigned getSimpleIntrinsicOpcode(Intrinsic::ID ID); + + /// Translates the intrinsics defined in getSimpleIntrinsicOpcode. + /// \return true if the translation succeeded. + bool translateSimpleIntrinsic(const CallInst &CI, Intrinsic::ID ID, + MachineIRBuilder &MIRBuilder); + bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, MachineIRBuilder &MIRBuilder); bool translateInlineAsm(const CallInst &CI, MachineIRBuilder &MIRBuilder); - // FIXME: temporary function to expose previous interface to call lowering - // until it is refactored. - /// Combines all component registers of \p V into a single scalar with size - /// "max(Offsets) + last size". - unsigned packRegs(const Value &V, MachineIRBuilder &MIRBuilder); - - void unpackRegs(const Value &V, unsigned Src, MachineIRBuilder &MIRBuilder); - /// Returns true if the value should be split into multiple LLTs. /// If \p Offsets is given then the split type's offsets will be stored in it. /// If \p Offsets is not empty it will be cleared first. @@ -242,6 +249,8 @@ private: bool translateInvoke(const User &U, MachineIRBuilder &MIRBuilder); + bool translateCallBr(const User &U, MachineIRBuilder &MIRBuilder); + bool translateLandingPad(const User &U, MachineIRBuilder &MIRBuilder); /// Translate one of LLVM's cast instructions into MachineInstrs, with the @@ -278,7 +287,42 @@ private: /// \pre \p U is a branch instruction. bool translateBr(const User &U, MachineIRBuilder &MIRBuilder); + // Begin switch lowering functions. + bool emitJumpTableHeader(SwitchCG::JumpTable &JT, + SwitchCG::JumpTableHeader &JTH, + MachineBasicBlock *HeaderBB); + void emitJumpTable(SwitchCG::JumpTable &JT, MachineBasicBlock *MBB); + + void emitSwitchCase(SwitchCG::CaseBlock &CB, MachineBasicBlock *SwitchBB, + MachineIRBuilder &MIB); + + bool lowerJumpTableWorkItem(SwitchCG::SwitchWorkListItem W, + MachineBasicBlock *SwitchMBB, + MachineBasicBlock *CurMBB, + MachineBasicBlock *DefaultMBB, + MachineIRBuilder &MIB, + MachineFunction::iterator BBI, + BranchProbability UnhandledProbs, + SwitchCG::CaseClusterIt I, + MachineBasicBlock *Fallthrough, + bool FallthroughUnreachable); + + bool lowerSwitchRangeWorkItem(SwitchCG::CaseClusterIt I, + Value *Cond, + MachineBasicBlock *Fallthrough, + bool FallthroughUnreachable, + BranchProbability UnhandledProbs, + MachineBasicBlock *CurMBB, + MachineIRBuilder &MIB, + MachineBasicBlock *SwitchMBB); + + bool lowerSwitchWorkItem(SwitchCG::SwitchWorkListItem W, Value *Cond, + MachineBasicBlock *SwitchMBB, + MachineBasicBlock *DefaultMBB, + MachineIRBuilder &MIB); + bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder); + // End switch lowering section. bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder); @@ -404,6 +448,7 @@ private: bool translateAtomicCmpXchg(const User &U, MachineIRBuilder &MIRBuilder); bool translateAtomicRMW(const User &U, MachineIRBuilder &MIRBuilder); + bool translateFence(const User &U, MachineIRBuilder &MIRBuilder); // Stubs to keep the compiler happy while we implement the rest of the // translation. @@ -419,9 +464,6 @@ private: bool translateCatchSwitch(const User &U, MachineIRBuilder &MIRBuilder) { return false; } - bool translateFence(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } bool translateAddrSpaceCast(const User &U, MachineIRBuilder &MIRBuilder) { return translateCast(TargetOpcode::G_ADDRSPACE_CAST, U, MIRBuilder); } @@ -466,19 +508,50 @@ private: /// Current optimization remark emitter. Used to report failures. std::unique_ptr<OptimizationRemarkEmitter> ORE; + FunctionLoweringInfo FuncInfo; + + // True when either the Target Machine specifies no optimizations or the + // function has the optnone attribute. + bool EnableOpts = false; + + /// Switch analysis and optimization. + class GISelSwitchLowering : public SwitchCG::SwitchLowering { + public: + GISelSwitchLowering(IRTranslator *irt, FunctionLoweringInfo &funcinfo) + : SwitchLowering(funcinfo), IRT(irt) { + assert(irt && "irt is null!"); + } + + virtual void addSuccessorWithProb( + MachineBasicBlock *Src, MachineBasicBlock *Dst, + BranchProbability Prob = BranchProbability::getUnknown()) override { + IRT->addSuccessorWithProb(Src, Dst, Prob); + } + + virtual ~GISelSwitchLowering() = default; + + private: + IRTranslator *IRT; + }; + + std::unique_ptr<GISelSwitchLowering> SL; + // * Insert all the code needed to materialize the constants // at the proper place. E.g., Entry block or dominator block // of each constant depending on how fancy we want to be. // * Clear the different maps. void finalizeFunction(); + // Handle emitting jump tables for each basic block. + void finalizeBasicBlock(); + /// Get the VRegs that represent \p Val. /// Non-aggregate types have just one corresponding VReg and the list can be /// used as a single "unsigned". Aggregates get flattened. If such VRegs do /// not exist, they are created. - ArrayRef<unsigned> getOrCreateVRegs(const Value &Val); + ArrayRef<Register> getOrCreateVRegs(const Value &Val); - unsigned getOrCreateVReg(const Value &Val) { + Register getOrCreateVReg(const Value &Val) { auto Regs = getOrCreateVRegs(Val); if (Regs.empty()) return 0; @@ -522,6 +595,14 @@ private: return SmallVector<MachineBasicBlock *, 4>(1, &getMBB(*Edge.first)); } + /// Return branch probability calculated by BranchProbabilityInfo for IR + /// blocks. + BranchProbability getEdgeProbability(const MachineBasicBlock *Src, + const MachineBasicBlock *Dst) const; + + void addSuccessorWithProb(MachineBasicBlock *Src, MachineBasicBlock *Dst, + BranchProbability Prob); + public: // Ctor, nothing fancy. IRTranslator(); diff --git a/include/llvm/CodeGen/GlobalISel/InstructionSelect.h b/include/llvm/CodeGen/GlobalISel/InstructionSelect.h index 01521c46ab6a..1af46e0a9e76 100644 --- a/include/llvm/CodeGen/GlobalISel/InstructionSelect.h +++ b/include/llvm/CodeGen/GlobalISel/InstructionSelect.h @@ -1,9 +1,8 @@ //== llvm/CodeGen/GlobalISel/InstructionSelect.h -----------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// \file This file describes the interface of the MachineFunctionPass diff --git a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h index 471def7f45a3..e9b93be76754 100644 --- a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h +++ b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/InstructionSelector.h ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -139,6 +138,16 @@ enum { /// - MMOIdx - MMO index /// - Size - The size in bytes of the memory access GIM_CheckMemorySizeEqualTo, + + /// Check the address space of the memory access for the given machine memory + /// operand. + /// - InsnID - Instruction ID + /// - MMOIdx - MMO index + /// - NumAddrSpace - Number of valid address spaces + /// - AddrSpaceN - An allowed space of the memory access + /// - AddrSpaceN+1 ... + GIM_CheckMemoryAddressSpace, + /// Check the size of the memory access for the given machine memory operand /// against the size of an operand. /// - InsnID - Instruction ID diff --git a/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h b/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h index 2003a79f6b20..e8ee4af0cb0b 100644 --- a/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h +++ b/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -371,6 +370,45 @@ bool InstructionSelector::executeMatchTable( return false; break; } + case GIM_CheckMemoryAddressSpace: { + int64_t InsnID = MatchTable[CurrentIdx++]; + int64_t MMOIdx = MatchTable[CurrentIdx++]; + // This accepts a list of possible address spaces. + const int NumAddrSpace = MatchTable[CurrentIdx++]; + + if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) { + if (handleReject() == RejectAndGiveUp) + return false; + break; + } + + // Need to still jump to the end of the list of address spaces if we find + // a match earlier. + const uint64_t LastIdx = CurrentIdx + NumAddrSpace; + + const MachineMemOperand *MMO + = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx); + const unsigned MMOAddrSpace = MMO->getAddrSpace(); + + bool Success = false; + for (int I = 0; I != NumAddrSpace; ++I) { + unsigned AddrSpace = MatchTable[CurrentIdx++]; + DEBUG_WITH_TYPE( + TgtInstructionSelector::getName(), + dbgs() << "addrspace(" << MMOAddrSpace << ") vs " + << AddrSpace << '\n'); + + if (AddrSpace == MMOAddrSpace) { + Success = true; + break; + } + } + + CurrentIdx = LastIdx; + if (!Success && handleReject() == RejectAndGiveUp) + return false; + break; + } case GIM_CheckMemorySizeEqualTo: { int64_t InsnID = MatchTable[CurrentIdx++]; int64_t MMOIdx = MatchTable[CurrentIdx++]; @@ -438,15 +476,15 @@ bool InstructionSelector::executeMatchTable( unsigned Size = MRI.getType(MO.getReg()).getSizeInBits(); if (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT && - MMO->getSize() * 8 != Size) { + MMO->getSizeInBits() != Size) { if (handleReject() == RejectAndGiveUp) return false; } else if (MatcherOpcode == GIM_CheckMemorySizeLessThanLLT && - MMO->getSize() * 8 >= Size) { + MMO->getSizeInBits() >= Size) { if (handleReject() == RejectAndGiveUp) return false; } else if (MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT && - MMO->getSize() * 8 <= Size) + MMO->getSizeInBits() <= Size) if (handleReject() == RejectAndGiveUp) return false; @@ -479,17 +517,19 @@ bool InstructionSelector::executeMatchTable( << InsnID << "]->getOperand(" << OpIdx << "), SizeInBits=" << SizeInBits << ")\n"); assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); + const LLT Ty = MRI.getType(MO.getReg()); + // iPTR must be looked up in the target. if (SizeInBits == 0) { MachineFunction *MF = State.MIs[InsnID]->getParent()->getParent(); - SizeInBits = MF->getDataLayout().getPointerSizeInBits(0); + const unsigned AddrSpace = Ty.getAddressSpace(); + SizeInBits = MF->getDataLayout().getPointerSizeInBits(AddrSpace); } assert(SizeInBits != 0 && "Pointer size must be known"); - MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); if (MO.isReg()) { - const LLT &Ty = MRI.getType(MO.getReg()); if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits) if (handleReject() == RejectAndGiveUp) return false; diff --git a/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h index 20bec7650179..a22778b8848c 100644 --- a/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ b/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h -----*- C++ -*-// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 file contains some helper functions which try to cleanup artifacts @@ -29,6 +28,18 @@ class LegalizationArtifactCombiner { MachineRegisterInfo &MRI; const LegalizerInfo &LI; + static bool isArtifactCast(unsigned Opc) { + switch (Opc) { + case TargetOpcode::G_TRUNC: + case TargetOpcode::G_SEXT: + case TargetOpcode::G_ZEXT: + case TargetOpcode::G_ANYEXT: + return true; + default: + return false; + } + } + public: LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI, const LegalizerInfo &LI) @@ -40,11 +51,11 @@ public: return false; Builder.setInstr(MI); - unsigned DstReg = MI.getOperand(0).getReg(); - unsigned SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); + Register DstReg = MI.getOperand(0).getReg(); + Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); // aext(trunc x) - > aext/copy/trunc x - unsigned TruncSrc; + Register TruncSrc; if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); Builder.buildAnyExtOrTrunc(DstReg, TruncSrc); @@ -53,7 +64,7 @@ public: } // aext([asz]ext x) -> [asz]ext x - unsigned ExtSrc; + Register ExtSrc; MachineInstr *ExtMI; if (mi_match(SrcReg, MRI, m_all_of(m_MInstr(ExtMI), m_any_of(m_GAnyExt(m_Reg(ExtSrc)), @@ -63,6 +74,20 @@ public: markInstAndDefDead(MI, *ExtMI, DeadInsts); return true; } + + // Try to fold aext(g_constant) when the larger constant type is legal. + // Can't use MIPattern because we don't have a specific constant in mind. + auto *SrcMI = MRI.getVRegDef(SrcReg); + if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) { + const LLT &DstTy = MRI.getType(DstReg); + if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) { + auto &CstVal = SrcMI->getOperand(1); + Builder.buildConstant( + DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits())); + markInstAndDefDead(MI, *SrcMI, DeadInsts); + return true; + } + } return tryFoldImplicitDef(MI, DeadInsts); } @@ -73,25 +98,39 @@ public: return false; Builder.setInstr(MI); - unsigned DstReg = MI.getOperand(0).getReg(); - unsigned SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); + Register DstReg = MI.getOperand(0).getReg(); + Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); // zext(trunc x) - > and (aext/copy/trunc x), mask - unsigned TruncSrc; + Register TruncSrc; if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { LLT DstTy = MRI.getType(DstReg); if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) || - isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}})) + isConstantUnsupported(DstTy)) return false; LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); LLT SrcTy = MRI.getType(SrcReg); - APInt Mask = APInt::getAllOnesValue(SrcTy.getSizeInBits()); + APInt Mask = APInt::getAllOnesValue(SrcTy.getScalarSizeInBits()); auto MIBMask = Builder.buildConstant(DstTy, Mask.getZExtValue()); Builder.buildAnd(DstReg, Builder.buildAnyExtOrTrunc(DstTy, TruncSrc), MIBMask); markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts); return true; } + + // Try to fold zext(g_constant) when the larger constant type is legal. + // Can't use MIPattern because we don't have a specific constant in mind. + auto *SrcMI = MRI.getVRegDef(SrcReg); + if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) { + const LLT &DstTy = MRI.getType(DstReg); + if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) { + auto &CstVal = SrcMI->getOperand(1); + Builder.buildConstant( + DstReg, CstVal.getCImm()->getValue().zext(DstTy.getSizeInBits())); + markInstAndDefDead(MI, *SrcMI, DeadInsts); + return true; + } + } return tryFoldImplicitDef(MI, DeadInsts); } @@ -102,20 +141,22 @@ public: return false; Builder.setInstr(MI); - unsigned DstReg = MI.getOperand(0).getReg(); - unsigned SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); + Register DstReg = MI.getOperand(0).getReg(); + Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); // sext(trunc x) - > ashr (shl (aext/copy/trunc x), c), c - unsigned TruncSrc; + Register TruncSrc; if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { LLT DstTy = MRI.getType(DstReg); - if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy}}) || - isInstUnsupported({TargetOpcode::G_ASHR, {DstTy}}) || - isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}})) + // Guess on the RHS shift amount type, which should be re-legalized if + // applicable. + if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy, DstTy}}) || + isInstUnsupported({TargetOpcode::G_ASHR, {DstTy, DstTy}}) || + isConstantUnsupported(DstTy)) return false; LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); LLT SrcTy = MRI.getType(SrcReg); - unsigned ShAmt = DstTy.getSizeInBits() - SrcTy.getSizeInBits(); + unsigned ShAmt = DstTy.getScalarSizeInBits() - SrcTy.getScalarSizeInBits(); auto MIBShAmt = Builder.buildConstant(DstTy, ShAmt); auto MIBShl = Builder.buildInstr( TargetOpcode::G_SHL, {DstTy}, @@ -138,7 +179,7 @@ public: if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(1).getReg(), MRI)) { Builder.setInstr(MI); - unsigned DstReg = MI.getOperand(0).getReg(); + Register DstReg = MI.getOperand(0).getReg(); LLT DstTy = MRI.getType(DstReg); if (Opcode == TargetOpcode::G_ANYEXT) { @@ -150,7 +191,7 @@ public: } else { // G_[SZ]EXT (G_IMPLICIT_DEF) -> G_CONSTANT 0 because the top // bits will be 0 for G_ZEXT and 0/1 for the G_SEXT. - if (isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}})) + if (isConstantUnsupported(DstTy)) return false; LLVM_DEBUG(dbgs() << ".. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI;); Builder.buildConstant(DstReg, 0); @@ -162,6 +203,16 @@ public: return false; } + static unsigned getMergeOpcode(LLT OpTy, LLT DestTy) { + if (OpTy.isVector() && DestTy.isVector()) + return TargetOpcode::G_CONCAT_VECTORS; + + if (OpTy.isVector() && !DestTy.isVector()) + return TargetOpcode::G_BUILD_VECTOR; + + return TargetOpcode::G_MERGE_VALUES; + } + bool tryCombineMerges(MachineInstr &MI, SmallVectorImpl<MachineInstr *> &DeadInsts) { @@ -169,27 +220,33 @@ public: return false; unsigned NumDefs = MI.getNumOperands() - 1; + MachineInstr *SrcDef = + getDefIgnoringCopies(MI.getOperand(NumDefs).getReg(), MRI); + if (!SrcDef) + return false; - unsigned MergingOpcode; LLT OpTy = MRI.getType(MI.getOperand(NumDefs).getReg()); LLT DestTy = MRI.getType(MI.getOperand(0).getReg()); - if (OpTy.isVector() && DestTy.isVector()) - MergingOpcode = TargetOpcode::G_CONCAT_VECTORS; - else if (OpTy.isVector() && !DestTy.isVector()) - MergingOpcode = TargetOpcode::G_BUILD_VECTOR; - else - MergingOpcode = TargetOpcode::G_MERGE_VALUES; + MachineInstr *MergeI = SrcDef; + unsigned ConvertOp = 0; - MachineInstr *MergeI = - getOpcodeDef(MergingOpcode, MI.getOperand(NumDefs).getReg(), MRI); + // Handle intermediate conversions + unsigned SrcOp = SrcDef->getOpcode(); + if (isArtifactCast(SrcOp)) { + ConvertOp = SrcOp; + MergeI = getDefIgnoringCopies(SrcDef->getOperand(1).getReg(), MRI); + } - if (!MergeI) + // FIXME: Handle scalarizing concat_vectors (scalar result type with vector + // source) + unsigned MergingOpcode = getMergeOpcode(OpTy, DestTy); + if (!MergeI || MergeI->getOpcode() != MergingOpcode) return false; const unsigned NumMergeRegs = MergeI->getNumOperands() - 1; if (NumMergeRegs < NumDefs) { - if (NumDefs % NumMergeRegs != 0) + if (ConvertOp != 0 || NumDefs % NumMergeRegs != 0) return false; Builder.setInstr(MI); @@ -202,7 +259,7 @@ public: const unsigned NewNumDefs = NumDefs / NumMergeRegs; for (unsigned Idx = 0; Idx < NumMergeRegs; ++Idx) { - SmallVector<unsigned, 2> DstRegs; + SmallVector<Register, 2> DstRegs; for (unsigned j = 0, DefIdx = Idx * NewNumDefs; j < NewNumDefs; ++j, ++DefIdx) DstRegs.push_back(MI.getOperand(DefIdx).getReg()); @@ -211,7 +268,7 @@ public: } } else if (NumMergeRegs > NumDefs) { - if (NumMergeRegs % NumDefs != 0) + if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0) return false; Builder.setInstr(MI); @@ -224,7 +281,7 @@ public: const unsigned NumRegs = NumMergeRegs / NumDefs; for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) { - SmallVector<unsigned, 2> Regs; + SmallVector<Register, 2> Regs; for (unsigned j = 0, Idx = NumRegs * DefIdx + 1; j < NumRegs; ++j, ++Idx) Regs.push_back(MergeI->getOperand(Idx).getReg()); @@ -233,10 +290,22 @@ public: } } else { + LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg()); + if (ConvertOp) { + Builder.setInstr(MI); + + for (unsigned Idx = 0; Idx < NumDefs; ++Idx) { + Register MergeSrc = MergeI->getOperand(Idx + 1).getReg(); + Builder.buildInstr(ConvertOp, {MI.getOperand(Idx).getReg()}, + {MergeSrc}); + } + + markInstAndDefDead(MI, *MergeI, DeadInsts); + return true; + } // FIXME: is a COPY appropriate if the types mismatch? We know both // registers are allocatable by now. - if (MRI.getType(MI.getOperand(0).getReg()) != - MRI.getType(MergeI->getOperand(1).getReg())) + if (DestTy != MergeSrcTy) return false; for (unsigned Idx = 0; Idx < NumDefs; ++Idx) @@ -248,12 +317,77 @@ public: return true; } + static bool isMergeLikeOpcode(unsigned Opc) { + switch (Opc) { + case TargetOpcode::G_MERGE_VALUES: + case TargetOpcode::G_BUILD_VECTOR: + case TargetOpcode::G_CONCAT_VECTORS: + return true; + default: + return false; + } + } + + bool tryCombineExtract(MachineInstr &MI, + SmallVectorImpl<MachineInstr *> &DeadInsts) { + assert(MI.getOpcode() == TargetOpcode::G_EXTRACT); + + // Try to use the source registers from a G_MERGE_VALUES + // + // %2 = G_MERGE_VALUES %0, %1 + // %3 = G_EXTRACT %2, N + // => + // + // for N < %2.getSizeInBits() / 2 + // %3 = G_EXTRACT %0, N + // + // for N >= %2.getSizeInBits() / 2 + // %3 = G_EXTRACT %1, (N - %0.getSizeInBits() + + unsigned Src = lookThroughCopyInstrs(MI.getOperand(1).getReg()); + MachineInstr *MergeI = MRI.getVRegDef(Src); + if (!MergeI || !isMergeLikeOpcode(MergeI->getOpcode())) + return false; + + LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); + LLT SrcTy = MRI.getType(Src); + + // TODO: Do we need to check if the resulting extract is supported? + unsigned ExtractDstSize = DstTy.getSizeInBits(); + unsigned Offset = MI.getOperand(2).getImm(); + unsigned NumMergeSrcs = MergeI->getNumOperands() - 1; + unsigned MergeSrcSize = SrcTy.getSizeInBits() / NumMergeSrcs; + unsigned MergeSrcIdx = Offset / MergeSrcSize; + + // Compute the offset of the last bit the extract needs. + unsigned EndMergeSrcIdx = (Offset + ExtractDstSize - 1) / MergeSrcSize; + + // Can't handle the case where the extract spans multiple inputs. + if (MergeSrcIdx != EndMergeSrcIdx) + return false; + + // TODO: We could modify MI in place in most cases. + Builder.setInstr(MI); + Builder.buildExtract( + MI.getOperand(0).getReg(), + MergeI->getOperand(MergeSrcIdx + 1).getReg(), + Offset - MergeSrcIdx * MergeSrcSize); + markInstAndDefDead(MI, *MergeI, DeadInsts); + return true; + } + /// Try to combine away MI. /// Returns true if it combined away the MI. /// Adds instructions that are dead as a result of the combine /// into DeadInsts, which can include MI. bool tryCombineInstruction(MachineInstr &MI, - SmallVectorImpl<MachineInstr *> &DeadInsts) { + SmallVectorImpl<MachineInstr *> &DeadInsts, + GISelObserverWrapper &WrapperObserver) { + // This might be a recursive call, and we might have DeadInsts already + // populated. To avoid bad things happening later with multiple vreg defs + // etc, process the dead instructions now if any. + if (!DeadInsts.empty()) + deleteMarkedDeadInsts(DeadInsts, WrapperObserver); switch (MI.getOpcode()) { default: return false; @@ -265,16 +399,35 @@ public: return tryCombineSExt(MI, DeadInsts); case TargetOpcode::G_UNMERGE_VALUES: return tryCombineMerges(MI, DeadInsts); + case TargetOpcode::G_EXTRACT: + return tryCombineExtract(MI, DeadInsts); case TargetOpcode::G_TRUNC: { bool Changed = false; for (auto &Use : MRI.use_instructions(MI.getOperand(0).getReg())) - Changed |= tryCombineInstruction(Use, DeadInsts); + Changed |= tryCombineInstruction(Use, DeadInsts, WrapperObserver); return Changed; } } } private: + + static unsigned getArtifactSrcReg(const MachineInstr &MI) { + switch (MI.getOpcode()) { + case TargetOpcode::COPY: + case TargetOpcode::G_TRUNC: + case TargetOpcode::G_ZEXT: + case TargetOpcode::G_ANYEXT: + case TargetOpcode::G_SEXT: + case TargetOpcode::G_UNMERGE_VALUES: + return MI.getOperand(MI.getNumOperands() - 1).getReg(); + case TargetOpcode::G_EXTRACT: + return MI.getOperand(1).getReg(); + default: + llvm_unreachable("Not a legalization artifact happen"); + } + } + /// Mark MI as dead. If a def of one of MI's operands, DefMI, would also be /// dead due to MI being killed, then mark DefMI as dead too. /// Some of the combines (extends(trunc)), try to walk through redundant @@ -295,13 +448,15 @@ private: // and as a result, %3, %2, %1 are dead. MachineInstr *PrevMI = &MI; while (PrevMI != &DefMI) { - unsigned PrevRegSrc = - PrevMI->getOperand(PrevMI->getNumOperands() - 1).getReg(); + unsigned PrevRegSrc = getArtifactSrcReg(*PrevMI); + MachineInstr *TmpDef = MRI.getVRegDef(PrevRegSrc); if (MRI.hasOneUse(PrevRegSrc)) { if (TmpDef != &DefMI) { - assert(TmpDef->getOpcode() == TargetOpcode::COPY && - "Expecting copy here"); + assert((TmpDef->getOpcode() == TargetOpcode::COPY || + isArtifactCast(TmpDef->getOpcode())) && + "Expecting copy or artifact cast here"); + DeadInsts.push_back(TmpDef); } } else @@ -312,6 +467,22 @@ private: DeadInsts.push_back(&DefMI); } + /// Erase the dead instructions in the list and call the observer hooks. + /// Normally the Legalizer will deal with erasing instructions that have been + /// marked dead. However, for the trunc(ext(x)) cases we can end up trying to + /// process instructions which have been marked dead, but otherwise break the + /// MIR by introducing multiple vreg defs. For those cases, allow the combines + /// to explicitly delete the instructions before we run into trouble. + void deleteMarkedDeadInsts(SmallVectorImpl<MachineInstr *> &DeadInsts, + GISelObserverWrapper &WrapperObserver) { + for (auto *DeadMI : DeadInsts) { + LLVM_DEBUG(dbgs() << *DeadMI << "Is dead, eagerly deleting\n"); + WrapperObserver.erasingInstr(*DeadMI); + DeadMI->eraseFromParentAndMarkDBGValuesForRemoval(); + } + DeadInsts.clear(); + } + /// Checks if the target legalizer info has specified anything about the /// instruction, or if unsupported. bool isInstUnsupported(const LegalityQuery &Query) const { @@ -320,10 +491,23 @@ private: return Step.Action == Unsupported || Step.Action == NotFound; } + bool isInstLegal(const LegalityQuery &Query) const { + return LI.getAction(Query).Action == LegalizeActions::Legal; + } + + bool isConstantUnsupported(LLT Ty) const { + if (!Ty.isVector()) + return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}}); + + LLT EltTy = Ty.getElementType(); + return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) || + isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}}); + } + /// Looks through copy instructions and returns the actual /// source register. - unsigned lookThroughCopyInstrs(unsigned Reg) { - unsigned TmpReg; + unsigned lookThroughCopyInstrs(Register Reg) { + Register TmpReg; while (mi_match(Reg, MRI, m_Copy(m_Reg(TmpReg)))) { if (MRI.getType(TmpReg).isValid()) Reg = TmpReg; diff --git a/include/llvm/CodeGen/GlobalISel/Legalizer.h b/include/llvm/CodeGen/GlobalISel/Legalizer.h index 8284ab6dac65..13cf3f7e694d 100644 --- a/include/llvm/CodeGen/GlobalISel/Legalizer.h +++ b/include/llvm/CodeGen/GlobalISel/Legalizer.h @@ -1,9 +1,8 @@ -//== llvm/CodeGen/GlobalISel/LegalizePass.h ------------- -*- C++ -*-==// +//== llvm/CodeGen/GlobalISel/Legalizer.h ---------------- -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -55,6 +54,11 @@ public: MachineFunctionProperties::Property::Legalized); } + MachineFunctionProperties getClearedProperties() const override { + return MachineFunctionProperties() + .set(MachineFunctionProperties::Property::NoPHIs); + } + bool combineExtracts(MachineInstr &MI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII); diff --git a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index 9b4ecf9284e3..a0f21e8b19d7 100644 --- a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -1,9 +1,8 @@ //== llvm/CodeGen/GlobalISel/LegalizerHelper.h ---------------- -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -87,7 +86,7 @@ public: /// Legalize a vector instruction by increasing the number of vector elements /// involved and ignoring the added elements later. LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, - LLT WideTy); + LLT MoreTy); /// Expose MIRBuilder so clients can set their own RecordInsertInstruction /// functions @@ -105,19 +104,126 @@ private: unsigned ExtOpcode); /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a + /// Use by truncating the operand's type to \p NarrowTy using G_TRUNC, and + /// replacing the vreg of the operand in place. + void narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx); + + /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a /// Def by extending the operand's type to \p WideTy and truncating it back /// with the \p TruncOpcode, and replacing the vreg of the operand in place. void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx = 0, unsigned TruncOpcode = TargetOpcode::G_TRUNC); + // Legalize a single operand \p OpIdx of the machine instruction \p MI as a + // Def by truncating the operand's type to \p NarrowTy, replacing in place and + // extending back with \p ExtOpcode. + void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx, + unsigned ExtOpcode); + /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a + /// Def by performing it with additional vector elements and extracting the + /// result elements, and replacing the vreg of the operand in place. + void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx); + + /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a + /// Use by producing a vector with undefined high elements, extracting the + /// original vector type, and replacing the vreg of the operand in place. + void moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, unsigned OpIdx); + + LegalizeResult + widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); + LegalizeResult + widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); + LegalizeResult + widenScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); + LegalizeResult + widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); + /// Helper function to split a wide generic register into bitwise blocks with /// the given Type (which implies the number of blocks needed). The generic /// registers created are appended to Ops, starting at bit 0 of Reg. - void extractParts(unsigned Reg, LLT Ty, int NumParts, - SmallVectorImpl<unsigned> &VRegs); + void extractParts(Register Reg, LLT Ty, int NumParts, + SmallVectorImpl<Register> &VRegs); + + /// Version which handles irregular splits. + bool extractParts(Register Reg, LLT RegTy, LLT MainTy, + LLT &LeftoverTy, + SmallVectorImpl<Register> &VRegs, + SmallVectorImpl<Register> &LeftoverVRegs); + + /// Helper function to build a wide generic register \p DstReg of type \p + /// RegTy from smaller parts. This will produce a G_MERGE_VALUES, + /// G_BUILD_VECTOR, G_CONCAT_VECTORS, or sequence of G_INSERT as appropriate + /// for the types. + /// + /// \p PartRegs must be registers of type \p PartTy. + /// + /// If \p ResultTy does not evenly break into \p PartTy sized pieces, the + /// remainder must be specified with \p LeftoverRegs of type \p LeftoverTy. + void insertParts(Register DstReg, LLT ResultTy, + LLT PartTy, ArrayRef<Register> PartRegs, + LLT LeftoverTy = LLT(), ArrayRef<Register> LeftoverRegs = {}); + + /// Perform generic multiplication of values held in multiple registers. + /// Generated instructions use only types NarrowTy and i1. + /// Destination can be same or two times size of the source. + void multiplyRegisters(SmallVectorImpl<Register> &DstRegs, + ArrayRef<Register> Src1Regs, + ArrayRef<Register> Src2Regs, LLT NarrowTy); + +public: + LegalizeResult fewerElementsVectorImplicitDef(MachineInstr &MI, + unsigned TypeIdx, LLT NarrowTy); + + /// Legalize a simple vector instruction where all operands are the same type + /// by splitting into multiple components. + LegalizeResult fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx, + LLT NarrowTy); + + /// Legalize a instruction with a vector type where each operand may have a + /// different element type. All type indexes must have the same number of + /// elements. + LegalizeResult fewerElementsVectorMultiEltType(MachineInstr &MI, + unsigned TypeIdx, LLT NarrowTy); + + LegalizeResult fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx, + LLT NarrowTy); + + LegalizeResult + fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); + + LegalizeResult + fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); + + LegalizeResult fewerElementsVectorPhi(MachineInstr &MI, + unsigned TypeIdx, LLT NarrowTy); + + LegalizeResult moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, + LLT MoreTy); + + LegalizeResult + reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); + + LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, + LLT HalfTy, LLT ShiftAmtTy); + + LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty); + LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + + LegalizeResult narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI); + LegalizeResult lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerFCopySign(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI); + +private: MachineRegisterInfo &MRI; const LegalizerInfo &LI; /// To keep track of changes made by the LegalizerHelper. diff --git a/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h index 13776dd3e87d..513c98f2d23f 100644 --- a/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ b/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/LegalizerInfo.h ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -93,6 +92,7 @@ enum LegalizeAction : std::uint8_t { UseLegacyRules, }; } // end namespace LegalizeActions +raw_ostream &operator<<(raw_ostream &OS, LegalizeActions::LegalizeAction Action); using LegalizeActions::LegalizeAction; @@ -123,6 +123,7 @@ struct LegalityQuery { struct MemDesc { uint64_t SizeInBits; + uint64_t AlignInBits; AtomicOrdering Ordering; }; @@ -165,13 +166,23 @@ using LegalizeMutation = std::function<std::pair<unsigned, LLT>(const LegalityQuery &)>; namespace LegalityPredicates { -struct TypePairAndMemSize { +struct TypePairAndMemDesc { LLT Type0; LLT Type1; uint64_t MemSize; + uint64_t Align; + + bool operator==(const TypePairAndMemDesc &Other) const { + return Type0 == Other.Type0 && Type1 == Other.Type1 && + Align == Other.Align && + MemSize == Other.MemSize; + } - bool operator==(const TypePairAndMemSize &Other) const { + /// \returns true if this memory access is legal with for the acecss described + /// by \p Other (The alignment is sufficient for the size and result type). + bool isCompatible(const TypePairAndMemDesc &Other) const { return Type0 == Other.Type0 && Type1 == Other.Type1 && + Align >= Other.Align && MemSize == Other.MemSize; } }; @@ -200,20 +211,45 @@ typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1, std::initializer_list<std::pair<LLT, LLT>> TypesInit); /// True iff the given types for the given pair of type indexes is one of the /// specified type pairs. -LegalityPredicate typePairAndMemSizeInSet( +LegalityPredicate typePairAndMemDescInSet( unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx, - std::initializer_list<TypePairAndMemSize> TypesAndMemSizeInit); + std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit); /// True iff the specified type index is a scalar. LegalityPredicate isScalar(unsigned TypeIdx); +/// True iff the specified type index is a vector. +LegalityPredicate isVector(unsigned TypeIdx); +/// True iff the specified type index is a pointer (with any address space). +LegalityPredicate isPointer(unsigned TypeIdx); +/// True iff the specified type index is a pointer with the specified address +/// space. +LegalityPredicate isPointer(unsigned TypeIdx, unsigned AddrSpace); + /// True iff the specified type index is a scalar that's narrower than the given /// size. LegalityPredicate narrowerThan(unsigned TypeIdx, unsigned Size); + /// True iff the specified type index is a scalar that's wider than the given /// size. LegalityPredicate widerThan(unsigned TypeIdx, unsigned Size); + +/// True iff the specified type index is a scalar or vector with an element type +/// that's narrower than the given size. +LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size); + +/// True iff the specified type index is a scalar or a vector with an element +/// type that's wider than the given size. +LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size); + /// True iff the specified type index is a scalar whose size is not a power of /// 2. LegalityPredicate sizeNotPow2(unsigned TypeIdx); + +/// True iff the specified type index is a scalar or vector whose element size +/// is not a power of 2. +LegalityPredicate scalarOrEltSizeNotPow2(unsigned TypeIdx); + +/// True iff the specified type indices are both the same bit size. +LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1); /// True iff the specified MMO index has a size that is not a power of 2 LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx); /// True iff the specified type index is a vector whose element count is not a @@ -228,13 +264,25 @@ LegalityPredicate atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx, namespace LegalizeMutations { /// Select this specific type for the given type index. LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty); + /// Keep the same type as the given type index. LegalizeMutation changeTo(unsigned TypeIdx, unsigned FromTypeIdx); -/// Widen the type for the given type index to the next power of 2. -LegalizeMutation widenScalarToNextPow2(unsigned TypeIdx, unsigned Min = 0); + +/// Keep the same scalar or element type as the given type index. +LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx); + +/// Keep the same scalar or element type as the given type. +LegalizeMutation changeElementTo(unsigned TypeIdx, LLT Ty); + +/// Widen the scalar type or vector element type for the given type index to the +/// next power of 2. +LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min = 0); + /// Add more elements to the type for the given type index to the next power of /// 2. LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min = 0); +/// Break up the vector type for the given type index into the element type. +LegalizeMutation scalarize(unsigned TypeIdx); } // end namespace LegalizeMutations /// A single rule in a legalizer info ruleset. @@ -419,13 +467,13 @@ public: return actionFor(LegalizeAction::Legal, Types); } /// The instruction is legal when type indexes 0 and 1 along with the memory - /// size is any type and size tuple in the given list. - LegalizeRuleSet &legalForTypesWithMemSize( - std::initializer_list<LegalityPredicates::TypePairAndMemSize> - TypesAndMemSize) { + /// size and minimum alignment is any type and size tuple in the given list. + LegalizeRuleSet &legalForTypesWithMemDesc( + std::initializer_list<LegalityPredicates::TypePairAndMemDesc> + TypesAndMemDesc) { return actionIf(LegalizeAction::Legal, - LegalityPredicates::typePairAndMemSizeInSet( - typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemSize)); + LegalityPredicates::typePairAndMemDescInSet( + typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemDesc)); } /// The instruction is legal when type indexes 0 and 1 are both in the given /// list. That is, the type pair is in the cartesian product of the list. @@ -438,6 +486,20 @@ public: std::initializer_list<LLT> Types1) { return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1); } + /// The instruction is legal when type indexes 0, 1, and 2 are both their + /// respective lists. + LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0, + std::initializer_list<LLT> Types1, + std::initializer_list<LLT> Types2) { + return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1, + Types2); + } + + LegalizeRuleSet &alwaysLegal() { + using namespace LegalizeMutations; + markAllTypeIdxsAsCovered(); + return actionIf(LegalizeAction::Legal, always); + } /// The instruction is lowered. LegalizeRuleSet &lower() { @@ -588,6 +650,13 @@ public: LegalizeRuleSet &customFor(std::initializer_list<LLT> Types) { return actionFor(LegalizeAction::Custom, Types); } + + /// The instruction is custom when type indexes 0 and 1 is any type pair in the + /// given list. + LegalizeRuleSet &customFor(std::initializer_list<std::pair<LLT, LLT>> Types) { + return actionFor(LegalizeAction::Custom, Types); + } + LegalizeRuleSet &customForCartesianProduct(std::initializer_list<LLT> Types) { return actionForCartesianProduct(LegalizeAction::Custom, Types); } @@ -597,13 +666,29 @@ public: return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1); } + /// Unconditionally custom lower. + LegalizeRuleSet &custom() { + return customIf(always); + } + /// Widen the scalar to the next power of two that is at least MinSize. /// No effect if the type is not a scalar or is a power of two. LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize = 0) { using namespace LegalityPredicates; - return actionIf(LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)), - LegalizeMutations::widenScalarToNextPow2(TypeIdx, MinSize)); + return actionIf( + LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)), + LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize)); + } + + /// Widen the scalar or vector element type to the next power of two that is + /// at least MinSize. No effect if the scalar size is a power of two. + LegalizeRuleSet &widenScalarOrEltToNextPow2(unsigned TypeIdx, + unsigned MinSize = 0) { + using namespace LegalityPredicates; + return actionIf( + LegalizeAction::WidenScalar, scalarOrEltSizeNotPow2(typeIdx(TypeIdx)), + LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize)); } LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) { @@ -612,6 +697,32 @@ public: Mutation); } + LegalizeRuleSet &scalarize(unsigned TypeIdx) { + using namespace LegalityPredicates; + return actionIf(LegalizeAction::FewerElements, isVector(typeIdx(TypeIdx)), + LegalizeMutations::scalarize(TypeIdx)); + } + + /// Ensure the scalar or element is at least as wide as Ty. + LegalizeRuleSet &minScalarOrElt(unsigned TypeIdx, const LLT &Ty) { + using namespace LegalityPredicates; + using namespace LegalizeMutations; + return actionIf(LegalizeAction::WidenScalar, + scalarOrEltNarrowerThan(TypeIdx, Ty.getScalarSizeInBits()), + changeElementTo(typeIdx(TypeIdx), Ty)); + } + + /// Ensure the scalar or element is at least as wide as Ty. + LegalizeRuleSet &minScalarOrEltIf(LegalityPredicate Predicate, + unsigned TypeIdx, const LLT &Ty) { + using namespace LegalityPredicates; + using namespace LegalizeMutations; + return actionIf(LegalizeAction::WidenScalar, + all(Predicate, scalarOrEltNarrowerThan( + TypeIdx, Ty.getScalarSizeInBits())), + changeElementTo(typeIdx(TypeIdx), Ty)); + } + /// Ensure the scalar is at least as wide as Ty. LegalizeRuleSet &minScalar(unsigned TypeIdx, const LLT &Ty) { using namespace LegalityPredicates; @@ -622,6 +733,15 @@ public: } /// Ensure the scalar is at most as wide as Ty. + LegalizeRuleSet &maxScalarOrElt(unsigned TypeIdx, const LLT &Ty) { + using namespace LegalityPredicates; + using namespace LegalizeMutations; + return actionIf(LegalizeAction::NarrowScalar, + scalarOrEltWiderThan(TypeIdx, Ty.getScalarSizeInBits()), + changeElementTo(typeIdx(TypeIdx), Ty)); + } + + /// Ensure the scalar is at most as wide as Ty. LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT &Ty) { using namespace LegalityPredicates; using namespace LegalizeMutations; @@ -637,12 +757,12 @@ public: const LLT &Ty) { using namespace LegalityPredicates; using namespace LegalizeMutations; - return actionIf(LegalizeAction::NarrowScalar, - [=](const LegalityQuery &Query) { - return widerThan(TypeIdx, Ty.getSizeInBits()) && - Predicate(Query); - }, - changeTo(typeIdx(TypeIdx), Ty)); + return actionIf( + LegalizeAction::NarrowScalar, + [=](const LegalityQuery &Query) { + return widerThan(TypeIdx, Ty.getSizeInBits()) && Predicate(Query); + }, + changeElementTo(typeIdx(TypeIdx), Ty)); } /// Limit the range of scalar sizes to MinTy and MaxTy. @@ -652,6 +772,12 @@ public: return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy); } + /// Limit the range of scalar sizes to MinTy and MaxTy. + LegalizeRuleSet &clampScalarOrElt(unsigned TypeIdx, const LLT &MinTy, + const LLT &MaxTy) { + return minScalarOrElt(TypeIdx, MinTy).maxScalarOrElt(TypeIdx, MaxTy); + } + /// Widen the scalar to match the size of another. LegalizeRuleSet &minScalarSameAs(unsigned TypeIdx, unsigned LargeTypeIdx) { typeIdx(TypeIdx); @@ -661,8 +787,25 @@ public: Query.Types[TypeIdx].getSizeInBits(); }, [=](const LegalityQuery &Query) { + LLT T = Query.Types[LargeTypeIdx]; return std::make_pair(TypeIdx, - Query.Types[LargeTypeIdx].getElementType()); + T.isVector() ? T.getElementType() : T); + }); + } + + /// Conditionally widen the scalar or elt to match the size of another. + LegalizeRuleSet &minScalarEltSameAsIf(LegalityPredicate Predicate, + unsigned TypeIdx, unsigned LargeTypeIdx) { + typeIdx(TypeIdx); + return widenScalarIf( + [=](const LegalityQuery &Query) { + return Query.Types[LargeTypeIdx].getScalarSizeInBits() > + Query.Types[TypeIdx].getScalarSizeInBits() && + Predicate(Query); + }, + [=](const LegalityQuery &Query) { + LLT T = Query.Types[LargeTypeIdx]; + return std::make_pair(TypeIdx, T); }); } @@ -691,7 +834,7 @@ public: [=](const LegalityQuery &Query) { LLT VecTy = Query.Types[TypeIdx]; return std::make_pair( - TypeIdx, LLT::vector(MinElements, VecTy.getScalarSizeInBits())); + TypeIdx, LLT::vector(MinElements, VecTy.getElementType())); }); } /// Limit the number of elements in EltTy vectors to at most MaxElements. @@ -708,10 +851,8 @@ public: }, [=](const LegalityQuery &Query) { LLT VecTy = Query.Types[TypeIdx]; - if (MaxElements == 1) - return std::make_pair(TypeIdx, VecTy.getElementType()); - return std::make_pair( - TypeIdx, LLT::vector(MaxElements, VecTy.getScalarSizeInBits())); + LLT NewTy = LLT::scalarOrVector(MaxElements, VecTy.getElementType()); + return std::make_pair(TypeIdx, NewTy); }); } /// Limit the number of elements for the given vectors to at least MinTy's @@ -962,12 +1103,22 @@ public: LegalizeActionStep getAction(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; + bool isLegal(const LegalityQuery &Query) const { + return getAction(Query).Action == LegalizeAction::Legal; + } bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; + bool isLegalOrCustom(const MachineInstr &MI, + const MachineRegisterInfo &MRI) const; virtual bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &MIRBuilder, GISelChangeObserver &Observer) const; + /// Return true if MI is either legal or has been legalized and false + /// if not legal. + virtual bool legalizeIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const; + private: /// Determine what action should be taken to legalize the given generic /// instruction opcode, type-index and type. Requires computeTables to have diff --git a/include/llvm/CodeGen/GlobalISel/Localizer.h b/include/llvm/CodeGen/GlobalISel/Localizer.h index 1e2d4763e5e1..06de5800b8b7 100644 --- a/include/llvm/CodeGen/GlobalISel/Localizer.h +++ b/include/llvm/CodeGen/GlobalISel/Localizer.h @@ -1,9 +1,8 @@ //== llvm/CodeGen/GlobalISel/Localizer.h - Localizer -------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -22,12 +21,14 @@ #ifndef LLVM_CODEGEN_GLOBALISEL_LOCALIZER_H #define LLVM_CODEGEN_GLOBALISEL_LOCALIZER_H +#include "llvm/ADT/SetVector.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/MachineFunctionPass.h" namespace llvm { // Forward declarations. class MachineRegisterInfo; +class TargetTransformInfo; /// This pass implements the localization mechanism described at the /// top of this file. One specificity of the implementation is that @@ -44,9 +45,11 @@ private: /// MRI contains all the register class/bank information that this /// pass uses and updates. MachineRegisterInfo *MRI; + /// TTI used for getting remat costs for instructions. + TargetTransformInfo *TTI; /// Check whether or not \p MI needs to be moved close to its uses. - static bool shouldLocalize(const MachineInstr &MI); + bool shouldLocalize(const MachineInstr &MI); /// Check if \p MOUse is used in the same basic block as \p Def. /// If the use is in the same block, we say it is local. @@ -58,6 +61,15 @@ private: /// Initialize the field members using \p MF. void init(MachineFunction &MF); + typedef SmallSetVector<MachineInstr *, 32> LocalizedSetVecT; + + /// Do inter-block localization from the entry block. + bool localizeInterBlock(MachineFunction &MF, + LocalizedSetVecT &LocalizedInstrs); + + /// Do intra-block localization of already localized instructions. + bool localizeIntraBlock(LocalizedSetVecT &LocalizedInstrs); + public: Localizer(); diff --git a/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h b/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h index f77f9a8df7ee..13eddd9539fa 100644 --- a/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h +++ b/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h @@ -1,9 +1,8 @@ -//== ----- llvm/CodeGen/GlobalISel/MIPatternMatch.h --------------------- == // +//==------ llvm/CodeGen/GlobalISel/MIPatternMatch.h -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -31,8 +30,7 @@ template <typename SubPatternT> struct OneUse_match { SubPatternT SubPat; OneUse_match(const SubPatternT &SP) : SubPat(SP) {} - template <typename OpTy> - bool match(const MachineRegisterInfo &MRI, unsigned Reg) { + bool match(MachineRegisterInfo &MRI, unsigned Reg) { return MRI.hasOneUse(Reg) && SubPat.match(MRI, Reg); } }; @@ -162,7 +160,7 @@ template <typename Class> struct bind_ty { } }; -inline bind_ty<unsigned> m_Reg(unsigned &R) { return R; } +inline bind_ty<Register> m_Reg(Register &R) { return R; } inline bind_ty<MachineInstr *> m_MInstr(MachineInstr *&MI) { return MI; } inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; } diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 37de8f030410..10d712176b1b 100644 --- a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/GlobalISel/MachineIRBuilder.h - MIBuilder --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// \file @@ -60,13 +59,15 @@ struct MachineIRBuilderState { class DstOp { union { LLT LLTTy; - unsigned Reg; + Register Reg; const TargetRegisterClass *RC; }; public: enum class DstType { Ty_LLT, Ty_Reg, Ty_RC }; DstOp(unsigned R) : Reg(R), Ty(DstType::Ty_Reg) {} + DstOp(Register R) : Reg(R), Ty(DstType::Ty_Reg) {} + DstOp(const MachineOperand &Op) : Reg(Op.getReg()), Ty(DstType::Ty_Reg) {} DstOp(const LLT &T) : LLTTy(T), Ty(DstType::Ty_LLT) {} DstOp(const TargetRegisterClass *TRC) : RC(TRC), Ty(DstType::Ty_RC) {} @@ -96,7 +97,7 @@ public: llvm_unreachable("Unrecognised DstOp::DstType enum"); } - unsigned getReg() const { + Register getReg() const { assert(Ty == DstType::Ty_Reg && "Not a register"); return Reg; } @@ -119,13 +120,14 @@ private: class SrcOp { union { MachineInstrBuilder SrcMIB; - unsigned Reg; + Register Reg; CmpInst::Predicate Pred; }; public: enum class SrcType { Ty_Reg, Ty_MIB, Ty_Predicate }; - SrcOp(unsigned R) : Reg(R), Ty(SrcType::Ty_Reg) {} + SrcOp(Register R) : Reg(R), Ty(SrcType::Ty_Reg) {} + SrcOp(const MachineOperand &Op) : Reg(Op.getReg()), Ty(SrcType::Ty_Reg) {} SrcOp(const MachineInstrBuilder &MIB) : SrcMIB(MIB), Ty(SrcType::Ty_MIB) {} SrcOp(const CmpInst::Predicate P) : Pred(P), Ty(SrcType::Ty_Predicate) {} @@ -155,7 +157,7 @@ public: llvm_unreachable("Unrecognised SrcOp::SrcType enum"); } - unsigned getReg() const { + Register getReg() const { switch (Ty) { case SrcType::Ty_Predicate: llvm_unreachable("Not a register operand"); @@ -202,6 +204,7 @@ protected: void validateTruncExt(const LLT &Dst, const LLT &Src, bool IsExtend); void validateBinaryOp(const LLT &Res, const LLT &Op0, const LLT &Op1); + void validateShiftOp(const LLT &Res, const LLT &Op0, const LLT &Op1); void validateSelectOp(const LLT &ResTy, const LLT &TstTy, const LLT &Op0Ty, const LLT &Op1Ty); @@ -230,6 +233,15 @@ public: return *State.MF; } + const MachineFunction &getMF() const { + assert(State.MF && "MachineFunction is not set"); + return *State.MF; + } + + const DataLayout &getDataLayout() const { + return getMF().getFunction().getParent()->getDataLayout(); + } + /// Getter for DebugLoc const DebugLoc &getDL() { return State.DL; } @@ -310,13 +322,13 @@ public: /// Build and insert a DBG_VALUE instruction expressing the fact that the /// associated \p Variable lives in \p Reg (suitably modified by \p Expr). - MachineInstrBuilder buildDirectDbgValue(unsigned Reg, const MDNode *Variable, + MachineInstrBuilder buildDirectDbgValue(Register Reg, const MDNode *Variable, const MDNode *Expr); /// Build and insert a DBG_VALUE instruction expressing the fact that the /// associated \p Variable lives in memory at \p Reg (suitably modified by \p /// Expr). - MachineInstrBuilder buildIndirectDbgValue(unsigned Reg, + MachineInstrBuilder buildIndirectDbgValue(Register Reg, const MDNode *Variable, const MDNode *Expr); @@ -345,7 +357,7 @@ public: /// \pre \p Res must be a generic virtual register with pointer type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildFrameIndex(unsigned Res, int Idx); + MachineInstrBuilder buildFrameIndex(const DstOp &Res, int Idx); /// Build and insert \p Res = G_GLOBAL_VALUE \p GV /// @@ -357,8 +369,7 @@ public: /// in the same address space as \p GV. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildGlobalValue(unsigned Res, const GlobalValue *GV); - + MachineInstrBuilder buildGlobalValue(const DstOp &Res, const GlobalValue *GV); /// Build and insert \p Res = G_GEP \p Op0, \p Op1 /// @@ -371,8 +382,8 @@ public: /// \pre \p Op1 must be a generic virtual register with scalar type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildGEP(unsigned Res, unsigned Op0, - unsigned Op1); + MachineInstrBuilder buildGEP(const DstOp &Res, const SrcOp &Op0, + const SrcOp &Op1); /// Materialize and insert \p Res = G_GEP \p Op0, (G_CONSTANT \p Value) /// @@ -390,7 +401,7 @@ public: /// type as \p Op0 or \p Op0 itself. /// /// \return a MachineInstrBuilder for the newly created instruction. - Optional<MachineInstrBuilder> materializeGEP(unsigned &Res, unsigned Op0, + Optional<MachineInstrBuilder> materializeGEP(Register &Res, Register Op0, const LLT &ValueTy, uint64_t Value); @@ -407,9 +418,24 @@ public: /// be cleared in \p Op0. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildPtrMask(unsigned Res, unsigned Op0, + MachineInstrBuilder buildPtrMask(const DstOp &Res, const SrcOp &Op0, uint32_t NumBits); + /// Build and insert \p Res, \p CarryOut = G_UADDO \p Op0, \p Op1 + /// + /// G_UADDO sets \p Res to \p Op0 + \p Op1 (truncated to the bit width) and + /// sets \p CarryOut to 1 if the result overflowed in unsigned arithmetic. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers with the + /// same scalar type. + ////\pre \p CarryOut must be generic virtual register with scalar type + ///(typically s1) + /// + /// \return The newly created instruction. + MachineInstrBuilder buildUAddo(const DstOp &Res, const DstOp &CarryOut, + const SrcOp &Op0, const SrcOp &Op1); + /// Build and insert \p Res, \p CarryOut = G_UADDE \p Op0, /// \p Op1, \p CarryIn /// @@ -458,6 +484,25 @@ public: /// \return The newly created instruction. MachineInstrBuilder buildSExt(const DstOp &Res, const SrcOp &Op); + /// Build and insert a G_PTRTOINT instruction. + MachineInstrBuilder buildPtrToInt(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_PTRTOINT, {Dst}, {Src}); + } + + /// Build and insert \p Dst = G_BITCAST \p Src + MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_BITCAST, {Dst}, {Src}); + } + + /// \return The opcode of the extension the target wants to use for boolean + /// values. + unsigned getBoolExtOp(bool IsVec, bool IsFP) const; + + // Build and insert \p Res = G_ANYEXT \p Op, \p Res = G_SEXT \p Op, or \p Res + // = G_ZEXT \p Op depending on how the target wants to extend boolean values. + MachineInstrBuilder buildBoolExt(const DstOp &Res, const SrcOp &Op, + bool IsFP); + /// Build and insert \p Res = G_ZEXT \p Op /// /// G_ZEXT produces a register of the specified width, with bits 0 to @@ -538,7 +583,7 @@ public: /// depend on bit 0 (for now). /// /// \return The newly created instruction. - MachineInstrBuilder buildBrCond(unsigned Tst, MachineBasicBlock &Dest); + MachineInstrBuilder buildBrCond(Register Tst, MachineBasicBlock &Dest); /// Build and insert G_BRINDIRECT \p Tgt /// @@ -548,7 +593,21 @@ public: /// \pre \p Tgt must be a generic virtual register with pointer type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildBrIndirect(unsigned Tgt); + MachineInstrBuilder buildBrIndirect(Register Tgt); + + /// Build and insert G_BRJT \p TablePtr, \p JTI, \p IndexReg + /// + /// G_BRJT is a jump table branch using a table base pointer \p TablePtr, + /// jump table index \p JTI and index \p IndexReg + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p TablePtr must be a generic virtual register with pointer type. + /// \pre \p JTI must be be a jump table index. + /// \pre \p IndexReg must be a generic virtual register with pointer type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildBrJT(Register TablePtr, unsigned JTI, + Register IndexReg); /// Build and insert \p Res = G_CONSTANT \p Val /// @@ -572,6 +631,7 @@ public: /// /// \return The newly created instruction. MachineInstrBuilder buildConstant(const DstOp &Res, int64_t Val); + MachineInstrBuilder buildConstant(const DstOp &Res, const APInt &Val); /// Build and insert \p Res = G_FCONSTANT \p Val /// @@ -586,6 +646,7 @@ public: const ConstantFP &Val); MachineInstrBuilder buildFConstant(const DstOp &Res, double Val); + MachineInstrBuilder buildFConstant(const DstOp &Res, const APFloat &Val); /// Build and insert \p Res = COPY Op /// @@ -605,7 +666,7 @@ public: /// \pre \p Addr must be a generic virtual register with pointer type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildLoad(unsigned Res, unsigned Addr, + MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO); /// Build and insert `Res = <opcode> Addr, MMO`. @@ -617,8 +678,8 @@ public: /// \pre \p Addr must be a generic virtual register with pointer type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildLoadInstr(unsigned Opcode, unsigned Res, - unsigned Addr, MachineMemOperand &MMO); + MachineInstrBuilder buildLoadInstr(unsigned Opcode, const DstOp &Res, + const SrcOp &Addr, MachineMemOperand &MMO); /// Build and insert `G_STORE Val, Addr, MMO`. /// @@ -629,7 +690,7 @@ public: /// \pre \p Addr must be a generic virtual register with pointer type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildStore(unsigned Val, unsigned Addr, + MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO); /// Build and insert `Res0, ... = G_EXTRACT Src, Idx0`. @@ -638,7 +699,7 @@ public: /// \pre \p Res and \p Src must be generic virtual registers. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildExtract(unsigned Res, unsigned Src, uint64_t Index); + MachineInstrBuilder buildExtract(const DstOp &Res, const SrcOp &Src, uint64_t Index); /// Build and insert \p Res = IMPLICIT_DEF. MachineInstrBuilder buildUndef(const DstOp &Res); @@ -656,7 +717,7 @@ public: /// \pre The bits defined by each Op (derived from index and scalar size) must /// not overlap. /// \pre \p Indices must be in ascending order of bit position. - void buildSequence(unsigned Res, ArrayRef<unsigned> Ops, + void buildSequence(Register Res, ArrayRef<Register> Ops, ArrayRef<uint64_t> Indices); /// Build and insert \p Res = G_MERGE_VALUES \p Op0, ... @@ -670,7 +731,7 @@ public: /// \pre The type of all \p Ops registers must be identical. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildMerge(const DstOp &Res, ArrayRef<unsigned> Ops); + MachineInstrBuilder buildMerge(const DstOp &Res, ArrayRef<Register> Ops); /// Build and insert \p Res0, ... = G_UNMERGE_VALUES \p Op /// @@ -683,7 +744,10 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildUnmerge(ArrayRef<LLT> Res, const SrcOp &Op); - MachineInstrBuilder buildUnmerge(ArrayRef<unsigned> Res, const SrcOp &Op); + MachineInstrBuilder buildUnmerge(ArrayRef<Register> Res, const SrcOp &Op); + + /// Build and insert an unmerge of \p Res sized pieces to cover \p Op + MachineInstrBuilder buildUnmerge(LLT Res, const SrcOp &Op); /// Build and insert \p Res = G_BUILD_VECTOR \p Op0, ... /// @@ -695,7 +759,12 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildBuildVector(const DstOp &Res, - ArrayRef<unsigned> Ops); + ArrayRef<Register> Ops); + + /// Build and insert \p Res = G_BUILD_VECTOR with \p Src replicated to fill + /// the number of elements + MachineInstrBuilder buildSplatVector(const DstOp &Res, + const SrcOp &Src); /// Build and insert \p Res = G_BUILD_VECTOR_TRUNC \p Op0, ... /// @@ -711,7 +780,7 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildBuildVectorTrunc(const DstOp &Res, - ArrayRef<unsigned> Ops); + ArrayRef<Register> Ops); /// Build and insert \p Res = G_CONCAT_VECTORS \p Op0, ... /// @@ -725,10 +794,10 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildConcatVectors(const DstOp &Res, - ArrayRef<unsigned> Ops); + ArrayRef<Register> Ops); - MachineInstrBuilder buildInsert(unsigned Res, unsigned Src, - unsigned Op, unsigned Index); + MachineInstrBuilder buildInsert(Register Res, Register Src, + Register Op, unsigned Index); /// Build and insert either a G_INTRINSIC (if \p HasSideEffects is false) or /// G_INTRINSIC_W_SIDE_EFFECTS instruction. Its first operand will be the @@ -740,7 +809,9 @@ public: /// \pre setBasicBlock or setMI must have been called. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, unsigned Res, + MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, ArrayRef<Register> Res, + bool HasSideEffects); + MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, ArrayRef<DstOp> Res, bool HasSideEffects); /// Build and insert \p Res = G_FPTRUNC \p Op @@ -855,8 +926,8 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder - buildAtomicCmpXchgWithSuccess(unsigned OldValRes, unsigned SuccessRes, - unsigned Addr, unsigned CmpVal, unsigned NewVal, + buildAtomicCmpXchgWithSuccess(Register OldValRes, Register SuccessRes, + Register Addr, Register CmpVal, Register NewVal, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMIC_CMPXCHG Addr, CmpVal, NewVal, @@ -873,8 +944,8 @@ public: /// registers of the same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicCmpXchg(unsigned OldValRes, unsigned Addr, - unsigned CmpVal, unsigned NewVal, + MachineInstrBuilder buildAtomicCmpXchg(Register OldValRes, Register Addr, + Register CmpVal, Register NewVal, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_<Opcode> Addr, Val, MMO`. @@ -890,8 +961,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMW(unsigned Opcode, unsigned OldValRes, - unsigned Addr, unsigned Val, + MachineInstrBuilder buildAtomicRMW(unsigned Opcode, Register OldValRes, + Register Addr, Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_XCHG Addr, Val, MMO`. @@ -906,8 +977,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWXchg(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWXchg(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_ADD Addr, Val, MMO`. /// @@ -921,8 +992,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWAdd(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWAdd(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_SUB Addr, Val, MMO`. /// @@ -936,8 +1007,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWSub(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWSub(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_AND Addr, Val, MMO`. /// @@ -951,8 +1022,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWAnd(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWAnd(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_NAND Addr, Val, MMO`. /// @@ -967,8 +1038,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWNand(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWNand(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_OR Addr, Val, MMO`. /// @@ -982,8 +1053,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWOr(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWOr(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_XOR Addr, Val, MMO`. /// @@ -997,8 +1068,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWXor(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWXor(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_MAX Addr, Val, MMO`. /// @@ -1013,8 +1084,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWMax(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWMax(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_MIN Addr, Val, MMO`. /// @@ -1029,8 +1100,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWMin(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWMin(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_UMAX Addr, Val, MMO`. /// @@ -1045,8 +1116,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWUmax(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWUmax(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_UMIN Addr, Val, MMO`. /// @@ -1061,8 +1132,11 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWUmin(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWUmin(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); + + /// Build and insert `G_FENCE Ordering, Scope`. + MachineInstrBuilder buildFence(unsigned Ordering, unsigned Scope); /// Build and insert \p Res = G_BLOCK_ADDR \p BA /// @@ -1072,7 +1146,7 @@ public: /// \pre \p Res must be a generic virtual register of a pointer type. /// /// \return The newly created instruction. - MachineInstrBuilder buildBlockAddress(unsigned Res, const BlockAddress *BA); + MachineInstrBuilder buildBlockAddress(Register Res, const BlockAddress *BA); /// Build and insert \p Res = G_ADD \p Op0, \p Op1 /// @@ -1124,6 +1198,36 @@ public: return buildInstr(TargetOpcode::G_MUL, {Dst}, {Src0, Src1}, Flags); } + MachineInstrBuilder buildUMulH(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional<unsigned> Flags = None) { + return buildInstr(TargetOpcode::G_UMULH, {Dst}, {Src0, Src1}, Flags); + } + + MachineInstrBuilder buildSMulH(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional<unsigned> Flags = None) { + return buildInstr(TargetOpcode::G_SMULH, {Dst}, {Src0, Src1}, Flags); + } + + MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional<unsigned> Flags = None) { + return buildInstr(TargetOpcode::G_SHL, {Dst}, {Src0, Src1}, Flags); + } + + MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional<unsigned> Flags = None) { + return buildInstr(TargetOpcode::G_LSHR, {Dst}, {Src0, Src1}, Flags); + } + + MachineInstrBuilder buildAShr(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional<unsigned> Flags = None) { + return buildInstr(TargetOpcode::G_ASHR, {Dst}, {Src0, Src1}, Flags); + } + /// Build and insert \p Res = G_AND \p Op0, \p Op1 /// /// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p @@ -1155,6 +1259,137 @@ public: return buildInstr(TargetOpcode::G_OR, {Dst}, {Src0, Src1}); } + /// Build and insert \p Res = G_XOR \p Op0, \p Op1 + MachineInstrBuilder buildXor(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_XOR, {Dst}, {Src0, Src1}); + } + + /// Build and insert a bitwise not, + /// \p NegOne = G_CONSTANT -1 + /// \p Res = G_OR \p Op0, NegOne + MachineInstrBuilder buildNot(const DstOp &Dst, const SrcOp &Src0) { + auto NegOne = buildConstant(Dst.getLLTTy(*getMRI()), -1); + return buildInstr(TargetOpcode::G_XOR, {Dst}, {Src0, NegOne}); + } + + /// Build and insert \p Res = G_CTPOP \p Op0, \p Src0 + MachineInstrBuilder buildCTPOP(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_CTPOP, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_CTLZ \p Op0, \p Src0 + MachineInstrBuilder buildCTLZ(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_CTLZ, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_CTLZ_ZERO_UNDEF \p Op0, \p Src0 + MachineInstrBuilder buildCTLZ_ZERO_UNDEF(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_CTTZ \p Op0, \p Src0 + MachineInstrBuilder buildCTTZ(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_CTTZ, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_CTTZ_ZERO_UNDEF \p Op0, \p Src0 + MachineInstrBuilder buildCTTZ_ZERO_UNDEF(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_FADD \p Op0, \p Op1 + MachineInstrBuilder buildFAdd(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_FADD, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_FSUB \p Op0, \p Op1 + MachineInstrBuilder buildFSub(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_FSUB, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_FMA \p Op0, \p Op1, \p Op2 + MachineInstrBuilder buildFMA(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, const SrcOp &Src2) { + return buildInstr(TargetOpcode::G_FMA, {Dst}, {Src0, Src1, Src2}); + } + + /// Build and insert \p Res = G_FNEG \p Op0 + MachineInstrBuilder buildFNeg(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_FNEG, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_FABS \p Op0 + MachineInstrBuilder buildFAbs(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_FABS, {Dst}, {Src0}); + } + + /// Build and insert \p Dst = G_FCANONICALIZE \p Src0 + MachineInstrBuilder buildFCanonicalize(const DstOp &Dst, const SrcOp &Src0, + Optional<unsigned> Flags = None) { + return buildInstr(TargetOpcode::G_FCANONICALIZE, {Dst}, {Src0}, Flags); + } + + /// Build and insert \p Res = G_FCOPYSIGN \p Op0, \p Op1 + MachineInstrBuilder buildFCopysign(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_FCOPYSIGN, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_UITOFP \p Src0 + MachineInstrBuilder buildUITOFP(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_UITOFP, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_SITOFP \p Src0 + MachineInstrBuilder buildSITOFP(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_SITOFP, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_FPTOUI \p Src0 + MachineInstrBuilder buildFPTOUI(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_FPTOUI, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_FPTOSI \p Src0 + MachineInstrBuilder buildFPTOSI(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_FPTOSI, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_SMIN \p Op0, \p Op1 + MachineInstrBuilder buildSMin(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_SMIN, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_SMAX \p Op0, \p Op1 + MachineInstrBuilder buildSMax(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_SMAX, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_UMIN \p Op0, \p Op1 + MachineInstrBuilder buildUMin(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_UMIN, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_UMAX \p Op0, \p Op1 + MachineInstrBuilder buildUMax(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_UMAX, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_JUMP_TABLE \p JTI + /// + /// G_JUMP_TABLE sets \p Res to the address of the jump table specified by + /// the jump table index \p JTI. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildJumpTable(const LLT PtrTy, unsigned JTI); + virtual MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps, ArrayRef<SrcOp> SrcOps, Optional<unsigned> Flags = None); diff --git a/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h index c53ae416e60b..d9d076ba312c 100644 --- a/include/llvm/CodeGen/GlobalISel/RegBankSelect.h +++ b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h @@ -1,9 +1,8 @@ //=- llvm/CodeGen/GlobalISel/RegBankSelect.h - Reg Bank Selector --*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -524,7 +523,7 @@ private: /// \p OnlyAssign == true means that \p Reg just needs to be assigned a /// register bank. I.e., no repairing is necessary to have the /// assignment match. - bool assignmentMatch(unsigned Reg, + bool assignmentMatch(Register Reg, const RegisterBankInfo::ValueMapping &ValMapping, bool &OnlyAssign) const; @@ -563,7 +562,7 @@ private: bool repairReg(MachineOperand &MO, const RegisterBankInfo::ValueMapping &ValMapping, RegBankSelect::RepairingPlacement &RepairPt, - const iterator_range<SmallVectorImpl<unsigned>::const_iterator> + const iterator_range<SmallVectorImpl<Register>::const_iterator> &NewVRegs); /// Return the cost of the instruction needed to map \p MO to \p ValMapping. @@ -634,6 +633,11 @@ public: MachineFunctionProperties::Property::RegBankSelected); } + MachineFunctionProperties getClearedProperties() const override { + return MachineFunctionProperties() + .set(MachineFunctionProperties::Property::NoPHIs); + } + /// Walk through \p MF and assign a register bank to every virtual register /// that are still mapped to nothing. /// The target needs to provide a RegisterBankInfo and in particular diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBank.h b/include/llvm/CodeGen/GlobalISel/RegisterBank.h index d5612e17393c..f528d1a46012 100644 --- a/include/llvm/CodeGen/GlobalISel/RegisterBank.h +++ b/include/llvm/CodeGen/GlobalISel/RegisterBank.h @@ -1,9 +1,8 @@ //==-- llvm/CodeGen/GlobalISel/RegisterBank.h - Register Bank ----*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h index c33b32b2db40..e84b1c3ea8b1 100644 --- a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/RegisterBankInfo.h ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,6 +18,7 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/CodeGen/Register.h" #include "llvm/Support/ErrorHandling.h" #include <cassert> #include <initializer_list> @@ -161,6 +161,10 @@ public: const PartialMapping *begin() const { return BreakDown; } const PartialMapping *end() const { return BreakDown + NumBreakDowns; } + /// \return true if all partial mappings are the same size and register + /// bank. + bool partsAllUniform() const; + /// Check if this ValueMapping is valid. bool isValid() const { return BreakDown && NumBreakDowns; } @@ -190,7 +194,7 @@ public: unsigned Cost = 0; /// Mapping of all the operands. - const ValueMapping *OperandsMapping; + const ValueMapping *OperandsMapping = nullptr; /// Number of operands. unsigned NumOperands = 0; @@ -207,15 +211,11 @@ public: /// The rationale is that it is more efficient for the optimizers /// to be able to assume that the mapping of the ith operand is /// at the index i. - /// - /// \pre ID != InvalidMappingID InstructionMapping(unsigned ID, unsigned Cost, const ValueMapping *OperandsMapping, unsigned NumOperands) : ID(ID), Cost(Cost), OperandsMapping(OperandsMapping), NumOperands(NumOperands) { - assert(getID() != InvalidMappingID && - "Use the default constructor for invalid mapping"); } /// Default constructor. @@ -282,7 +282,7 @@ public: SmallVector<int, 8> OpToNewVRegIdx; /// Hold the registers that will be used to map MI with InstrMapping. - SmallVector<unsigned, 8> NewVRegs; + SmallVector<Register, 8> NewVRegs; /// Current MachineRegisterInfo, used to create new virtual registers. MachineRegisterInfo &MRI; @@ -303,15 +303,15 @@ public: /// \return The iterator range for the space created. // /// \pre getMI().getOperand(OpIdx).isReg() - iterator_range<SmallVectorImpl<unsigned>::iterator> + iterator_range<SmallVectorImpl<Register>::iterator> getVRegsMem(unsigned OpIdx); /// Get the end iterator for a range starting at \p StartIdx and /// spannig \p NumVal in NewVRegs. /// \pre StartIdx + NumVal <= NewVRegs.size() - SmallVectorImpl<unsigned>::const_iterator + SmallVectorImpl<Register>::const_iterator getNewVRegsEnd(unsigned StartIdx, unsigned NumVal) const; - SmallVectorImpl<unsigned>::iterator getNewVRegsEnd(unsigned StartIdx, + SmallVectorImpl<Register>::iterator getNewVRegsEnd(unsigned StartIdx, unsigned NumVal); public: @@ -357,7 +357,7 @@ public: /// /// \post the \p PartialMapIdx-th register of the value mapping of the \p /// OpIdx-th operand has been set. - void setVRegs(unsigned OpIdx, unsigned PartialMapIdx, unsigned NewVReg); + void setVRegs(unsigned OpIdx, unsigned PartialMapIdx, Register NewVReg); /// Get all the virtual registers required to map the \p OpIdx-th operand of /// the instruction. @@ -371,7 +371,7 @@ public: /// /// \pre getMI().getOperand(OpIdx).isReg() /// \pre ForDebug || All partial mappings have been set a register - iterator_range<SmallVectorImpl<unsigned>::const_iterator> + iterator_range<SmallVectorImpl<Register>::const_iterator> getVRegs(unsigned OpIdx, bool ForDebug = false) const; /// Print this operands mapper on dbgs() stream. @@ -435,7 +435,7 @@ protected: /// Get the MinimalPhysRegClass for Reg. /// \pre Reg is a physical register. const TargetRegisterClass & - getMinimalPhysRegClass(unsigned Reg, const TargetRegisterInfo &TRI) const; + getMinimalPhysRegClass(Register Reg, const TargetRegisterInfo &TRI) const; /// Try to get the mapping of \p MI. /// See getInstrMapping for more details on what a mapping represents. @@ -580,7 +580,7 @@ public: /// or a register bank, then this returns nullptr. /// /// \pre Reg != 0 (NoRegister) - const RegisterBank *getRegBank(unsigned Reg, const MachineRegisterInfo &MRI, + const RegisterBank *getRegBank(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const; /// Get the total number of register banks. @@ -618,6 +618,21 @@ public: return &A != &B; } + /// \returns true if emitting a copy from \p Src to \p Dst is impossible. + bool cannotCopy(const RegisterBank &Dst, const RegisterBank &Src, + unsigned Size) const { + return copyCost(Dst, Src, Size) == std::numeric_limits<unsigned>::max(); + } + + /// Get the cost of using \p ValMapping to decompose a register. This is + /// similar to ::copyCost, except for cases where multiple copy-like + /// operations need to be inserted. If the register is used as a source + /// operand and already has a bank assigned, \p CurBank is non-null. + virtual unsigned getBreakDownCost(const ValueMapping &ValMapping, + const RegisterBank *CurBank = nullptr) const { + return std::numeric_limits<unsigned>::max(); + } + /// Constrain the (possibly generic) virtual register \p Reg to \p RC. /// /// \pre \p Reg is a virtual register that either has a bank or a class. @@ -626,7 +641,7 @@ public: /// \note Use MachineRegisterInfo::constrainRegAttrs instead for any non-isel /// purpose, including non-select passes of GlobalISel static const TargetRegisterClass * - constrainGenericRegister(unsigned Reg, const TargetRegisterClass &RC, + constrainGenericRegister(Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI); /// Identifier used when the related instruction mapping instance @@ -711,7 +726,7 @@ public: /// virtual register. /// /// \pre \p Reg != 0 (NoRegister). - unsigned getSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI, + unsigned getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const; /// Check that information hold by this instance make sense for the diff --git a/include/llvm/CodeGen/GlobalISel/Types.h b/include/llvm/CodeGen/GlobalISel/Types.h index 7b22e343a7f8..4fd7043ba02d 100644 --- a/include/llvm/CodeGen/GlobalISel/Types.h +++ b/include/llvm/CodeGen/GlobalISel/Types.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/Types.h - Types used by GISel ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/CodeGen/GlobalISel/Utils.h b/include/llvm/CodeGen/GlobalISel/Utils.h index 82b791d35b2b..4cdaa48fb689 100644 --- a/include/llvm/CodeGen/GlobalISel/Utils.h +++ b/include/llvm/CodeGen/GlobalISel/Utils.h @@ -1,9 +1,8 @@ //==-- llvm/CodeGen/GlobalISel/Utils.h ---------------------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -16,6 +15,7 @@ #define LLVM_CODEGEN_GLOBALISEL_UTILS_H #include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/Register.h" namespace llvm { @@ -37,21 +37,37 @@ class ConstantFP; class APFloat; /// Try to constrain Reg to the specified register class. If this fails, -/// create a new virtual register in the correct class and insert a COPY before -/// \p InsertPt. The debug location of \p InsertPt is used for the new copy. +/// create a new virtual register in the correct class. /// /// \return The virtual register constrained to the right register class. unsigned constrainRegToClass(MachineRegisterInfo &MRI, const TargetInstrInfo &TII, - const RegisterBankInfo &RBI, - MachineInstr &InsertPt, unsigned Reg, + const RegisterBankInfo &RBI, unsigned Reg, const TargetRegisterClass &RegClass); +/// Constrain the Register operand OpIdx, so that it is now constrained to the +/// TargetRegisterClass passed as an argument (RegClass). +/// If this fails, create a new virtual register in the correct class and +/// insert a COPY before \p InsertPt if it is a use or after if it is a +/// definition. The debug location of \p InsertPt is used for the new copy. +/// +/// \return The virtual register constrained to the right register class. +unsigned constrainOperandRegClass(const MachineFunction &MF, + const TargetRegisterInfo &TRI, + MachineRegisterInfo &MRI, + const TargetInstrInfo &TII, + const RegisterBankInfo &RBI, + MachineInstr &InsertPt, + const TargetRegisterClass &RegClass, + const MachineOperand &RegMO, unsigned OpIdx); + /// Try to constrain Reg so that it is usable by argument OpIdx of the /// provided MCInstrDesc \p II. If this fails, create a new virtual -/// register in the correct class and insert a COPY before \p InsertPt. -/// This is equivalent to constrainRegToClass() with RegClass obtained from the -/// MCInstrDesc. The debug location of \p InsertPt is used for the new copy. +/// register in the correct class and insert a COPY before \p InsertPt +/// if it is a use or after if it is a definition. +/// This is equivalent to constrainOperandRegClass(..., RegClass, ...) +/// with RegClass obtained from the MCInstrDesc. The debug location of \p +/// InsertPt is used for the new copy. /// /// \return The virtual register constrained to the right register class. unsigned constrainOperandRegClass(const MachineFunction &MF, @@ -90,17 +106,40 @@ void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, const char *PassName, StringRef Msg, const MachineInstr &MI); +/// If \p VReg is defined by a G_CONSTANT fits in int64_t +/// returns it. Optional<int64_t> getConstantVRegVal(unsigned VReg, const MachineRegisterInfo &MRI); +/// Simple struct used to hold a constant integer value and a virtual +/// register. +struct ValueAndVReg { + int64_t Value; + unsigned VReg; +}; +/// If \p VReg is defined by a statically evaluable chain of +/// instructions rooted on a G_CONSTANT (\p LookThroughInstrs == true) +/// and that constant fits in int64_t, returns its value as well as +/// the virtual register defined by this G_CONSTANT. +/// When \p LookThroughInstrs == false, this function behaves like +/// getConstantVRegVal. +Optional<ValueAndVReg> +getConstantVRegValWithLookThrough(unsigned VReg, const MachineRegisterInfo &MRI, + bool LookThroughInstrs = true); const ConstantFP* getConstantFPVRegVal(unsigned VReg, const MachineRegisterInfo &MRI); /// See if Reg is defined by an single def instruction that is /// Opcode. Also try to do trivial folding if it's a COPY with /// same types. Returns null otherwise. -MachineInstr *getOpcodeDef(unsigned Opcode, unsigned Reg, +MachineInstr *getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI); +/// Find the def instruction for \p Reg, folding away any trivial copies. Note +/// it may still return a COPY, if it changes the type. May return nullptr if \p +/// Reg is not a generic virtual register. +MachineInstr *getDefIgnoringCopies(Register Reg, + const MachineRegisterInfo &MRI); + /// Returns an APFloat from Val converted to the appropriate size. APFloat getAPFloatFromSize(double Val, unsigned Size); @@ -111,5 +150,16 @@ void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU); Optional<APInt> ConstantFoldBinOp(unsigned Opcode, const unsigned Op1, const unsigned Op2, const MachineRegisterInfo &MRI); + +/// Returns true if \p Val can be assumed to never be a NaN. If \p SNaN is true, +/// this returns if \p Val can be assumed to never be a signaling NaN. +bool isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI, + bool SNaN = false); + +/// Returns true if \p Val can be assumed to never be a signaling NaN. +inline bool isKnownNeverSNaN(Register Val, const MachineRegisterInfo &MRI) { + return isKnownNeverNaN(Val, MRI, true); +} + } // End namespace llvm. #endif diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 9c918ae1104f..acf27dcc5fab 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/ISDOpcodes.h - CodeGen opcodes -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -272,12 +271,17 @@ namespace ISD { /// resulting value is this minimum value. SSUBSAT, USUBSAT, - /// RESULT = SMULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on + /// RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on /// 2 integers with the same width and scale. SCALE represents the scale of /// both operands as fixed point numbers. This SCALE parameter must be a /// constant integer. A scale of zero is effectively performing /// multiplication on 2 integers. - SMULFIX, + SMULFIX, UMULFIX, + + /// Same as the corresponding unsaturated fixed point instructions, but the + /// result is clamped between the min and max values representable by the + /// bits of the first 2 operands. + SMULFIXSAT, /// Simple binary floating point operators. FADD, FSUB, FMUL, FDIV, FREM, @@ -298,6 +302,26 @@ namespace ISD { STRICT_FRINT, STRICT_FNEARBYINT, STRICT_FMAXNUM, STRICT_FMINNUM, STRICT_FCEIL, STRICT_FFLOOR, STRICT_FROUND, STRICT_FTRUNC, + /// X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating + /// point type down to the precision of the destination VT. TRUNC is a + /// flag, which is always an integer that is zero or one. If TRUNC is 0, + /// this is a normal rounding, if it is 1, this FP_ROUND is known to not + /// change the value of Y. + /// + /// The TRUNC = 1 case is used in cases where we know that the value will + /// not be modified by the node, because Y is not using any of the extra + /// precision of source type. This allows certain transformations like + /// STRICT_FP_EXTEND(STRICT_FP_ROUND(X,1)) -> X which are not safe for + /// STRICT_FP_EXTEND(STRICT_FP_ROUND(X,0)) because the extra bits aren't + /// removed. + /// It is used to limit optimizations while the DAG is being optimized. + STRICT_FP_ROUND, + + /// X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP + /// type. + /// It is used to limit optimizations while the DAG is being optimized. + STRICT_FP_EXTEND, + /// FMA - Perform a * b + c with no intermediate rounding step. FMA, @@ -580,10 +604,14 @@ namespace ISD { /// is often a storage-only type but has native conversions. FP16_TO_FP, FP_TO_FP16, - /// Perform various unary floating-point operations inspired by libm. + /// Perform various unary floating-point operations inspired by libm. For + /// FPOWI, the result is undefined if if the integer operand doesn't fit + /// into 32 bits. FNEG, FABS, FSQRT, FCBRT, FSIN, FCOS, FPOWI, FPOW, FLOG, FLOG2, FLOG10, FEXP, FEXP2, FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR, + LROUND, LLROUND, LRINT, LLRINT, + /// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two /// values. // @@ -666,6 +694,9 @@ namespace ISD { /// SDOperands. INLINEASM, + /// INLINEASM_BR - Terminator version of inline asm. Used by asm-goto. + INLINEASM_BR, + /// EH_LABEL - Represents a label in mid basic block used to track /// locations needed for debug and exception handling tables. These nodes /// take a chain as input and return a chain. @@ -819,6 +850,8 @@ namespace ISD { ATOMIC_LOAD_MAX, ATOMIC_LOAD_UMIN, ATOMIC_LOAD_UMAX, + ATOMIC_LOAD_FADD, + ATOMIC_LOAD_FSUB, // Masked load and store - consecutive vector load and store operations // with additional mask operand that prevents memory accesses to the @@ -866,11 +899,14 @@ namespace ISD { VECREDUCE_STRICT_FADD, VECREDUCE_STRICT_FMUL, /// These reductions are non-strict, and have a single vector operand. VECREDUCE_FADD, VECREDUCE_FMUL, + /// FMIN/FMAX nodes can have flags, for NaN/NoNaN variants. + VECREDUCE_FMAX, VECREDUCE_FMIN, + /// Integer reductions may have a result type larger than the vector element + /// type. However, the reduction is performed using the vector element type + /// and the value in the top bits is unspecified. VECREDUCE_ADD, VECREDUCE_MUL, VECREDUCE_AND, VECREDUCE_OR, VECREDUCE_XOR, VECREDUCE_SMAX, VECREDUCE_SMIN, VECREDUCE_UMAX, VECREDUCE_UMIN, - /// FMIN/FMAX nodes can have flags, for NaN/NoNaN variants. - VECREDUCE_FMAX, VECREDUCE_FMIN, /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific pre-isel opcode values start here. diff --git a/include/llvm/CodeGen/IntrinsicLowering.h b/include/llvm/CodeGen/IntrinsicLowering.h index 597d684909c1..daf2d9a47801 100644 --- a/include/llvm/CodeGen/IntrinsicLowering.h +++ b/include/llvm/CodeGen/IntrinsicLowering.h @@ -1,9 +1,8 @@ //===-- IntrinsicLowering.h - Intrinsic Function Lowering -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -31,10 +30,6 @@ class IntrinsicLowering { public: explicit IntrinsicLowering(const DataLayout &DL) : DL(DL), Warned(false) {} - /// Add all of the prototypes that might be needed by an intrinsic lowering - /// implementation to be inserted into the module specified. - void AddPrototypes(Module &M); - /// Replace a call to the specified intrinsic function. /// If an intrinsic function must be implemented by the code generator /// (such as va_start), this function should print a message and abort. diff --git a/include/llvm/CodeGen/LatencyPriorityQueue.h b/include/llvm/CodeGen/LatencyPriorityQueue.h index 9b8d83ce77ca..95f4c6473542 100644 --- a/include/llvm/CodeGen/LatencyPriorityQueue.h +++ b/include/llvm/CodeGen/LatencyPriorityQueue.h @@ -1,9 +1,8 @@ //===---- LatencyPriorityQueue.h - A latency-oriented priority queue ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h b/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h index 221f16a03f16..ca99c6c89b19 100644 --- a/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h +++ b/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h @@ -1,9 +1,8 @@ ///===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*--===// /// -/// The LLVM Compiler Infrastructure -/// -/// This file is distributed under the University of Illinois Open Source -/// License. See LICENSE.TXT for details. +/// 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 /// ///===---------------------------------------------------------------------===// /// \file diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 3ba503487823..253d4734995b 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -1,9 +1,8 @@ //===- LexicalScopes.cpp - Collecting lexical scope info --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LinkAllAsmWriterComponents.h b/include/llvm/CodeGen/LinkAllAsmWriterComponents.h index 38fcb37b1e69..75a5c359630e 100644 --- a/include/llvm/CodeGen/LinkAllAsmWriterComponents.h +++ b/include/llvm/CodeGen/LinkAllAsmWriterComponents.h @@ -1,9 +1,8 @@ //===- llvm/Codegen/LinkAllAsmWriterComponents.h ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 18c13ca8f598..56c93b24147e 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -1,9 +1,8 @@ //===- llvm/Codegen/LinkAllCodegenComponents.h ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index cdf9ad2588cf..8bb88165d3e1 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/LiveInterval.h - Interval representation ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -606,6 +605,44 @@ namespace llvm { /// activated in the constructor of the live range. void flushSegmentSet(); + /// Stores indexes from the input index sequence R at which this LiveRange + /// is live to the output O iterator. + /// R is a range of _ascending sorted_ _random_ access iterators + /// to the input indexes. Indexes stored at O are ascending sorted so it + /// can be used directly in the subsequent search (for example for + /// subranges). Returns true if found at least one index. + template <typename Range, typename OutputIt> + bool findIndexesLiveAt(Range &&R, OutputIt O) const { + assert(std::is_sorted(R.begin(), R.end())); + auto Idx = R.begin(), EndIdx = R.end(); + auto Seg = segments.begin(), EndSeg = segments.end(); + bool Found = false; + while (Idx != EndIdx && Seg != EndSeg) { + // if the Seg is lower find first segment that is above Idx using binary + // search + if (Seg->end <= *Idx) { + Seg = std::upper_bound(++Seg, EndSeg, *Idx, + [=](typename std::remove_reference<decltype(*Idx)>::type V, + const typename std::remove_reference<decltype(*Seg)>::type &S) { + return V < S.end; + }); + if (Seg == EndSeg) + break; + } + auto NotLessStart = std::lower_bound(Idx, EndIdx, Seg->start); + if (NotLessStart == EndIdx) + break; + auto NotLessEnd = std::lower_bound(NotLessStart, EndIdx, Seg->end); + if (NotLessEnd != NotLessStart) { + Found = true; + O = std::copy(NotLessStart, NotLessEnd, O); + } + Idx = NotLessEnd; + ++Seg; + } + return Found; + } + void print(raw_ostream &OS) const; void dump() const; @@ -790,8 +827,15 @@ namespace llvm { /// L000F, refining for mask L0018. Will split the L00F0 lane into /// L00E0 and L0010 and the L000F lane into L0007 and L0008. The Mod /// function will be applied to the L0010 and L0008 subranges. + /// + /// \p Indexes and \p TRI are required to clean up the VNIs that + /// don't defne the related lane masks after they get shrunk. E.g., + /// when L000F gets split into L0007 and L0008 maybe only a subset + /// of the VNIs that defined L000F defines L0007. void refineSubRanges(BumpPtrAllocator &Allocator, LaneBitmask LaneMask, - std::function<void(LiveInterval::SubRange&)> Apply); + std::function<void(LiveInterval::SubRange &)> Apply, + const SlotIndexes &Indexes, + const TargetRegisterInfo &TRI); bool operator<(const LiveInterval& other) const { const SlotIndex &thisIndex = beginIndex(); diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 9e2799bd4414..05506d2c3bc6 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -1,9 +1,8 @@ //===- LiveIntervalUnion.h - Live interval union data struct ---*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveIntervals.h b/include/llvm/CodeGen/LiveIntervals.h index 16ab1dc475c4..588b0f9cf39c 100644 --- a/include/llvm/CodeGen/LiveIntervals.h +++ b/include/llvm/CodeGen/LiveIntervals.h @@ -1,9 +1,8 @@ //===- LiveIntervals.h - Live Interval Analysis -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -418,6 +417,15 @@ class VirtRegMap; RegUnitRanges[Unit] = nullptr; } + /// Remove associated live ranges for the register units associated with \p + /// Reg. Subsequent uses should rely on on-demand recomputation. \note This + /// method can result in inconsistent liveness tracking if multiple phyical + /// registers share a regunit, and should be used cautiously. + void removeAllRegUnitsForPhysReg(unsigned Reg) { + for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + removeRegUnit(*Units); + } + /// Remove value numbers and related live segments starting at position /// \p Pos that are part of any liverange of physical register \p Reg or one /// of its subregisters. diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h index 7312902e21b7..50da0b3d5c48 100644 --- a/include/llvm/CodeGen/LivePhysRegs.h +++ b/include/llvm/CodeGen/LivePhysRegs.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/LivePhysRegs.h - Live Physical Register Set -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h index 53830297c525..6519937ec071 100644 --- a/include/llvm/CodeGen/LiveRangeEdit.h +++ b/include/llvm/CodeGen/LiveRangeEdit.h @@ -1,9 +1,8 @@ //===- LiveRangeEdit.h - Basic tools for split and spill --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveRegMatrix.h b/include/llvm/CodeGen/LiveRegMatrix.h index f62a55c73085..ab4d44f9a611 100644 --- a/include/llvm/CodeGen/LiveRegMatrix.h +++ b/include/llvm/CodeGen/LiveRegMatrix.h @@ -1,9 +1,8 @@ //===- LiveRegMatrix.h - Track register interference ----------*- C++ -*---===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveRegUnits.h b/include/llvm/CodeGen/LiveRegUnits.h index 5e9dd8b3cdf6..7dbb2feab8bf 100644 --- a/include/llvm/CodeGen/LiveRegUnits.h +++ b/include/llvm/CodeGen/LiveRegUnits.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/LiveRegUnits.h - Register Unit Set ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveStacks.h b/include/llvm/CodeGen/LiveStacks.h index 44ed785f7b53..7c4c64d515df 100644 --- a/include/llvm/CodeGen/LiveStacks.h +++ b/include/llvm/CodeGen/LiveStacks.h @@ -1,9 +1,8 @@ //===- LiveStacks.h - Live Stack Slot Analysis ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index ed8da8662106..71de306e2942 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/LiveVariables.h - Live Variable Analysis ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LoopTraversal.h b/include/llvm/CodeGen/LoopTraversal.h index 750da0143c0d..e5810ef1ef26 100644 --- a/include/llvm/CodeGen/LoopTraversal.h +++ b/include/llvm/CodeGen/LoopTraversal.h @@ -1,9 +1,8 @@ //==------ llvm/CodeGen/LoopTraversal.h - Loop Traversal -*- C++ -*---------==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LowLevelType.h b/include/llvm/CodeGen/LowLevelType.h index a3c5c9329f53..687233e4e168 100644 --- a/include/llvm/CodeGen/LowLevelType.h +++ b/include/llvm/CodeGen/LowLevelType.h @@ -1,9 +1,8 @@ //== llvm/CodeGen/LowLevelType.h ------------------------------- -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MIRParser/MIParser.h b/include/llvm/CodeGen/MIRParser/MIParser.h new file mode 100644 index 000000000000..4e32a04551c1 --- /dev/null +++ b/include/llvm/CodeGen/MIRParser/MIParser.h @@ -0,0 +1,233 @@ +//===- MIParser.h - Machine Instructions Parser -----------------*- C++ -*-===// +// +// 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 file declares the function that parses the machine instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H +#define LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { + +class MachineBasicBlock; +class MachineFunction; +class MDNode; +class RegisterBank; +struct SlotMapping; +class SMDiagnostic; +class SourceMgr; +class StringRef; +class TargetRegisterClass; +class TargetSubtargetInfo; + +struct VRegInfo { + enum uint8_t { + UNKNOWN, NORMAL, GENERIC, REGBANK + } Kind = UNKNOWN; + bool Explicit = false; ///< VReg was explicitly specified in the .mir file. + union { + const TargetRegisterClass *RC; + const RegisterBank *RegBank; + } D; + unsigned VReg; + unsigned PreferredReg = 0; +}; + +using Name2RegClassMap = StringMap<const TargetRegisterClass *>; +using Name2RegBankMap = StringMap<const RegisterBank *>; + +struct PerTargetMIParsingState { +private: + const TargetSubtargetInfo &Subtarget; + + /// Maps from instruction names to op codes. + StringMap<unsigned> Names2InstrOpCodes; + + /// Maps from register names to registers. + StringMap<unsigned> Names2Regs; + + /// Maps from register mask names to register masks. + StringMap<const uint32_t *> Names2RegMasks; + + /// Maps from subregister names to subregister indices. + StringMap<unsigned> Names2SubRegIndices; + + /// Maps from target index names to target indices. + StringMap<int> Names2TargetIndices; + + /// Maps from direct target flag names to the direct target flag values. + StringMap<unsigned> Names2DirectTargetFlags; + + /// Maps from direct target flag names to the bitmask target flag values. + StringMap<unsigned> Names2BitmaskTargetFlags; + + /// Maps from MMO target flag names to MMO target flag values. + StringMap<MachineMemOperand::Flags> Names2MMOTargetFlags; + + /// Maps from register class names to register classes. + Name2RegClassMap Names2RegClasses; + + /// Maps from register bank names to register banks. + Name2RegBankMap Names2RegBanks; + + void initNames2InstrOpCodes(); + void initNames2Regs(); + void initNames2RegMasks(); + void initNames2SubRegIndices(); + void initNames2TargetIndices(); + void initNames2DirectTargetFlags(); + void initNames2BitmaskTargetFlags(); + void initNames2MMOTargetFlags(); + + void initNames2RegClasses(); + void initNames2RegBanks(); + +public: + /// Try to convert an instruction name to an opcode. Return true if the + /// instruction name is invalid. + bool parseInstrName(StringRef InstrName, unsigned &OpCode); + + /// Try to convert a register name to a register number. Return true if the + /// register name is invalid. + bool getRegisterByName(StringRef RegName, unsigned &Reg); + + /// Check if the given identifier is a name of a register mask. + /// + /// Return null if the identifier isn't a register mask. + const uint32_t *getRegMask(StringRef Identifier); + + /// Check if the given identifier is a name of a subregister index. + /// + /// Return 0 if the name isn't a subregister index class. + unsigned getSubRegIndex(StringRef Name); + + /// Try to convert a name of target index to the corresponding target index. + /// + /// Return true if the name isn't a name of a target index. + bool getTargetIndex(StringRef Name, int &Index); + + /// Try to convert a name of a direct target flag to the corresponding + /// target flag. + /// + /// Return true if the name isn't a name of a direct flag. + bool getDirectTargetFlag(StringRef Name, unsigned &Flag); + + /// Try to convert a name of a bitmask target flag to the corresponding + /// target flag. + /// + /// Return true if the name isn't a name of a bitmask target flag. + bool getBitmaskTargetFlag(StringRef Name, unsigned &Flag); + + /// Try to convert a name of a MachineMemOperand target flag to the + /// corresponding target flag. + /// + /// Return true if the name isn't a name of a target MMO flag. + bool getMMOTargetFlag(StringRef Name, MachineMemOperand::Flags &Flag); + + /// Check if the given identifier is a name of a register class. + /// + /// Return null if the name isn't a register class. + const TargetRegisterClass *getRegClass(StringRef Name); + + /// Check if the given identifier is a name of a register bank. + /// + /// Return null if the name isn't a register bank. + const RegisterBank *getRegBank(StringRef Name); + + PerTargetMIParsingState(const TargetSubtargetInfo &STI) + : Subtarget(STI) { + initNames2RegClasses(); + initNames2RegBanks(); + } + + ~PerTargetMIParsingState() = default; + + void setTarget(const TargetSubtargetInfo &NewSubtarget); +}; + +struct PerFunctionMIParsingState { + BumpPtrAllocator Allocator; + MachineFunction &MF; + SourceMgr *SM; + const SlotMapping &IRSlots; + PerTargetMIParsingState &Target; + + DenseMap<unsigned, MachineBasicBlock *> MBBSlots; + DenseMap<unsigned, VRegInfo *> VRegInfos; + StringMap<VRegInfo *> VRegInfosNamed; + DenseMap<unsigned, int> FixedStackObjectSlots; + DenseMap<unsigned, int> StackObjectSlots; + DenseMap<unsigned, unsigned> ConstantPoolSlots; + DenseMap<unsigned, unsigned> JumpTableSlots; + + PerFunctionMIParsingState(MachineFunction &MF, SourceMgr &SM, + const SlotMapping &IRSlots, + PerTargetMIParsingState &Target); + + VRegInfo &getVRegInfo(unsigned Num); + VRegInfo &getVRegInfoNamed(StringRef RegName); +}; + +/// Parse the machine basic block definitions, and skip the machine +/// instructions. +/// +/// This function runs the first parsing pass on the machine function's body. +/// It parses only the machine basic block definitions and creates the machine +/// basic blocks in the given machine function. +/// +/// The machine instructions aren't parsed during the first pass because all +/// the machine basic blocks aren't defined yet - this makes it impossible to +/// resolve the machine basic block references. +/// +/// Return true if an error occurred. +bool parseMachineBasicBlockDefinitions(PerFunctionMIParsingState &PFS, + StringRef Src, SMDiagnostic &Error); + +/// Parse the machine instructions. +/// +/// This function runs the second parsing pass on the machine function's body. +/// It skips the machine basic block definitions and parses only the machine +/// instructions and basic block attributes like liveins and successors. +/// +/// The second parsing pass assumes that the first parsing pass already ran +/// on the given source string. +/// +/// Return true if an error occurred. +bool parseMachineInstructions(PerFunctionMIParsingState &PFS, StringRef Src, + SMDiagnostic &Error); + +bool parseMBBReference(PerFunctionMIParsingState &PFS, + MachineBasicBlock *&MBB, StringRef Src, + SMDiagnostic &Error); + +bool parseRegisterReference(PerFunctionMIParsingState &PFS, + unsigned &Reg, StringRef Src, + SMDiagnostic &Error); + +bool parseNamedRegisterReference(PerFunctionMIParsingState &PFS, unsigned &Reg, + StringRef Src, SMDiagnostic &Error); + +bool parseVirtualRegisterReference(PerFunctionMIParsingState &PFS, + VRegInfo *&Info, StringRef Src, + SMDiagnostic &Error); + +bool parseStackObjectReference(PerFunctionMIParsingState &PFS, int &FI, + StringRef Src, SMDiagnostic &Error); + +bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node, StringRef Src, + SMDiagnostic &Error); + +} // end namespace llvm + +#endif // LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H diff --git a/include/llvm/CodeGen/MIRParser/MIRParser.h b/include/llvm/CodeGen/MIRParser/MIRParser.h index e199a1f69ad7..6a04e48e533c 100644 --- a/include/llvm/CodeGen/MIRParser/MIRParser.h +++ b/include/llvm/CodeGen/MIRParser/MIRParser.h @@ -1,9 +1,8 @@ //===- MIRParser.h - MIR serialization format parser ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MIRPrinter.h b/include/llvm/CodeGen/MIRPrinter.h index 078c4b2f6072..a4b03a7fb765 100644 --- a/include/llvm/CodeGen/MIRPrinter.h +++ b/include/llvm/CodeGen/MIRPrinter.h @@ -1,9 +1,8 @@ -//===- MIRPrinter.h - MIR serialization format printer --------------------===// +//===- MIRPrinter.h - MIR serialization format printer ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MIRYamlMapping.h b/include/llvm/CodeGen/MIRYamlMapping.h index 98ac81915dc0..94e76a75e8da 100644 --- a/include/llvm/CodeGen/MIRYamlMapping.h +++ b/include/llvm/CodeGen/MIRYamlMapping.h @@ -1,9 +1,8 @@ -//===- MIRYAMLMapping.h - Describes the mapping between MIR and YAML ------===// +//===- MIRYamlMapping.h - Describe mapping between MIR and YAML--*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -18,6 +17,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" @@ -37,6 +37,7 @@ struct StringValue { StringValue() = default; StringValue(std::string Value) : Value(std::move(Value)) {} + StringValue(const char Val[]) : Value(Val) {} bool operator==(const StringValue &Other) const { return Value == Other.Value; @@ -212,7 +213,7 @@ struct MachineStackObject { int64_t Offset = 0; uint64_t Size = 0; unsigned Alignment = 0; - uint8_t StackID = 0; + TargetStackID::Value StackID; StringValue CalleeSavedRegister; bool CalleeSavedRestored = true; Optional<int64_t> LocalOffset; @@ -252,7 +253,7 @@ template <> struct MappingTraits<MachineStackObject> { if (Object.Type != MachineStackObject::VariableSized) YamlIO.mapRequired("size", Object.Size); YamlIO.mapOptional("alignment", Object.Alignment, (unsigned)0); - YamlIO.mapOptional("stack-id", Object.StackID); + YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default); YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister, StringValue()); // Don't print it out when it's empty. YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored, @@ -278,7 +279,7 @@ struct FixedMachineStackObject { int64_t Offset = 0; uint64_t Size = 0; unsigned Alignment = 0; - uint8_t StackID = 0; + TargetStackID::Value StackID; bool IsImmutable = false; bool IsAliased = false; StringValue CalleeSavedRegister; @@ -308,6 +309,15 @@ struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> { } }; +template <> +struct ScalarEnumerationTraits<TargetStackID::Value> { + static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) { + IO.enumCase(ID, "default", TargetStackID::Default); + IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill); + IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc); + } +}; + template <> struct MappingTraits<FixedMachineStackObject> { static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) { YamlIO.mapRequired("id", Object.ID); @@ -317,7 +327,7 @@ template <> struct MappingTraits<FixedMachineStackObject> { YamlIO.mapOptional("offset", Object.Offset, (int64_t)0); YamlIO.mapOptional("size", Object.Size, (uint64_t)0); YamlIO.mapOptional("alignment", Object.Alignment, (unsigned)0); - YamlIO.mapOptional("stack-id", Object.StackID); + YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default); if (Object.Type != FixedMachineStackObject::SpillSlot) { YamlIO.mapOptional("isImmutable", Object.IsImmutable, false); YamlIO.mapOptional("isAliased", Object.IsAliased, false); @@ -337,6 +347,66 @@ template <> struct MappingTraits<FixedMachineStackObject> { static const bool flow = true; }; + +/// Serializable representation of CallSiteInfo. +struct CallSiteInfo { + // Representation of call argument and register which is used to + // transfer it. + struct ArgRegPair { + StringValue Reg; + uint16_t ArgNo; + + bool operator==(const ArgRegPair &Other) const { + return Reg == Other.Reg && ArgNo == Other.ArgNo; + } + }; + + /// Identifies call instruction location in machine function. + struct MachineInstrLoc { + unsigned BlockNum; + unsigned Offset; + + bool operator==(const MachineInstrLoc &Other) const { + return BlockNum == Other.BlockNum && Offset == Other.Offset; + } + }; + + MachineInstrLoc CallLocation; + std::vector<ArgRegPair> ArgForwardingRegs; + + bool operator==(const CallSiteInfo &Other) const { + return CallLocation.BlockNum == Other.CallLocation.BlockNum && + CallLocation.Offset == Other.CallLocation.Offset; + } +}; + +template <> struct MappingTraits<CallSiteInfo::ArgRegPair> { + static void mapping(IO &YamlIO, CallSiteInfo::ArgRegPair &ArgReg) { + YamlIO.mapRequired("arg", ArgReg.ArgNo); + YamlIO.mapRequired("reg", ArgReg.Reg); + } + + static const bool flow = true; +}; +} +} + +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo::ArgRegPair) + +namespace llvm { +namespace yaml { + +template <> struct MappingTraits<CallSiteInfo> { + static void mapping(IO &YamlIO, CallSiteInfo &CSInfo) { + YamlIO.mapRequired("bb", CSInfo.CallLocation.BlockNum); + YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset); + YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs, + std::vector<CallSiteInfo::ArgRegPair>()); + } + + static const bool flow = true; +}; + struct MachineConstantPoolValue { UnsignedValue ID; StringValue Value; @@ -391,6 +461,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry) @@ -483,6 +554,20 @@ template <> struct MappingTraits<MachineFrameInfo> { } }; +/// Targets should override this in a way that mirrors the implementation of +/// llvm::MachineFunctionInfo. +struct MachineFunctionInfo { + virtual ~MachineFunctionInfo() {} + virtual void mappingImpl(IO &YamlIO) {} +}; + +template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> { + static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) { + if (MFI) + MFI->mappingImpl(YamlIO); + } +}; + struct MachineFunction { StringRef Name; unsigned Alignment = 0; @@ -504,6 +589,8 @@ struct MachineFunction { std::vector<FixedMachineStackObject> FixedStackObjects; std::vector<MachineStackObject> StackObjects; std::vector<MachineConstantPoolValue> Constants; /// Constant pool. + std::unique_ptr<MachineFunctionInfo> MachineFuncInfo; + std::vector<CallSiteInfo> CallSitesInfo; MachineJumpTable JumpTableInfo; BlockStringValue Body; }; @@ -530,8 +617,11 @@ template <> struct MappingTraits<MachineFunction> { std::vector<FixedMachineStackObject>()); YamlIO.mapOptional("stack", MF.StackObjects, std::vector<MachineStackObject>()); + YamlIO.mapOptional("callSites", MF.CallSitesInfo, + std::vector<CallSiteInfo>()); YamlIO.mapOptional("constants", MF.Constants, std::vector<MachineConstantPoolValue>()); + YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo); if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty()) YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable()); YamlIO.mapOptional("body", MF.Body, BlockStringValue()); diff --git a/include/llvm/CodeGen/MachORelocation.h b/include/llvm/CodeGen/MachORelocation.h index cbb49695af75..0185c7cbe018 100644 --- a/include/llvm/CodeGen/MachORelocation.h +++ b/include/llvm/CodeGen/MachORelocation.h @@ -1,9 +1,8 @@ //=== MachORelocation.h - Mach-O Relocation Info ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index ec2f270fcb3f..333d0a78618c 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineBasicBlock.h -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -115,6 +114,10 @@ private: /// branch. bool AddressTaken = false; + /// Indicate that this basic block needs its symbol be emitted regardless of + /// whether the flow just falls-through to it. + bool LabelMustBeEmitted = false; + /// Indicate that this basic block is the entry block of an EH scope, i.e., /// the block that used to have a catchpad or cleanuppad instruction in the /// LLVM IR. @@ -159,6 +162,13 @@ public: /// branch. void setHasAddressTaken() { AddressTaken = true; } + /// Test whether this block must have its label emitted. + bool hasLabelMustBeEmitted() const { return LabelMustBeEmitted; } + + /// Set this block to reflect that, regardless how we flow to it, we need + /// its label be emitted. + void setLabelMustBeEmitted() { LabelMustBeEmitted = true; } + /// Return the MachineFunction containing this basic block. const MachineFunction *getParent() const { return xParent; } MachineFunction *getParent() { return xParent; } @@ -900,11 +910,11 @@ class MachineInstrSpan { MachineBasicBlock::iterator I, B, E; public: - MachineInstrSpan(MachineBasicBlock::iterator I) - : MBB(*I->getParent()), - I(I), - B(I == MBB.begin() ? MBB.end() : std::prev(I)), - E(std::next(I)) {} + MachineInstrSpan(MachineBasicBlock::iterator I, MachineBasicBlock *BB) + : MBB(*BB), I(I), B(I == MBB.begin() ? MBB.end() : std::prev(I)), + E(std::next(I)) { + assert(I == BB->end() || I->getParent() == BB); + } MachineBasicBlock::iterator begin() { return B == MBB.end() ? MBB.begin() : std::next(B); diff --git a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h index 5b4b99ca0a5d..a438ecfcc25e 100644 --- a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h +++ b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h @@ -1,9 +1,8 @@ //===- MachineBlockFrequencyInfo.h - MBB Frequency Analysis -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h index 81b0524cf0a4..2b9b2030eb97 100644 --- a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h +++ b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h @@ -1,9 +1,8 @@ //=- MachineBranchProbabilityInfo.h - Branch Probability Analysis -*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineCombinerPattern.h b/include/llvm/CodeGen/MachineCombinerPattern.h index 586535f771c2..4f4034baf801 100644 --- a/include/llvm/CodeGen/MachineCombinerPattern.h +++ b/include/llvm/CodeGen/MachineCombinerPattern.h @@ -1,10 +1,9 @@ //===-- llvm/CodeGen/MachineCombinerPattern.h - Instruction pattern supported by // combiner ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h index b0b5420a884b..4d07b620a4b4 100644 --- a/include/llvm/CodeGen/MachineConstantPool.h +++ b/include/llvm/CodeGen/MachineConstantPool.h @@ -1,9 +1,8 @@ //===- CodeGen/MachineConstantPool.h - Abstract Constant Pool ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineDominanceFrontier.h b/include/llvm/CodeGen/MachineDominanceFrontier.h index 75d75bc3669a..f7bbd07a63ab 100644 --- a/include/llvm/CodeGen/MachineDominanceFrontier.h +++ b/include/llvm/CodeGen/MachineDominanceFrontier.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineDominanceFrontier.h ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index e3d3d169db97..d2200080b897 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -1,9 +1,8 @@ //==- llvm/CodeGen/MachineDominators.h - Machine Dom Calculation -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index c2706a21a177..761735120a64 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -1,9 +1,8 @@ //===-- CodeGen/MachineFrameInfo.h - Abstract Stack Frame Rep. --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -471,7 +470,10 @@ public: assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); Objects[ObjectIdx+NumFixedObjects].Alignment = Align; - ensureMaxAlignment(Align); + + // Only ensure max alignment for the default stack. + if (getStackID(ObjectIdx) == 0) + ensureMaxAlignment(Align); } /// Return the underlying Alloca of the specified @@ -698,6 +700,8 @@ public: assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); Objects[ObjectIdx+NumFixedObjects].StackID = ID; + // If ID > 0, MaxAlignment may now be overly conservative. + // If ID == 0, MaxAlignment will need to be updated separately. } /// Returns true if the specified index corresponds to a dead object. diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 25edf5bcce51..201c126ee52e 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineFunction.h ---------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -31,11 +30,6 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Metadata.h" -#include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MCSymbol.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ArrayRecycler.h" #include "llvm/Support/AtomicOrdering.h" @@ -53,6 +47,7 @@ namespace llvm { class BasicBlock; class BlockAddress; class DataLayout; +class DebugLoc; class DIExpression; class DILocalVariable; class DILocation; @@ -67,6 +62,7 @@ class MachineModuleInfo; class MachineRegisterInfo; class MCContext; class MCInstrDesc; +class MCSymbol; class Pass; class PseudoSourceValueManager; class raw_ostream; @@ -86,7 +82,7 @@ template <> struct ilist_callback_traits<MachineBasicBlock> { template <class Iterator> void transferNodesFromList(ilist_callback_traits &OldList, Iterator, Iterator) { - llvm_unreachable("Never transfer between lists"); + assert(this == &OldList && "never transfer MBBs between functions"); } }; @@ -325,6 +321,10 @@ class MachineFunction { /// CodeView label annotations. std::vector<std::pair<MCSymbol *, MDNode *>> CodeViewAnnotations; + /// CodeView heapallocsites. + std::vector<std::tuple<MCSymbol*, MCSymbol*, DIType*>> + CodeViewHeapAllocSites; + bool CallsEHReturn = false; bool CallsUnwindInit = false; bool HasEHScopes = false; @@ -378,9 +378,28 @@ public: virtual void MF_HandleRemoval(MachineInstr &MI) = 0; }; + /// Structure used to represent pair of argument number after call lowering + /// and register used to transfer that argument. + /// For now we support only cases when argument is transferred through one + /// register. + struct ArgRegPair { + unsigned Reg; + uint16_t ArgNo; + ArgRegPair(unsigned R, unsigned Arg) : Reg(R), ArgNo(Arg) { + assert(Arg < (1 << 16) && "Arg out of range"); + } + }; + /// Vector of call argument and its forwarding register. + using CallSiteInfo = SmallVector<ArgRegPair, 1>; + using CallSiteInfoImpl = SmallVectorImpl<ArgRegPair>; + private: Delegate *TheDelegate = nullptr; + using CallSiteInfoMap = DenseMap<const MachineInstr *, CallSiteInfo>; + /// Map a call instruction to call site arguments forwarding info. + CallSiteInfoMap CallSitesInfo; + // Callbacks for insertion and removal. void handleInsertion(MachineInstr &MI); void handleRemoval(MachineInstr &MI); @@ -443,7 +462,6 @@ public: /// getSubtarget - Return the subtarget for which this machine code is being /// compiled. const TargetSubtargetInfo &getSubtarget() const { return *STI; } - void setSubtarget(const TargetSubtargetInfo *ST) { STI = ST; } /// getSubtarget - This method returns a pointer to the specified type of /// TargetSubtargetInfo. In debug builds, it verifies that the object being @@ -741,6 +759,12 @@ public: MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, const AAMDNodes &AAInfo); + /// Allocate a new MachineMemOperand by copying an existing one, + /// replacing the flags. MachineMemOperands are owned + /// by the MachineFunction and need not be explicitly deallocated. + MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, + MachineMemOperand::Flags Flags); + using OperandCapacity = ArrayRecycler<MachineOperand>::Capacity; /// Allocate an array of MachineOperands. This is only intended for use by @@ -791,10 +815,7 @@ public: return FrameInstructions; } - LLVM_NODISCARD unsigned addFrameInst(const MCCFIInstruction &Inst) { - FrameInstructions.push_back(Inst); - return FrameInstructions.size() - 1; - } + LLVM_NODISCARD unsigned addFrameInst(const MCCFIInstruction &Inst); /// \name Exception Handling /// \{ @@ -913,6 +934,14 @@ public: return CodeViewAnnotations; } + /// Record heapallocsites + void addCodeViewHeapAllocSite(MachineInstr *I, MDNode *MD); + + ArrayRef<std::tuple<MCSymbol*, MCSymbol*, DIType*>> + getCodeViewHeapAllocSites() const { + return CodeViewHeapAllocSites; + } + /// Return a reference to the C++ typeinfo for the current function. const std::vector<const GlobalValue *> &getTypeInfos() const { return TypeInfos; @@ -936,6 +965,23 @@ public: const VariableDbgInfoMapTy &getVariableDbgInfo() const { return VariableDbgInfos; } + + void addCallArgsForwardingRegs(const MachineInstr *CallI, + CallSiteInfoImpl &&CallInfo) { + assert(CallI->isCall()); + CallSitesInfo[CallI] = std::move(CallInfo); + } + + const CallSiteInfoMap &getCallSitesInfo() const { + return CallSitesInfo; + } + + /// Update call sites info by deleting entry for \p Old call instruction. + /// If \p New is present then transfer \p Old call info to it. This function + /// should be called before removing call instruction or before replacing + /// call instruction with new one. + void updateCallSiteInfo(const MachineInstr *Old, + const MachineInstr *New = nullptr); }; //===--------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineFunctionPass.h b/include/llvm/CodeGen/MachineFunctionPass.h index 6d978daa2018..caaf22c2139e 100644 --- a/include/llvm/CodeGen/MachineFunctionPass.h +++ b/include/llvm/CodeGen/MachineFunctionPass.h @@ -1,9 +1,8 @@ //===-- MachineFunctionPass.h - Pass for MachineFunctions --------*-C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index ea1a2a536fc7..c82c5b137507 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineInstr.h - MachineInstr class ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -25,6 +24,7 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/InlineAsm.h" #include "llvm/MC/MCInstrDesc.h" @@ -103,8 +103,10 @@ public: // no unsigned wrap. NoSWrap = 1 << 12, // Instruction supports binary operator // no signed wrap. - IsExact = 1 << 13 // Instruction supports division is + IsExact = 1 << 13, // Instruction supports division is // known to be exact. + FPExcept = 1 << 14, // Instruction may raise floating-point + // exceptions. }; private: @@ -831,6 +833,17 @@ public: return mayLoad(Type) || mayStore(Type); } + /// Return true if this instruction could possibly raise a floating-point + /// exception. This is the case if the instruction is a floating-point + /// instruction that can in principle raise an exception, as indicated + /// by the MCID::MayRaiseFPException property, *and* at the same time, + /// the instruction is used in a context where we expect floating-point + /// exceptions might be enabled, as indicated by the FPExcept MI flag. + bool mayRaiseFPException() const { + return hasProperty(MCID::MayRaiseFPException) && + getFlag(MachineInstr::MIFlag::FPExcept); + } + //===--------------------------------------------------------------------===// // Flags that indicate whether an instruction can be modified by a method. //===--------------------------------------------------------------------===// @@ -1006,16 +1019,33 @@ public: && getOperand(1).isImm(); } + /// A DBG_VALUE is an entry value iff its debug expression contains the + /// DW_OP_entry_value DWARF operation. + bool isDebugEntryValue() const { + return isDebugValue() && getDebugExpression()->isEntryValue(); + } + + /// Return true if the instruction is a debug value which describes a part of + /// a variable as unavailable. + bool isUndefDebugValue() const { + return isDebugValue() && getOperand(0).isReg() && !getOperand(0).getReg(); + } + bool isPHI() const { return getOpcode() == TargetOpcode::PHI || getOpcode() == TargetOpcode::G_PHI; } bool isKill() const { return getOpcode() == TargetOpcode::KILL; } bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; } - bool isInlineAsm() const { return getOpcode() == TargetOpcode::INLINEASM; } + bool isInlineAsm() const { + return getOpcode() == TargetOpcode::INLINEASM || + getOpcode() == TargetOpcode::INLINEASM_BR; + } + /// FIXME: Seems like a layering violation that the AsmDialect, which is X86 + /// specific, be attached to a generic MachineInstr. bool isMSInlineAsm() const { - return getOpcode() == TargetOpcode::INLINEASM && getInlineAsmDialect(); + return isInlineAsm() && getInlineAsmDialect() == InlineAsm::AD_Intel; } bool isStackAligningInlineAsm() const; @@ -1197,12 +1227,22 @@ public: /// Wrapper for findRegisterDefOperandIdx, it returns /// a pointer to the MachineOperand rather than an index. - MachineOperand *findRegisterDefOperand(unsigned Reg, bool isDead = false, - const TargetRegisterInfo *TRI = nullptr) { - int Idx = findRegisterDefOperandIdx(Reg, isDead, false, TRI); + MachineOperand * + findRegisterDefOperand(unsigned Reg, bool isDead = false, + bool Overlap = false, + const TargetRegisterInfo *TRI = nullptr) { + int Idx = findRegisterDefOperandIdx(Reg, isDead, Overlap, TRI); return (Idx == -1) ? nullptr : &getOperand(Idx); } + const MachineOperand * + findRegisterDefOperand(unsigned Reg, bool isDead = false, + bool Overlap = false, + const TargetRegisterInfo *TRI = nullptr) const { + return const_cast<MachineInstr *>(this)->findRegisterDefOperand( + Reg, isDead, Overlap, TRI); + } + /// Find the index of the first operand in the /// operand list that is used to represent the predicate. It returns -1 if /// none is found. @@ -1364,7 +1404,7 @@ public: /// @param AA Optional alias analysis, used to compare memory operands. /// @param Other MachineInstr to check aliasing against. /// @param UseTBAA Whether to pass TBAA information to alias analysis. - bool mayAlias(AliasAnalysis *AA, MachineInstr &Other, bool UseTBAA); + bool mayAlias(AliasAnalysis *AA, const MachineInstr &Other, bool UseTBAA) const; /// Return true if this instruction may have an ordered /// or volatile memory reference, or if the information describing the memory @@ -1400,6 +1440,19 @@ public: /// Return true if all the defs of this instruction are dead. bool allDefsAreDead() const; + /// Return a valid size if the instruction is a spill instruction. + Optional<unsigned> getSpillSize(const TargetInstrInfo *TII) const; + + /// Return a valid size if the instruction is a folded spill instruction. + Optional<unsigned> getFoldedSpillSize(const TargetInstrInfo *TII) const; + + /// Return a valid size if the instruction is a restore instruction. + Optional<unsigned> getRestoreSize(const TargetInstrInfo *TII) const; + + /// Return a valid size if the instruction is a folded restore instruction. + Optional<unsigned> + getFoldedRestoreSize(const TargetInstrInfo *TII) const; + /// Copy implicit register operands from specified /// instruction to this instruction. void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI); @@ -1521,11 +1574,17 @@ public: /// FIXME: This is not fully implemented yet. void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol); + /// Clone another MachineInstr's pre- and post- instruction symbols and + /// replace ours with it. + void cloneInstrSymbols(MachineFunction &MF, const MachineInstr &MI); + /// Return the MIFlags which represent both MachineInstrs. This /// should be used when merging two MachineInstrs into one. This routine does /// not modify the MIFlags of this MachineInstr. uint16_t mergeFlagsWith(const MachineInstr& Other) const; + static uint16_t copyFlagsFromInstruction(const Instruction &I); + /// Copy all flags to MachineInst MIFlags void copyIRFlags(const Instruction &I); diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index b5e523f655e7..6d7fb72b6bd1 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -1,9 +1,8 @@ //===- CodeGen/MachineInstrBuilder.h - Simplify creation of MIs --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -80,6 +79,11 @@ public: /// explicitly. MachineInstr *getInstr() const { return MI; } + /// Get the register for the operand index. + /// The operand at the index should be a register (asserted by + /// MachineOperand). + Register getReg(unsigned Idx) const { return MI->getOperand(Idx).getReg(); } + /// Add a new virtual register operand. const MachineInstrBuilder &addReg(unsigned RegNo, unsigned flags = 0, unsigned SubReg = 0) const { @@ -283,6 +287,9 @@ public: case MachineOperand::MO_GlobalAddress: return addGlobalAddress(Disp.getGlobal(), Disp.getOffset() + off, TargetFlags); + case MachineOperand::MO_BlockAddress: + return addBlockAddress(Disp.getBlockAddress(), Disp.getOffset() + off, + TargetFlags); } } diff --git a/include/llvm/CodeGen/MachineInstrBundle.h b/include/llvm/CodeGen/MachineInstrBundle.h index b5341fd1ae49..1810d23072d0 100644 --- a/include/llvm/CodeGen/MachineInstrBundle.h +++ b/include/llvm/CodeGen/MachineInstrBundle.h @@ -1,9 +1,8 @@ -//===-- CodeGen/MachineInstBundle.h - MI bundle utilities -------*- C++ -*-===// +//===- llvm/CodeGen/MachineInstrBundle.h - MI bundle utilities --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -62,7 +61,8 @@ inline MachineBasicBlock::instr_iterator getBundleEnd( MachineBasicBlock::instr_iterator I) { while (I->isBundledWithSucc()) ++I; - return ++I; + ++I; + return I; } /// Returns an iterator pointing beyond the bundle containing \p I. @@ -70,7 +70,8 @@ inline MachineBasicBlock::const_instr_iterator getBundleEnd( MachineBasicBlock::const_instr_iterator I) { while (I->isBundledWithSucc()) ++I; - return ++I; + ++I; + return I; } //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineInstrBundleIterator.h b/include/llvm/CodeGen/MachineInstrBundleIterator.h index 5fe4964ff116..0f59563e7e1b 100644 --- a/include/llvm/CodeGen/MachineInstrBundleIterator.h +++ b/include/llvm/CodeGen/MachineInstrBundleIterator.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineInstrBundleIterator.h ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineJumpTableInfo.h b/include/llvm/CodeGen/MachineJumpTableInfo.h index 25a3e6b556a3..11781145b378 100644 --- a/include/llvm/CodeGen/MachineJumpTableInfo.h +++ b/include/llvm/CodeGen/MachineJumpTableInfo.h @@ -1,9 +1,8 @@ //===-- CodeGen/MachineJumpTableInfo.h - Abstract Jump Tables --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index 917fb90380f5..da6df59c739c 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineLoopInfo.h - Natural Loop Calculator -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h index 078ef7ca510c..65f706302bc2 100644 --- a/include/llvm/CodeGen/MachineMemOperand.h +++ b/include/llvm/CodeGen/MachineMemOperand.h @@ -1,9 +1,8 @@ //==- llvm/CodeGen/MachineMemOperand.h - MachineMemOperand class -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,8 +18,6 @@ #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/CodeGen/PseudoSourceValue.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Metadata.h" #include "llvm/IR/Value.h" // PointerLikeTypeTraits<Value*> #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/DataTypes.h" @@ -223,6 +220,9 @@ public: /// Return the size in bytes of the memory reference. uint64_t getSize() const { return Size; } + /// Return the size in bits of the memory reference. + uint64_t getSizeInBits() const { return Size * 8; } + /// Return the minimum known alignment in bytes of the actual memory /// reference. uint64_t getAlignment() const; @@ -267,13 +267,13 @@ public: bool isAtomic() const { return getOrdering() != AtomicOrdering::NotAtomic; } /// Returns true if this memory operation doesn't have any ordering - /// constraints other than normal aliasing. Volatile and atomic memory - /// operations can't be reordered. - /// - /// Currently, we don't model the difference between volatile and atomic - /// operations. They should retain their ordering relative to all memory - /// operations. - bool isUnordered() const { return !isVolatile(); } + /// constraints other than normal aliasing. Volatile and (ordered) atomic + /// memory operations can't be reordered. + bool isUnordered() const { + return (getOrdering() == AtomicOrdering::NotAtomic || + getOrdering() == AtomicOrdering::Unordered) && + !isVolatile(); + } /// Update this MachineMemOperand to reflect the alignment of MMO, if it has a /// greater alignment. This must only be used when the new alignment applies diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 4371420bc7a2..4ff5c7fd013a 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/MachineModuleInfo.h ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -114,10 +113,9 @@ class MachineModuleInfo : public ImmutablePass { /// True if debugging information is available in this module. bool DbgInfoAvailable; - /// True if this module calls VarArg function with floating-point arguments. - /// This is used to emit an undefined reference to _fltused on Windows - /// targets. - bool UsesVAFloatArgument; + /// True if this module is being built for windows/msvc, and uses floating + /// point. This is used to emit an undefined reference to _fltused. + bool UsesMSVCFloatingPoint; /// True if the module calls the __morestack function indirectly, as is /// required under the large code model on x86. This is used to emit @@ -152,6 +150,8 @@ public: bool doInitialization(Module &) override; bool doFinalization(Module &) override; + const LLVMTargetMachine &getTarget() const { return TM; } + const MCContext &getContext() const { return Context; } MCContext &getContext() { return Context; } @@ -187,13 +187,9 @@ public: bool hasDebugInfo() const { return DbgInfoAvailable; } void setDebugInfoAvailability(bool avail) { DbgInfoAvailable = avail; } - bool usesVAFloatArgument() const { - return UsesVAFloatArgument; - } + bool usesMSVCFloatingPoint() const { return UsesMSVCFloatingPoint; } - void setUsesVAFloatArgument(bool b) { - UsesVAFloatArgument = b; - } + void setUsesMSVCFloatingPoint(bool b) { UsesMSVCFloatingPoint = b; } bool usesMorestackAddr() const { return UsesMorestackAddr; @@ -258,14 +254,6 @@ public: /// \} }; // End class MachineModuleInfo -//===- MMI building helpers -----------------------------------------------===// - -/// Determine if any floating-point values are being passed to this variadic -/// function, and set the MachineModuleInfo's usesVAFloatArgument flag if so. -/// This flag is used to emit an undefined reference to _fltused on Windows, -/// which will link in MSVCRT's floating-point support. -void computeUsesVAFloatArgument(const CallInst &I, MachineModuleInfo &MMI); - } // end namespace llvm #endif // LLVM_CODEGEN_MACHINEMODULEINFO_H diff --git a/include/llvm/CodeGen/MachineModuleInfoImpls.h b/include/llvm/CodeGen/MachineModuleInfoImpls.h index 17df1fa792b7..746e92239613 100644 --- a/include/llvm/CodeGen/MachineModuleInfoImpls.h +++ b/include/llvm/CodeGen/MachineModuleInfoImpls.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineModuleInfoImpls.h --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 53e8889d118a..2152c7582e5a 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/MachineOperand.h - MachineOperand class ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -15,6 +14,7 @@ #define LLVM_CODEGEN_MACHINEOPERAND_H #include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/Register.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/LowLevelTypeImpl.h" @@ -346,9 +346,9 @@ public: //===--------------------------------------------------------------------===// /// getReg - Returns the register number. - unsigned getReg() const { + Register getReg() const { assert(isReg() && "This is not a register operand!"); - return SmallContents.RegNo; + return Register(SmallContents.RegNo); } unsigned getSubReg() const { @@ -684,6 +684,11 @@ public: Contents.RegMask = RegMaskPtr; } + void setPredicate(unsigned Predicate) { + assert(isPredicate() && "Wrong MachineOperand mutator"); + Contents.Pred = Predicate; + } + //===--------------------------------------------------------------------===// // Other methods. //===--------------------------------------------------------------------===// @@ -714,6 +719,10 @@ public: /// ChangeToES - Replace this operand with a new external symbol operand. void ChangeToES(const char *SymName, unsigned char TargetFlags = 0); + /// ChangeToGA - Replace this operand with a new global address operand. + void ChangeToGA(const GlobalValue *GV, int64_t Offset, + unsigned char TargetFlags = 0); + /// ChangeToMCSymbol - Replace this operand with a new MC symbol operand. void ChangeToMCSymbol(MCSymbol *Sym); diff --git a/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h b/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h index a7ce870400c2..a461a299917c 100644 --- a/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h +++ b/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h @@ -1,9 +1,8 @@ ///===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*----===// /// -/// The LLVM Compiler Infrastructure -/// -/// This file is distributed under the University of Illinois Open Source -/// License. See LICENSE.TXT for details. +/// 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 /// ///===---------------------------------------------------------------------===// /// \file @@ -159,9 +158,10 @@ public: /// (1) to filter trivial false positives or (2) to provide more context so /// that non-trivial false positives can be quickly detected by the user. bool allowExtraAnalysis(StringRef PassName) const { - return (MF.getFunction().getContext().getDiagnosticsOutputFile() || - MF.getFunction().getContext() - .getDiagHandlerPtr()->isAnyRemarkEnabled(PassName)); + return ( + MF.getFunction().getContext().getRemarkStreamer() || + MF.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled( + PassName)); } /// Take a lambda that returns a remark which will be emitted. Second @@ -172,8 +172,11 @@ public: // remarks enabled. We can't currently check whether remarks are requested // for the calling pass since that requires actually building the remark. - if (MF.getFunction().getContext().getDiagnosticsOutputFile() || - MF.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()) { + if (MF.getFunction().getContext().getRemarkStreamer() || + MF.getFunction() + .getContext() + .getDiagHandlerPtr() + ->isAnyRemarkEnabled()) { auto R = RemarkBuilder(); emit((DiagnosticInfoOptimizationBase &)R); } diff --git a/include/llvm/CodeGen/MachineOutliner.h b/include/llvm/CodeGen/MachineOutliner.h index bfd1e994053a..3868fa415579 100644 --- a/include/llvm/CodeGen/MachineOutliner.h +++ b/include/llvm/CodeGen/MachineOutliner.h @@ -1,9 +1,8 @@ //===---- MachineOutliner.h - Outliner data structures ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -172,13 +171,13 @@ public: /// Represents the size of a sequence in bytes. (Some instructions vary /// widely in size, so just counting the instructions isn't very useful.) - unsigned SequenceSize; + unsigned SequenceSize = 0; /// Target-defined overhead of constructing a frame for this function. - unsigned FrameOverhead; + unsigned FrameOverhead = 0; /// Target-defined identifier for constructing a frame for this function. - unsigned FrameConstructionID; + unsigned FrameConstructionID = 0; /// Return the number of candidates for this \p OutlinedFunction. unsigned getOccurrenceCount() const { return Candidates.size(); } diff --git a/include/llvm/CodeGen/MachinePassRegistry.h b/include/llvm/CodeGen/MachinePassRegistry.h index a031c92d914f..f5b3723db0aa 100644 --- a/include/llvm/CodeGen/MachinePassRegistry.h +++ b/include/llvm/CodeGen/MachinePassRegistry.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachinePassRegistry.h -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachinePipeliner.h b/include/llvm/CodeGen/MachinePipeliner.h index 38cb33e90e63..03ca53072685 100644 --- a/include/llvm/CodeGen/MachinePipeliner.h +++ b/include/llvm/CodeGen/MachinePipeliner.h @@ -1,9 +1,8 @@ //===- MachinePipeliner.h - Machine Software Pipeliner Pass -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -63,6 +62,8 @@ public: const InstrItineraryData *InstrItins; const TargetInstrInfo *TII = nullptr; RegisterClassInfo RegClassInfo; + bool disabledByPragma = false; + unsigned II_setByPragma = 0; #ifndef NDEBUG static int NumTries; @@ -100,6 +101,7 @@ private: bool canPipelineLoop(MachineLoop &L); bool scheduleLoop(MachineLoop &L); bool swingModuloScheduler(MachineLoop &L); + void setPragmaPipelineOptions(MachineLoop &L); }; /// This class builds the dependence graph for the instructions in a loop, @@ -108,11 +110,14 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs { MachinePipeliner &Pass; /// The minimum initiation interval between iterations for this schedule. unsigned MII = 0; + /// The maximum initiation interval between iterations for this schedule. + unsigned MAX_II = 0; /// Set to true if a valid pipelined schedule is found for the loop. bool Scheduled = false; MachineLoop &Loop; LiveIntervals &LIS; const RegisterClassInfo &RegClassInfo; + unsigned II_setByPragma = 0; /// A toplogical ordering of the SUnits, which is needed for changing /// dependences and iterating over the SUnits. @@ -190,9 +195,9 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs { public: SwingSchedulerDAG(MachinePipeliner &P, MachineLoop &L, LiveIntervals &lis, - const RegisterClassInfo &rci) + const RegisterClassInfo &rci, unsigned II) : ScheduleDAGInstrs(*P.MF, P.MLI, false), Pass(P), Loop(L), LIS(lis), - RegClassInfo(rci), Topo(SUnits, &ExitSU) { + RegClassInfo(rci), II_setByPragma(II), Topo(SUnits, &ExitSU) { P.MF->getSubtarget().getSMSMutations(Mutations); if (SwpEnableCopyToPhi) Mutations.push_back(llvm::make_unique<CopyToPhiMutation>()); @@ -253,9 +258,6 @@ public: return 0; } - /// Set the Minimum Initiation Interval for this schedule attempt. - void setMII(unsigned mii) { MII = mii; } - void applyInstrChange(MachineInstr *MI, SMSchedule &Schedule); void fixupRegisterOverlaps(std::deque<SUnit *> &Instrs); @@ -316,9 +318,9 @@ private: MBBVectorTy &EpilogBBs); void splitLifetimes(MachineBasicBlock *KernelBB, MBBVectorTy &EpilogBBs, SMSchedule &Schedule); - void addBranches(MBBVectorTy &PrologBBs, MachineBasicBlock *KernelBB, - MBBVectorTy &EpilogBBs, SMSchedule &Schedule, - ValueMapTy *VRMap); + void addBranches(MachineBasicBlock &PreheaderBB, MBBVectorTy &PrologBBs, + MachineBasicBlock *KernelBB, MBBVectorTy &EpilogBBs, + SMSchedule &Schedule, ValueMapTy *VRMap); bool computeDelta(MachineInstr &MI, unsigned &Delta); void updateMemOperands(MachineInstr &NewMI, MachineInstr &OldMI, unsigned Num); @@ -346,6 +348,10 @@ private: unsigned &OffsetPos, unsigned &NewBase, int64_t &NewOffset); void postprocessDAG(); + /// Set the Minimum Initiation Interval for this schedule attempt. + void setMII(unsigned ResMII, unsigned RecMII); + /// Set the Maximum Initiation Interval for this schedule attempt. + void setMAX_II(); }; /// A NodeSet contains a set of SUnit DAG nodes with additional information @@ -457,6 +463,56 @@ public: #endif }; +// 16 was selected based on the number of ProcResource kinds for all +// existing Subtargets, so that SmallVector don't need to resize too often. +static const int DefaultProcResSize = 16; + +class ResourceManager { +private: + const MCSubtargetInfo *STI; + const MCSchedModel &SM; + const bool UseDFA; + std::unique_ptr<DFAPacketizer> DFAResources; + /// Each processor resource is associated with a so-called processor resource + /// mask. This vector allows to correlate processor resource IDs with + /// processor resource masks. There is exactly one element per each processor + /// resource declared by the scheduling model. + llvm::SmallVector<uint64_t, DefaultProcResSize> ProcResourceMasks; + + llvm::SmallVector<uint64_t, DefaultProcResSize> ProcResourceCount; + +public: + ResourceManager(const TargetSubtargetInfo *ST) + : STI(ST), SM(ST->getSchedModel()), UseDFA(ST->useDFAforSMS()), + ProcResourceMasks(SM.getNumProcResourceKinds(), 0), + ProcResourceCount(SM.getNumProcResourceKinds(), 0) { + if (UseDFA) + DFAResources.reset(ST->getInstrInfo()->CreateTargetScheduleState(*ST)); + initProcResourceVectors(SM, ProcResourceMasks); + } + + void initProcResourceVectors(const MCSchedModel &SM, + SmallVectorImpl<uint64_t> &Masks); + /// Check if the resources occupied by a MCInstrDesc are available in + /// the current state. + bool canReserveResources(const MCInstrDesc *MID) const; + + /// Reserve the resources occupied by a MCInstrDesc and change the current + /// state to reflect that change. + void reserveResources(const MCInstrDesc *MID); + + /// Check if the resources occupied by a machine instruction are available + /// in the current state. + bool canReserveResources(const MachineInstr &MI) const; + + /// Reserve the resources occupied by a machine instruction and change the + /// current state to reflect that change. + void reserveResources(const MachineInstr &MI); + + /// Reset the state + void clearResources(); +}; + /// This class represents the scheduled code. The main data structure is a /// map from scheduled cycle to instructions. During scheduling, the /// data structure explicitly represents all stages/iterations. When @@ -495,12 +551,11 @@ private: /// Virtual register information. MachineRegisterInfo &MRI; - std::unique_ptr<DFAPacketizer> Resources; + ResourceManager ProcItinResources; public: SMSchedule(MachineFunction *mf) - : ST(mf->getSubtarget()), MRI(mf->getRegInfo()), - Resources(ST.getInstrInfo()->CreateTargetScheduleState(ST)) {} + : ST(mf->getSubtarget()), MRI(mf->getRegInfo()), ProcItinResources(&ST) {} void reset() { ScheduledInstrs.clear(); diff --git a/include/llvm/CodeGen/MachinePostDominators.h b/include/llvm/CodeGen/MachinePostDominators.h index c6a41598ce32..b67e6b52ac8f 100644 --- a/include/llvm/CodeGen/MachinePostDominators.h +++ b/include/llvm/CodeGen/MachinePostDominators.h @@ -1,9 +1,8 @@ -//=- llvm/CodeGen/MachineDominators.h ----------------------------*- C++ -*-==// +//===- llvm/CodeGen/MachinePostDominators.h ----------------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineRegionInfo.h b/include/llvm/CodeGen/MachineRegionInfo.h index 8394b58d0a16..6d9fb9b9100a 100644 --- a/include/llvm/CodeGen/MachineRegionInfo.h +++ b/include/llvm/CodeGen/MachineRegionInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineRegionInfo.h -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index fef010a23ef9..b5deed1f5010 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineRegisterInfo.h -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -562,9 +561,14 @@ public: } /// hasOneNonDBGUse - Return true if there is exactly one non-Debug - /// instruction using the specified register. + /// use of the specified register. bool hasOneNonDBGUse(unsigned RegNo) const; + /// hasOneNonDBGUse - Return true if there is exactly one non-Debug + /// instruction using the specified register. Said instruction may have + /// multiple uses. + bool hasOneNonDBGUser(unsigned RegNo) const; + /// replaceRegWith - Replace all instances of FromReg with ToReg in the /// machine function. This is like llvm-level X->replaceAllUsesWith(Y), /// except that it also changes any definitions of the register as well. @@ -713,12 +717,12 @@ public: /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. - unsigned createVirtualRegister(const TargetRegisterClass *RegClass, + Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name = ""); /// Create and return a new virtual register in the function with the same /// attributes as the given register. - unsigned cloneVirtualRegister(unsigned VReg, StringRef Name = ""); + Register cloneVirtualRegister(Register VReg, StringRef Name = ""); /// Get the low-level type of \p Reg or LLT{} if Reg is not a generic /// (target independent) virtual register. @@ -733,7 +737,7 @@ public: /// Create and return a new generic virtual register with low-level /// type \p Ty. - unsigned createGenericVirtualRegister(LLT Ty, StringRef Name = ""); + Register createGenericVirtualRegister(LLT Ty, StringRef Name = ""); /// Remove all types associated to virtual registers (after instruction /// selection and constraining of all generic virtual registers). diff --git a/include/llvm/CodeGen/MachineSSAUpdater.h b/include/llvm/CodeGen/MachineSSAUpdater.h index 5e91246b402c..0319ec774671 100644 --- a/include/llvm/CodeGen/MachineSSAUpdater.h +++ b/include/llvm/CodeGen/MachineSSAUpdater.h @@ -1,9 +1,8 @@ //===- MachineSSAUpdater.h - Unstructured SSA Update Tool -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index 4bc31ae7c61a..75a334f61ad0 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -1,9 +1,8 @@ //===- MachineScheduler.h - MachineInstr Scheduling Pass --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -265,10 +264,6 @@ protected: LiveIntervals *LIS; std::unique_ptr<MachineSchedStrategy> SchedImpl; - /// Topo - A topological ordering for SUnits which permits fast IsReachable - /// and similar queries. - ScheduleDAGTopologicalSort Topo; - /// Ordered list of DAG postprocessing steps. std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations; @@ -292,7 +287,7 @@ public: ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S, bool RemoveKillFlags) : ScheduleDAGInstrs(*C->MF, C->MLI, RemoveKillFlags), AA(C->AA), - LIS(C->LIS), SchedImpl(std::move(S)), Topo(SUnits, &ExitSU) {} + LIS(C->LIS), SchedImpl(std::move(S)) {} // Provide a vtable anchor ~ScheduleDAGMI() override; @@ -320,17 +315,6 @@ public: Mutations.push_back(std::move(Mutation)); } - /// True if an edge can be added from PredSU to SuccSU without creating - /// a cycle. - bool canAddEdge(SUnit *SuccSU, SUnit *PredSU); - - /// Add a DAG edge to the given SU with the given predecessor - /// dependence data. - /// - /// \returns true if the edge may be added without creating a cycle OR if an - /// equivalent edge already existed (false indicates failure). - bool addEdge(SUnit *SuccSU, const SDep &PredDep); - MachineBasicBlock::iterator top() const { return CurrentTop; } MachineBasicBlock::iterator bottom() const { return CurrentBottom; } @@ -682,6 +666,10 @@ private: // scheduled instruction. SmallVector<unsigned, 16> ReservedCycles; + // For each PIdx, stores first index into ReservedCycles that corresponds to + // it. + SmallVector<unsigned, 16> ReservedCyclesIndex; + #ifndef NDEBUG // Remember the greatest possible stall as an upper bound on the number of // times we should retry the pending queue because of a hazard. @@ -756,7 +744,11 @@ public: /// cycle. unsigned getLatencyStallCycles(SUnit *SU); - unsigned getNextResourceCycle(unsigned PIdx, unsigned Cycles); + unsigned getNextResourceCycleByInstance(unsigned InstanceIndex, + unsigned Cycles); + + std::pair<unsigned, unsigned> getNextResourceCycle(unsigned PIdx, + unsigned Cycles); bool checkHazard(SUnit *SU); @@ -1015,6 +1007,7 @@ protected: /// Callbacks from ScheduleDAGMI: /// initPolicy -> initialize(DAG) -> registerRoots -> pickNode ... class PostGenericScheduler : public GenericSchedulerBase { +protected: ScheduleDAGMI *DAG; SchedBoundary Top; SmallVector<SUnit*, 8> BotRoots; diff --git a/include/llvm/CodeGen/MachineTraceMetrics.h b/include/llvm/CodeGen/MachineTraceMetrics.h index 9d8db393ca92..025989504177 100644 --- a/include/llvm/CodeGen/MachineTraceMetrics.h +++ b/include/llvm/CodeGen/MachineTraceMetrics.h @@ -1,9 +1,8 @@ //===- lib/CodeGen/MachineTraceMetrics.h - Super-scalar metrics -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MacroFusion.h b/include/llvm/CodeGen/MacroFusion.h index a77226ddaf33..3a140fe63fde 100644 --- a/include/llvm/CodeGen/MacroFusion.h +++ b/include/llvm/CodeGen/MacroFusion.h @@ -1,9 +1,8 @@ //===- MacroFusion.h - Macro Fusion -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/PBQP/CostAllocator.h b/include/llvm/CodeGen/PBQP/CostAllocator.h index bde451ae1fcc..0d6d8a31317b 100644 --- a/include/llvm/CodeGen/PBQP/CostAllocator.h +++ b/include/llvm/CodeGen/PBQP/CostAllocator.h @@ -1,9 +1,8 @@ //===- CostAllocator.h - PBQP Cost Allocator --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h index a6d88b057dcb..c2cd6dadae5f 100644 --- a/include/llvm/CodeGen/PBQP/Graph.h +++ b/include/llvm/CodeGen/PBQP/Graph.h @@ -1,9 +1,8 @@ //===- Graph.h - PBQP Graph -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/PBQP/Math.h b/include/llvm/CodeGen/PBQP/Math.h index d1432a3053c4..8b014ccbb07b 100644 --- a/include/llvm/CodeGen/PBQP/Math.h +++ b/include/llvm/CodeGen/PBQP/Math.h @@ -1,9 +1,8 @@ //===- Math.h - PBQP Vector and Matrix classes ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/PBQP/ReductionRules.h b/include/llvm/CodeGen/PBQP/ReductionRules.h index 21b99027970d..51822d082bad 100644 --- a/include/llvm/CodeGen/PBQP/ReductionRules.h +++ b/include/llvm/CodeGen/PBQP/ReductionRules.h @@ -1,9 +1,8 @@ //===- ReductionRules.h - Reduction Rules -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/PBQP/Solution.h b/include/llvm/CodeGen/PBQP/Solution.h index 4d4379fbc2c2..d5b1474f0f4c 100644 --- a/include/llvm/CodeGen/PBQP/Solution.h +++ b/include/llvm/CodeGen/PBQP/Solution.h @@ -1,9 +1,8 @@ //===- Solution.h - PBQP Solution -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/PBQPRAConstraint.h b/include/llvm/CodeGen/PBQPRAConstraint.h index 995467dc56d8..876ab97a669f 100644 --- a/include/llvm/CodeGen/PBQPRAConstraint.h +++ b/include/llvm/CodeGen/PBQPRAConstraint.h @@ -1,9 +1,8 @@ -//===- RegAllocPBQP.h -------------------------------------------*- C++ -*-===// +//===- llvm/CodeGen/PBQPRAConstraint.h --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ParallelCG.h b/include/llvm/CodeGen/ParallelCG.h index dbf09ea31e20..a44715d4fc4f 100644 --- a/include/llvm/CodeGen/ParallelCG.h +++ b/include/llvm/CodeGen/ParallelCG.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/ParallelCG.h - Parallel code generation ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index acf1ebb5bc83..d92ee93268e7 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -1,9 +1,8 @@ //===-- Passes.h - Target independent code generation passes ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -346,8 +345,9 @@ namespace llvm { /// pointer or stack pointer index addressing. extern char &LocalStackSlotAllocationID; - /// ExpandISelPseudos - This pass expands pseudo-instructions. - extern char &ExpandISelPseudosID; + /// This pass expands pseudo-instructions, reserves registers and adjusts + /// machine frame information. + extern char &FinalizeISelID; /// UnpackMachineBundles - This pass unpack machine instruction bundles. extern char &UnpackMachineBundlesID; @@ -447,6 +447,9 @@ namespace llvm { /// Creates CFI Instruction Inserter pass. \see CFIInstrInserter.cpp FunctionPass *createCFIInstrInserter(); + /// Create Hardware Loop pass. \see HardwareLoops.cpp + FunctionPass *createHardwareLoopsPass(); + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/PreISelIntrinsicLowering.h b/include/llvm/CodeGen/PreISelIntrinsicLowering.h index b7f83e515b7e..73d7d779e55b 100644 --- a/include/llvm/CodeGen/PreISelIntrinsicLowering.h +++ b/include/llvm/CodeGen/PreISelIntrinsicLowering.h @@ -1,9 +1,8 @@ //===- PreISelIntrinsicLowering.h - Pre-ISel intrinsic lowering pass ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/PseudoSourceValue.h b/include/llvm/CodeGen/PseudoSourceValue.h index f66191bc9fb4..4b3cc9145a13 100644 --- a/include/llvm/CodeGen/PseudoSourceValue.h +++ b/include/llvm/CodeGen/PseudoSourceValue.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/PseudoSourceValue.h ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -16,7 +15,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Value.h" #include "llvm/IR/ValueMap.h" #include <map> @@ -124,7 +122,7 @@ public: bool mayAlias(const MachineFrameInfo *) const override; }; -/// A specialized pseudo soruce value for holding GlobalValue values. +/// A specialized pseudo source value for holding GlobalValue values. class GlobalValuePseudoSourceValue : public CallEntryPseudoSourceValue { const GlobalValue *GV; diff --git a/include/llvm/CodeGen/ReachingDefAnalysis.h b/include/llvm/CodeGen/ReachingDefAnalysis.h index b21b745c8fd1..a599fb62f5e2 100644 --- a/include/llvm/CodeGen/ReachingDefAnalysis.h +++ b/include/llvm/CodeGen/ReachingDefAnalysis.h @@ -1,15 +1,14 @@ //==--- llvm/CodeGen/ReachingDefAnalysis.h - Reaching Def Analysis -*- C++ -*---==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // /// \file Reaching Defs Analysis pass. /// -/// This pass tracks for each instruction what is the “closest” reaching def of +/// This pass tracks for each instruction what is the "closest" reaching def of /// a given register. It is used by BreakFalseDeps (for clearance calculation) /// and ExecutionDomainFix (for arbitrating conflicting domains). /// diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index ba9763077d09..f7f92248f4ce 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -1,9 +1,8 @@ //===- RegAllocPBQP.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/RegAllocRegistry.h b/include/llvm/CodeGen/RegAllocRegistry.h index b518fbb9c9da..9a63674689b3 100644 --- a/include/llvm/CodeGen/RegAllocRegistry.h +++ b/include/llvm/CodeGen/RegAllocRegistry.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/RegAllocRegistry.h --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -23,29 +22,30 @@ class FunctionPass; //===----------------------------------------------------------------------===// /// -/// RegisterRegAlloc class - Track the registration of register allocators. +/// RegisterRegAllocBase class - Track the registration of register allocators. /// //===----------------------------------------------------------------------===// -class RegisterRegAlloc : public MachinePassRegistryNode<FunctionPass *(*)()> { +template <class SubClass> +class RegisterRegAllocBase : public MachinePassRegistryNode<FunctionPass *(*)()> { public: using FunctionPassCtor = FunctionPass *(*)(); static MachinePassRegistry<FunctionPassCtor> Registry; - RegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C) + RegisterRegAllocBase(const char *N, const char *D, FunctionPassCtor C) : MachinePassRegistryNode(N, D, C) { Registry.Add(this); } - ~RegisterRegAlloc() { Registry.Remove(this); } + ~RegisterRegAllocBase() { Registry.Remove(this); } // Accessors. - RegisterRegAlloc *getNext() const { - return (RegisterRegAlloc *)MachinePassRegistryNode::getNext(); + SubClass *getNext() const { + return static_cast<SubClass *>(MachinePassRegistryNode::getNext()); } - static RegisterRegAlloc *getList() { - return (RegisterRegAlloc *)Registry.getList(); + static SubClass *getList() { + return static_cast<SubClass *>(Registry.getList()); } static FunctionPassCtor getDefault() { return Registry.getDefault(); } @@ -57,6 +57,17 @@ public: } }; +class RegisterRegAlloc : public RegisterRegAllocBase<RegisterRegAlloc> { +public: + RegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C) + : RegisterRegAllocBase(N, D, C) {} +}; + +/// RegisterRegAlloc's global Registry tracks allocator registration. +template <class T> +MachinePassRegistry<RegisterRegAlloc::FunctionPassCtor> +RegisterRegAllocBase<T>::Registry; + } // end namespace llvm #endif // LLVM_CODEGEN_REGALLOCREGISTRY_H diff --git a/include/llvm/CodeGen/Register.h b/include/llvm/CodeGen/Register.h new file mode 100644 index 000000000000..907c1a99e56f --- /dev/null +++ b/include/llvm/CodeGen/Register.h @@ -0,0 +1,60 @@ +//===-- llvm/CodeGen/Register.h ---------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REGISTER_H +#define LLVM_CODEGEN_REGISTER_H + +#include <cassert> + +namespace llvm { + +/// Wrapper class representing virtual and physical registers. Should be passed +/// by value. +class Register { + unsigned Reg; + +public: + Register(unsigned Val = 0): Reg(Val) {} + + /// Return true if the specified register number is in the virtual register + /// namespace. + bool isVirtual() const { + return int(Reg) < 0; + } + + /// Return true if the specified register number is in the physical register + /// namespace. + bool isPhysical() const { + return int(Reg) > 0; + } + + /// Convert a virtual register number to a 0-based index. The first virtual + /// register in a function will get the index 0. + unsigned virtRegIndex() const { + assert(isVirtual() && "Not a virtual register"); + return Reg & ~(1u << 31); + } + + /// Convert a 0-based index to a virtual register number. + /// This is the inverse operation of VirtReg2IndexFunctor below. + static Register index2VirtReg(unsigned Index) { + return Register(Index | (1u << 31)); + } + + operator unsigned() const { + return Reg; + } + + bool isValid() const { + return Reg != 0; + } +}; + +} + +#endif diff --git a/include/llvm/CodeGen/RegisterClassInfo.h b/include/llvm/CodeGen/RegisterClassInfo.h index 97113c575815..14af5c4d090d 100644 --- a/include/llvm/CodeGen/RegisterClassInfo.h +++ b/include/llvm/CodeGen/RegisterClassInfo.h @@ -1,9 +1,8 @@ //===- RegisterClassInfo.h - Dynamic Register Class Info --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index 79054b9e33b7..5bbaa03fd751 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -1,9 +1,8 @@ //===- RegisterPressure.h - Dynamic Register Pressure -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -132,10 +131,6 @@ public: } }; -template <> struct isPodLike<PressureChange> { - static const bool value = true; -}; - /// List of PressureChanges in order of increasing, unique PSetID. /// /// Use a small fixed number, because we can fit more PressureChanges in an diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index b6bd028a8cac..9c48df82f07d 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -1,9 +1,8 @@ //===- RegisterScavenging.h - Machine register scavenging -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -158,10 +157,15 @@ public: /// Returns the scavenged register. /// This is deprecated as it depends on the quality of the kill flags being /// present; Use scavengeRegisterBackwards() instead! + /// + /// If \p AllowSpill is false, fail if a spill is required to make the + /// register available, and return NoRegister. unsigned scavengeRegister(const TargetRegisterClass *RC, - MachineBasicBlock::iterator I, int SPAdj); - unsigned scavengeRegister(const TargetRegisterClass *RegClass, int SPAdj) { - return scavengeRegister(RegClass, MBBI, SPAdj); + MachineBasicBlock::iterator I, int SPAdj, + bool AllowSpill = true); + unsigned scavengeRegister(const TargetRegisterClass *RegClass, int SPAdj, + bool AllowSpill = true) { + return scavengeRegister(RegClass, MBBI, SPAdj, AllowSpill); } /// Make a register of the specific register class available from the current @@ -170,9 +174,13 @@ public: /// SPAdj is the stack adjustment due to call frame, it's passed along to /// eliminateFrameIndex(). /// Returns the scavenged register. + /// + /// If \p AllowSpill is false, fail if a spill is required to make the + /// register available, and return NoRegister. unsigned scavengeRegisterBackwards(const TargetRegisterClass &RC, MachineBasicBlock::iterator To, - bool RestoreAfter, int SPAdj); + bool RestoreAfter, int SPAdj, + bool AllowSpill = true); /// Tell the scavenger a register is used. void setRegUsed(unsigned Reg, LaneBitmask LaneMask = LaneBitmask::getAll()); diff --git a/include/llvm/CodeGen/RegisterUsageInfo.h b/include/llvm/CodeGen/RegisterUsageInfo.h index efecc61d9c30..33554550b9dc 100644 --- a/include/llvm/CodeGen/RegisterUsageInfo.h +++ b/include/llvm/CodeGen/RegisterUsageInfo.h @@ -1,9 +1,8 @@ //==- RegisterUsageInfo.h - Register Usage Informartion Storage --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// \file diff --git a/include/llvm/CodeGen/ResourcePriorityQueue.h b/include/llvm/CodeGen/ResourcePriorityQueue.h index 8d582ee298b6..81587a3170ce 100644 --- a/include/llvm/CodeGen/ResourcePriorityQueue.h +++ b/include/llvm/CodeGen/ResourcePriorityQueue.h @@ -1,9 +1,8 @@ //===----- ResourcePriorityQueue.h - A DFA-oriented priority queue -------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index 28567a1ce437..f71f39e5bf03 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -1,9 +1,8 @@ //===-- CodeGen/RuntimeLibcalls.h - Runtime Library Calls -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/SDNodeProperties.td b/include/llvm/CodeGen/SDNodeProperties.td index 83bbab2fdc8d..d25e0bda26a9 100644 --- a/include/llvm/CodeGen/SDNodeProperties.td +++ b/include/llvm/CodeGen/SDNodeProperties.td @@ -1,9 +1,8 @@ //===- SDNodeProperties.td - Common code for DAG isels ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 0870d67db390..e004f3bf2cc1 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/ScheduleDAG.h - Common Base Class -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -239,9 +238,6 @@ class TargetRegisterInfo; void dump(const TargetRegisterInfo *TRI = nullptr) const; }; - template <> - struct isPodLike<SDep> { static const bool value = true; }; - /// Scheduling unit. This is a node in the scheduling DAG. class SUnit { private: @@ -418,7 +414,7 @@ class TargetRegisterInfo; /// dirty. void setDepthToAtLeast(unsigned NewDepth); - /// If NewDepth is greater than this node's depth value, set it to be + /// If NewHeight is greater than this node's height value, set it to be /// the new height value. This also recursively marks predecessor nodes /// dirty. void setHeightToAtLeast(unsigned NewHeight); @@ -695,6 +691,12 @@ class TargetRegisterInfo; std::vector<SUnit> &SUnits; SUnit *ExitSU; + // Have any new nodes been added? + bool Dirty = false; + + // Outstanding added edges, that have not been applied to the ordering. + SmallVector<std::pair<SUnit *, SUnit *>, 16> Updates; + /// Maps topological index to the node number. std::vector<int> Index2Node; /// Maps the node number to its topological index. @@ -714,6 +716,11 @@ class TargetRegisterInfo; /// Assigns the topological index to the node n. void Allocate(int n, int index); + /// Fix the ordering, by either recomputing from scratch or by applying + /// any outstanding updates. Uses a heuristic to estimate what will be + /// cheaper. + void FixOrder(); + public: ScheduleDAGTopologicalSort(std::vector<SUnit> &SUnits, SUnit *ExitSU); @@ -738,11 +745,19 @@ class TargetRegisterInfo; /// added from SUnit \p X to SUnit \p Y. void AddPred(SUnit *Y, SUnit *X); + /// Queues an update to the topological ordering to accommodate an edge to + /// be added from SUnit \p X to SUnit \p Y. + void AddPredQueued(SUnit *Y, SUnit *X); + /// Updates the topological ordering to accommodate an an edge to be /// removed from the specified node \p N from the predecessors of the /// current node \p M. void RemovePred(SUnit *M, SUnit *N); + /// Mark the ordering as temporarily broken, after a new node has been + /// added. + void MarkDirty() { Dirty = true; } + typedef std::vector<int>::iterator iterator; typedef std::vector<int>::const_iterator const_iterator; iterator begin() { return Index2Node.begin(); } diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index daad18125db9..3e3b604acbac 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -1,9 +1,8 @@ //===- ScheduleDAGInstrs.h - MachineInstr Scheduling ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -235,6 +234,11 @@ namespace llvm { /// For an unanalyzable memory access, this Value is used in maps. UndefValue *UnknownValue; + + /// Topo - A topological ordering for SUnits which permits fast IsReachable + /// and similar queries. + ScheduleDAGTopologicalSort Topo; + using DbgValueVector = std::vector<std::pair<MachineInstr *, MachineInstr *>>; /// Remember instruction that precedes DBG_VALUE. @@ -339,6 +343,17 @@ namespace llvm { /// Fixes register kill flags that scheduling has made invalid. void fixupKills(MachineBasicBlock &MBB); + /// True if an edge can be added from PredSU to SuccSU without creating + /// a cycle. + bool canAddEdge(SUnit *SuccSU, SUnit *PredSU); + + /// Add a DAG edge to the given SU with the given predecessor + /// dependence data. + /// + /// \returns true if the edge may be added without creating a cycle OR if an + /// equivalent edge already existed (false indicates failure). + bool addEdge(SUnit *SuccSU, const SDep &PredDep); + protected: void initSUnits(); void addPhysRegDataDeps(SUnit *SU, unsigned OperIdx); diff --git a/include/llvm/CodeGen/ScheduleDAGMutation.h b/include/llvm/CodeGen/ScheduleDAGMutation.h index 5c236427e0b8..d1dd72859a38 100644 --- a/include/llvm/CodeGen/ScheduleDAGMutation.h +++ b/include/llvm/CodeGen/ScheduleDAGMutation.h @@ -1,9 +1,8 @@ //===- ScheduleDAGMutation.h - MachineInstr Scheduling ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ScheduleDFS.h b/include/llvm/CodeGen/ScheduleDFS.h index 3ecc033ac35a..d60deab95f5d 100644 --- a/include/llvm/CodeGen/ScheduleDFS.h +++ b/include/llvm/CodeGen/ScheduleDFS.h @@ -1,9 +1,8 @@ -//===- ScheduleDAGILP.h - ILP metric for ScheduleDAGInstrs ------*- C++ -*-===// +//===- ScheduleDFS.h - ILP metric for ScheduleDAGInstrs ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/include/llvm/CodeGen/ScheduleHazardRecognizer.h index ace4a2d836ca..37590f496ca2 100644 --- a/include/llvm/CodeGen/ScheduleHazardRecognizer.h +++ b/include/llvm/CodeGen/ScheduleHazardRecognizer.h @@ -1,9 +1,8 @@ //=- llvm/CodeGen/ScheduleHazardRecognizer.h - Scheduling Support -*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/SchedulerRegistry.h b/include/llvm/CodeGen/SchedulerRegistry.h index fbe559f25556..0ccfaafd9e50 100644 --- a/include/llvm/CodeGen/SchedulerRegistry.h +++ b/include/llvm/CodeGen/SchedulerRegistry.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/SchedulerRegistry.h -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h index 3f75d108f282..ac67f3008fa7 100644 --- a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h +++ b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h @@ -1,9 +1,8 @@ //=- llvm/CodeGen/ScoreboardHazardRecognizer.h - Schedule Support -*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 67fe87fc96af..12a970847021 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/SelectionDAG.h - InstSelection DAG ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -268,6 +267,10 @@ class SelectionDAG { /// Tracks dbg_value and dbg_label information through SDISel. SDDbgInfo *DbgInfo; + using CallSiteInfo = MachineFunction::CallSiteInfo; + using CallSiteInfoImpl = MachineFunction::CallSiteInfoImpl; + DenseMap<const SDNode *, CallSiteInfo> SDCallSiteInfo; + uint16_t NextPersistentId = 0; public: @@ -298,6 +301,9 @@ public: /// The node N that was updated. virtual void NodeUpdated(SDNode *N); + + /// The node N that was inserted. + virtual void NodeInserted(SDNode *N); }; struct DAGNodeDeletedListener : public DAGUpdateListener { @@ -404,6 +410,7 @@ public: const TargetLowering &getTargetLoweringInfo() const { return *TLI; } const TargetLibraryInfo &getLibInfo() const { return *LibInfo; } const SelectionDAGTargetInfo &getSelectionDAGInfo() const { return *TSI; } + const LegacyDivergenceAnalysis *getDivergenceAnalysis() const { return DA; } LLVMContext *getContext() const {return Context; } OptimizationRemarkEmitter &getORE() const { return *ORE; } @@ -573,6 +580,9 @@ public: bool isTarget = false, bool isOpaque = false); SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget = false); + SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL, + bool LegalTypes = true); + SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque = false) { return getConstant(Val, DL, VT, true, isOpaque); @@ -789,6 +799,16 @@ public: /// value assuming it was the smaller SrcTy value. SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT); + /// Convert Op, which must be of integer type, to the integer type VT, by + /// either truncating it or performing either zero or sign extension as + /// appropriate extension for the pointer's semantics. + SDValue getPtrExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT); + + /// Return the expression required to extend the Op as a pointer value + /// assuming it was the smaller SrcTy value. This may be either a zero extend + /// or a sign extend. + SDValue getPtrExtendInReg(SDValue Op, const SDLoc &DL, EVT VT); + /// Convert Op, which must be of integer type, to the integer type VT, /// by using an extension appropriate for the target's /// BooleanContent for type OpVT or truncating it. @@ -971,6 +991,10 @@ public: /// Try to simplify a shift into 1 of its operands or a constant. SDValue simplifyShift(SDValue X, SDValue Y); + /// Try to simplify a floating-point binary operation into 1 of its operands + /// or a constant. + SDValue simplifyFPBinop(unsigned Opcode, SDValue X, SDValue Y); + /// VAArg produces a result and token chain, and takes a pointer /// and a source value as input. SDValue getVAArg(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, @@ -982,21 +1006,11 @@ public: /// a success flag (initially i1), and a chain. SDValue getAtomicCmpSwap(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDVTList VTs, SDValue Chain, SDValue Ptr, - SDValue Cmp, SDValue Swp, MachinePointerInfo PtrInfo, - unsigned Alignment, AtomicOrdering SuccessOrdering, - AtomicOrdering FailureOrdering, - SyncScope::ID SSID); - SDValue getAtomicCmpSwap(unsigned Opcode, const SDLoc &dl, EVT MemVT, - SDVTList VTs, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, MachineMemOperand *MMO); /// Gets a node for an atomic op, produces result (if relevant) /// and chain and takes 2 operands. SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, - SDValue Ptr, SDValue Val, const Value *PtrVal, - unsigned Alignment, AtomicOrdering Ordering, - SyncScope::ID SSID); - SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO); /// Gets a node for an atomic op, produces result and chain and @@ -1021,12 +1035,19 @@ public: unsigned Align = 0, MachineMemOperand::Flags Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore, - unsigned Size = 0); + unsigned Size = 0, + const AAMDNodes &AAInfo = AAMDNodes()); SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef<SDValue> Ops, EVT MemVT, MachineMemOperand *MMO); + /// Creates a LifetimeSDNode that starts (`IsStart==true`) or ends + /// (`IsStart==false`) the lifetime of the portion of `FrameIndex` between + /// offsets `Offset` and `Offset + Size`. + SDValue getLifetimeNode(bool IsStart, const SDLoc &dl, SDValue Chain, + int FrameIndex, int64_t Size, int64_t Offset = -1); + /// Create a MERGE_VALUES node from the given operands. SDValue getMergeValues(ArrayRef<SDValue> Ops, const SDLoc &dl); @@ -1154,6 +1175,11 @@ public: SDValue Op3, SDValue Op4, SDValue Op5); SDNode *UpdateNodeOperands(SDNode *N, ArrayRef<SDValue> Ops); + /// Creates a new TokenFactor containing \p Vals. If \p Vals contains 64k + /// values or more, move values into new TokenFactors in 64k-1 blocks, until + /// the final TokenFactor has less than 64k operands. + SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl<SDValue> &Vals); + /// *Mutate* the specified machine node's memory references to the provided /// list. void setNodeMemRefs(MachineSDNode *N, @@ -1358,21 +1384,20 @@ public: /// with this SelectionDAG. bool hasDebugValues() const { return !DbgInfo->empty(); } - SDDbgInfo::DbgIterator DbgBegin() { return DbgInfo->DbgBegin(); } - SDDbgInfo::DbgIterator DbgEnd() { return DbgInfo->DbgEnd(); } + SDDbgInfo::DbgIterator DbgBegin() const { return DbgInfo->DbgBegin(); } + SDDbgInfo::DbgIterator DbgEnd() const { return DbgInfo->DbgEnd(); } - SDDbgInfo::DbgIterator ByvalParmDbgBegin() { + SDDbgInfo::DbgIterator ByvalParmDbgBegin() const { return DbgInfo->ByvalParmDbgBegin(); } - - SDDbgInfo::DbgIterator ByvalParmDbgEnd() { + SDDbgInfo::DbgIterator ByvalParmDbgEnd() const { return DbgInfo->ByvalParmDbgEnd(); } - SDDbgInfo::DbgLabelIterator DbgLabelBegin() { + SDDbgInfo::DbgLabelIterator DbgLabelBegin() const { return DbgInfo->DbgLabelBegin(); } - SDDbgInfo::DbgLabelIterator DbgLabelEnd() { + SDDbgInfo::DbgLabelIterator DbgLabelEnd() const { return DbgInfo->DbgLabelEnd(); } @@ -1395,27 +1420,42 @@ public: const SDNode *N2); SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, - SDNode *Cst1, SDNode *Cst2); + SDNode *N1, SDNode *N2); SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, - const ConstantSDNode *Cst1, - const ConstantSDNode *Cst2); + const ConstantSDNode *C1, + const ConstantSDNode *C2); SDValue FoldConstantVectorArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef<SDValue> Ops, const SDNodeFlags Flags = SDNodeFlags()); + /// Fold floating-point operations with 2 operands when both operands are + /// constants and/or undefined. + SDValue foldConstantFPMath(unsigned Opcode, const SDLoc &DL, EVT VT, + SDValue N1, SDValue N2); + /// Constant fold a setcc to true or false. SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, const SDLoc &dl); - /// See if the specified operand can be simplified with the knowledge that only - /// the bits specified by Mask are used. If so, return the simpler operand, - /// otherwise return a null SDValue. + /// See if the specified operand can be simplified with the knowledge that + /// only the bits specified by DemandedBits are used. If so, return the + /// simpler operand, otherwise return a null SDValue. + /// + /// (This exists alongside SimplifyDemandedBits because GetDemandedBits can + /// simplify nodes with multiple uses more aggressively.) + SDValue GetDemandedBits(SDValue V, const APInt &DemandedBits); + + /// See if the specified operand can be simplified with the knowledge that + /// only the bits specified by DemandedBits are used in the elements specified + /// by DemandedElts. If so, return the simpler operand, otherwise return a + /// null SDValue. /// /// (This exists alongside SimplifyDemandedBits because GetDemandedBits can /// simplify nodes with multiple uses more aggressively.) - SDValue GetDemandedBits(SDValue V, const APInt &Mask); + SDValue GetDemandedBits(SDValue V, const APInt &DemandedBits, + const APInt &DemandedElts); /// Return true if the sign bit of Op is known to be zero. /// We use this predicate to simplify operations downstream. @@ -1424,8 +1464,19 @@ public: /// Return true if 'Op & Mask' is known to be zero. We /// use this predicate to simplify operations downstream. Op and Mask are /// known to be the same type. - bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth = 0) - const; + bool MaskedValueIsZero(SDValue Op, const APInt &Mask, + unsigned Depth = 0) const; + + /// Return true if 'Op & Mask' is known to be zero in DemandedElts. We + /// use this predicate to simplify operations downstream. Op and Mask are + /// known to be the same type. + bool MaskedValueIsZero(SDValue Op, const APInt &Mask, + const APInt &DemandedElts, unsigned Depth = 0) const; + + /// Return true if '(Op & Mask) == Mask'. + /// Op and Mask are known to be the same type. + bool MaskedValueIsAllOnes(SDValue Op, const APInt &Mask, + unsigned Depth = 0) const; /// Determine which bits of Op are known to be either zero or one and return /// them in Known. For vectors, the known bits are those that are shared by @@ -1525,6 +1576,13 @@ public: /// Test whether \p V has a splatted value. bool isSplatValue(SDValue V, bool AllowUndefs = false); + /// If V is a splatted value, return the source vector and its splat index. + SDValue getSplatSourceVector(SDValue V, int &SplatIndex); + + /// If V is a splat vector, return its scalar source operand by extracting + /// that element from the source vector. + SDValue getSplatValue(SDValue V); + /// Match a binop + shuffle pyramid that represents a horizontal reduction /// over the elements of a vector starting from the EXTRACT_VECTOR_ELT node /p /// Extract. The reduction must use one of the opcodes listed in /p @@ -1542,6 +1600,11 @@ public: /// vector op and fill the end of the resulting vector with UNDEFS. SDValue UnrollVectorOp(SDNode *N, unsigned ResNE = 0); + /// Like UnrollVectorOp(), but for the [US](ADD|SUB|MUL)O family of opcodes. + /// This is a separate function because those opcodes have two results. + std::pair<SDValue, SDValue> UnrollVectorOverflowOp(SDNode *N, + unsigned ResNE = 0); + /// Return true if loads are next to each other and can be /// merged. Check that both are nonvolatile and if LD is loading /// 'Bytes' bytes from a location that is 'Dist' units away from the @@ -1576,6 +1639,9 @@ public: return SplitVector(N->getOperand(OpNo), SDLoc(N)); } + /// Widen the vector up to the next power of two using INSERT_SUBVECTOR. + SDValue WidenVector(const SDValue &N, const SDLoc &DL); + /// Append the extracted elements from Start to Count out of the vector Op /// in Args. If Count is 0, all of the elements will be extracted. void ExtractVectorElements(SDValue Op, SmallVectorImpl<SDValue> &Args, @@ -1597,6 +1663,17 @@ public: isConstantFPBuildVectorOrConstantFP(N); } + void addCallSiteInfo(const SDNode *CallNode, CallSiteInfoImpl &&CallInfo) { + SDCallSiteInfo[CallNode] = std::move(CallInfo); + } + + CallSiteInfo getSDCallSiteInfo(const SDNode *CallNode) { + auto I = SDCallSiteInfo.find(CallNode); + if (I != SDCallSiteInfo.end()) + return std::move(I->second); + return CallSiteInfo(); + } + private: void InsertNode(SDNode *N); bool RemoveNodeFromCSEMaps(SDNode *N); diff --git a/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h b/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h index 2b2c48d57bc0..4ee58333495b 100644 --- a/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h +++ b/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h @@ -1,9 +1,8 @@ //===- SelectionDAGAddressAnalysis.h - DAG Address Analysis -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -34,11 +33,13 @@ class BaseIndexOffset { private: SDValue Base; SDValue Index; - int64_t Offset = 0; + Optional<int64_t> Offset; bool IsIndexSignExt = false; public: BaseIndexOffset() = default; + BaseIndexOffset(SDValue Base, SDValue Index, bool IsIndexSignExt) + : Base(Base), Index(Index), Offset(), IsIndexSignExt(IsIndexSignExt) {} BaseIndexOffset(SDValue Base, SDValue Index, int64_t Offset, bool IsIndexSignExt) : Base(Base), Index(Index), Offset(Offset), @@ -48,6 +49,13 @@ public: SDValue getBase() const { return Base; } SDValue getIndex() { return Index; } SDValue getIndex() const { return Index; } + bool hasValidOffset() const { return Offset.hasValue(); } + + // Returns true if `Other` and `*this` are both some offset from the same base + // pointer. In that case, `Off` is set to the offset between `*this` and + // `Other` (negative if `Other` is before `*this`). + bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG, + int64_t &Off) const; bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG) const { @@ -55,11 +63,31 @@ public: return equalBaseIndex(Other, DAG, Off); } - bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG, - int64_t &Off) const; + // Returns true if `Other` (with size `OtherSize`) can be proven to be fully + // contained in `*this` (with size `Size`). + bool contains(const SelectionDAG &DAG, int64_t BitSize, + const BaseIndexOffset &Other, int64_t OtherBitSize, + int64_t &BitOffset) const; + + bool contains(const SelectionDAG &DAG, int64_t BitSize, + const BaseIndexOffset &Other, int64_t OtherBitSize) const { + int64_t BitOffset; + return contains(DAG, BitSize, Other, OtherBitSize, BitOffset); + } + + // Returns true `Op0` and `Op1` can be proven to alias/not alias, in + // which case `IsAlias` is set to true/false. + static bool computeAliasing(const SDNode *Op0, + const Optional<int64_t> NumBytes0, + const SDNode *Op1, + const Optional<int64_t> NumBytes1, + const SelectionDAG &DAG, bool &IsAlias); + + /// Parses tree in N for base, index, offset addresses. + static BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG); - /// Parses tree in Ptr for base, index, offset addresses. - static BaseIndexOffset match(const LSBaseSDNode *N, const SelectionDAG &DAG); + void print(raw_ostream& OS) const; + void dump() const; }; } // end namespace llvm diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 6758c55c696a..147c325342fc 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/SelectionDAGISel.h - Common Base Class------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -35,6 +34,7 @@ namespace llvm { class TargetLibraryInfo; class FunctionLoweringInfo; class ScheduleHazardRecognizer; + class SwiftErrorValueTracking; class GCFunctionInfo; class ScheduleDAGSDNodes; class LoadInst; @@ -46,6 +46,7 @@ public: TargetMachine &TM; const TargetLibraryInfo *LibInfo; FunctionLoweringInfo *FuncInfo; + SwiftErrorValueTracking *SwiftError; MachineFunction *MF; MachineRegisterInfo *RegInfo; SelectionDAG *CurDAG; @@ -144,10 +145,12 @@ public: OPC_CheckInteger, OPC_CheckChild0Integer, OPC_CheckChild1Integer, OPC_CheckChild2Integer, OPC_CheckChild3Integer, OPC_CheckChild4Integer, - OPC_CheckCondCode, + OPC_CheckCondCode, OPC_CheckChild2CondCode, OPC_CheckValueType, OPC_CheckComplexPat, OPC_CheckAndImm, OPC_CheckOrImm, + OPC_CheckImmAllOnesV, + OPC_CheckImmAllZerosV, OPC_CheckFoldableChainNode, OPC_EmitInteger, @@ -303,7 +306,7 @@ public: private: // Calls to these functions are generated by tblgen. - void Select_INLINEASM(SDNode *N); + void Select_INLINEASM(SDNode *N, bool Branch); void Select_READ_REGISTER(SDNode *Op); void Select_WRITE_REGISTER(SDNode *Op); void Select_UNDEF(SDNode *N); diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 10f284179084..5aab9643e09d 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/SelectionDAGNodes.h - SelectionDAG Nodes ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -184,6 +183,7 @@ public: inline unsigned getNumOperands() const; inline const SDValue &getOperand(unsigned i) const; inline uint64_t getConstantOperandVal(unsigned i) const; + inline const APInt &getConstantOperandAPInt(unsigned i) const; inline bool isTargetMemoryOpcode() const; inline bool isTargetOpcode() const; inline bool isMachineOpcode() const; @@ -232,7 +232,6 @@ template<> struct DenseMapInfo<SDValue> { return LHS == RHS; } }; -template <> struct isPodLike<SDValue> { static const bool value = true; }; /// Allow casting operators to work directly on /// SDValues as if they were SDNode*'s. @@ -369,6 +368,13 @@ private: bool ApproximateFuncs : 1; bool AllowReassociation : 1; + // We assume instructions do not raise floating-point exceptions by default, + // and only those marked explicitly may do so. We could choose to represent + // this via a positive "FPExcept" flags like on the MI level, but having a + // negative "NoFPExcept" flag here (that defaults to true) makes the flag + // intersection logic more straightforward. + bool NoFPExcept : 1; + public: /// Default constructor turns off all optimization flags. SDNodeFlags() @@ -376,7 +382,7 @@ public: Exact(false), NoNaNs(false), NoInfs(false), NoSignedZeros(false), AllowReciprocal(false), VectorReduction(false), AllowContract(false), ApproximateFuncs(false), - AllowReassociation(false) {} + AllowReassociation(false), NoFPExcept(true) {} /// Propagate the fast-math-flags from an IR FPMathOperator. void copyFMF(const FPMathOperator &FPMO) { @@ -439,6 +445,10 @@ public: setDefined(); AllowReassociation = b; } + void setFPExcept(bool b) { + setDefined(); + NoFPExcept = !b; + } // These are accessors for each flag. bool hasNoUnsignedWrap() const { return NoUnsignedWrap; } @@ -452,9 +462,10 @@ public: bool hasAllowContract() const { return AllowContract; } bool hasApproximateFuncs() const { return ApproximateFuncs; } bool hasAllowReassociation() const { return AllowReassociation; } + bool hasFPExcept() const { return !NoFPExcept; } bool isFast() const { - return NoSignedZeros && AllowReciprocal && NoNaNs && NoInfs && + return NoSignedZeros && AllowReciprocal && NoNaNs && NoInfs && NoFPExcept && AllowContract && ApproximateFuncs && AllowReassociation; } @@ -474,6 +485,7 @@ public: AllowContract &= Flags.AllowContract; ApproximateFuncs &= Flags.ApproximateFuncs; AllowReassociation &= Flags.AllowReassociation; + NoFPExcept &= Flags.NoFPExcept; } }; @@ -489,6 +501,17 @@ protected: // SubclassData. These are designed to fit within a uint16_t so they pack // with NodeType. +#if defined(_AIX) && (!defined(__GNUC__) || defined(__ibmxl__)) +// Except for GCC; by default, AIX compilers store bit-fields in 4-byte words +// and give the `pack` pragma push semantics. +#define BEGIN_TWO_BYTE_PACK() _Pragma("pack(2)") +#define END_TWO_BYTE_PACK() _Pragma("pack(pop)") +#else +#define BEGIN_TWO_BYTE_PACK() +#define END_TWO_BYTE_PACK() +#endif + +BEGIN_TWO_BYTE_PACK() class SDNodeBitfields { friend class SDNode; friend class MemIntrinsicSDNode; @@ -561,6 +584,9 @@ protected: LoadSDNodeBitfields LoadSDNodeBits; StoreSDNodeBitfields StoreSDNodeBits; }; +END_TWO_BYTE_PACK() +#undef BEGIN_TWO_BYTE_PACK +#undef END_TWO_BYTE_PACK // RawSDNodeBits must cover the entirety of the union. This means that all of // the union's members must have size <= RawSDNodeBits. We write the RHS as @@ -678,6 +704,8 @@ public: case ISD::STRICT_FFLOOR: case ISD::STRICT_FROUND: case ISD::STRICT_FTRUNC: + case ISD::STRICT_FP_ROUND: + case ISD::STRICT_FP_EXTEND: return true; } } @@ -898,9 +926,17 @@ public: /// Return the number of values used by this operation. unsigned getNumOperands() const { return NumOperands; } + /// Return the maximum number of operands that a SDNode can hold. + static constexpr size_t getMaxNumOperands() { + return std::numeric_limits<decltype(SDNode::NumOperands)>::max(); + } + /// Helper method returns the integer value of a ConstantSDNode operand. inline uint64_t getConstantOperandVal(unsigned Num) const; + /// Helper method returns the APInt of a ConstantSDNode operand. + inline const APInt &getConstantOperandAPInt(unsigned Num) const; + const SDValue &getOperand(unsigned Num) const { assert(Num < NumOperands && "Invalid child # of SDNode!"); return OperandList[Num]; @@ -1128,6 +1164,10 @@ inline uint64_t SDValue::getConstantOperandVal(unsigned i) const { return Node->getConstantOperandVal(i); } +inline const APInt &SDValue::getConstantOperandAPInt(unsigned i) const { + return Node->getConstantOperandAPInt(i); +} + inline bool SDValue::isTargetOpcode() const { return Node->isTargetOpcode(); } @@ -1356,6 +1396,8 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_MAX || N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || + N->getOpcode() == ISD::ATOMIC_LOAD_FADD || + N->getOpcode() == ISD::ATOMIC_LOAD_FSUB || N->getOpcode() == ISD::ATOMIC_LOAD || N->getOpcode() == ISD::ATOMIC_STORE || N->getOpcode() == ISD::MLOAD || @@ -1372,7 +1414,10 @@ class AtomicSDNode : public MemSDNode { public: AtomicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTL, EVT MemVT, MachineMemOperand *MMO) - : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {} + : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { + assert(((Opc != ISD::ATOMIC_LOAD && Opc != ISD::ATOMIC_STORE) || + MMO->isAtomic()) && "then why are we using an AtomicSDNode?"); + } const SDValue &getBasePtr() const { return getOperand(1); } const SDValue &getVal() const { return getOperand(2); } @@ -1408,6 +1453,8 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_MAX || N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || + N->getOpcode() == ISD::ATOMIC_LOAD_FADD || + N->getOpcode() == ISD::ATOMIC_LOAD_FSUB || N->getOpcode() == ISD::ATOMIC_LOAD || N->getOpcode() == ISD::ATOMIC_STORE; } @@ -1467,14 +1514,16 @@ public: bool isSplat() const { return isSplatMask(Mask, getValueType(0)); } - int getSplatIndex() const { + int getSplatIndex() const { assert(isSplat() && "Cannot get splat index for non-splat!"); EVT VT = getValueType(0); - for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { + for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) if (Mask[i] >= 0) return Mask[i]; - } - llvm_unreachable("Splat with all undef indices?"); + + // We can choose any index value here and be correct because all elements + // are undefined. Return 0 for better potential for callers to simplify. + return 0; } static bool isSplatMask(const int *Mask, EVT VT); @@ -1536,6 +1585,10 @@ uint64_t SDNode::getConstantOperandVal(unsigned Num) const { return cast<ConstantSDNode>(getOperand(Num))->getZExtValue(); } +const APInt &SDNode::getConstantOperandAPInt(unsigned Num) const { + return cast<ConstantSDNode>(getOperand(Num))->getAPIntValue(); +} + class ConstantFPSDNode : public SDNode { friend class SelectionDAG; @@ -1603,20 +1656,36 @@ SDValue peekThroughBitcasts(SDValue V); /// If \p V is not a bitcasted one-use value, it is returned as-is. SDValue peekThroughOneUseBitcasts(SDValue V); +/// Return the non-extracted vector source operand of \p V if it exists. +/// If \p V is not an extracted subvector, it is returned as-is. +SDValue peekThroughExtractSubvectors(SDValue V); + /// Returns true if \p V is a bitwise not operation. Assumes that an all ones /// constant is canonicalized to be operand 1. -bool isBitwiseNot(SDValue V); +bool isBitwiseNot(SDValue V, bool AllowUndefs = false); /// Returns the SDNode if it is a constant splat BuildVector or constant int. -ConstantSDNode *isConstOrConstSplat(SDValue N, bool AllowUndefs = false); +ConstantSDNode *isConstOrConstSplat(SDValue N, bool AllowUndefs = false, + bool AllowTruncation = false); + +/// Returns the SDNode if it is a demanded constant splat BuildVector or +/// constant int. +ConstantSDNode *isConstOrConstSplat(SDValue N, const APInt &DemandedElts, + bool AllowUndefs = false, + bool AllowTruncation = false); /// Returns the SDNode if it is a constant splat BuildVector or constant float. ConstantFPSDNode *isConstOrConstSplatFP(SDValue N, bool AllowUndefs = false); +/// Returns the SDNode if it is a demanded constant splat BuildVector or +/// constant float. +ConstantFPSDNode *isConstOrConstSplatFP(SDValue N, const APInt &DemandedElts, + bool AllowUndefs = false); + /// Return true if the value is a constant 0 integer or a splatted vector of -/// a constant 0 integer (with no undefs). +/// a constant 0 integer (with no undefs by default). /// Build vector implicit truncation is not an issue for null values. -bool isNullOrNullSplat(SDValue V); +bool isNullOrNullSplat(SDValue V, bool AllowUndefs = false); /// Return true if the value is a constant 1 integer or a splatted vector of a /// constant 1 integer (with no undefs). @@ -1673,6 +1742,38 @@ public: } }; +/// This SDNode is used for LIFETIME_START/LIFETIME_END values, which indicate +/// the offet and size that are started/ended in the underlying FrameIndex. +class LifetimeSDNode : public SDNode { + friend class SelectionDAG; + int64_t Size; + int64_t Offset; // -1 if offset is unknown. + + LifetimeSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl, + SDVTList VTs, int64_t Size, int64_t Offset) + : SDNode(Opcode, Order, dl, VTs), Size(Size), Offset(Offset) {} +public: + int64_t getFrameIndex() const { + return cast<FrameIndexSDNode>(getOperand(1))->getIndex(); + } + + bool hasOffset() const { return Offset >= 0; } + int64_t getOffset() const { + assert(hasOffset() && "offset is unknown"); + return Offset; + } + int64_t getSize() const { + assert(hasOffset() && "offset is unknown"); + return Size; + } + + // Methods to support isa and dyn_cast + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::LIFETIME_START || + N->getOpcode() == ISD::LIFETIME_END; + } +}; + class JumpTableSDNode : public SDNode { friend class SelectionDAG; @@ -1818,12 +1919,31 @@ public: unsigned MinSplatBits = 0, bool isBigEndian = false) const; + /// Returns the demanded splatted value or a null value if this is not a + /// splat. + /// + /// The DemandedElts mask indicates the elements that must be in the splat. + /// If passed a non-null UndefElements bitvector, it will resize it to match + /// the vector width and set the bits where elements are undef. + SDValue getSplatValue(const APInt &DemandedElts, + BitVector *UndefElements = nullptr) const; + /// Returns the splatted value or a null value if this is not a splat. /// /// If passed a non-null UndefElements bitvector, it will resize it to match /// the vector width and set the bits where elements are undef. SDValue getSplatValue(BitVector *UndefElements = nullptr) const; + /// Returns the demanded splatted constant or null if this is not a constant + /// splat. + /// + /// The DemandedElts mask indicates the elements that must be in the splat. + /// If passed a non-null UndefElements bitvector, it will resize it to match + /// the vector width and set the bits where elements are undef. + ConstantSDNode * + getConstantSplatNode(const APInt &DemandedElts, + BitVector *UndefElements = nullptr) const; + /// Returns the splatted constant or null if this is not a constant /// splat. /// @@ -1832,6 +1952,16 @@ public: ConstantSDNode * getConstantSplatNode(BitVector *UndefElements = nullptr) const; + /// Returns the demanded splatted constant FP or null if this is not a + /// constant FP splat. + /// + /// The DemandedElts mask indicates the elements that must be in the splat. + /// If passed a non-null UndefElements bitvector, it will resize it to match + /// the vector width and set the bits where elements are undef. + ConstantFPSDNode * + getConstantFPSplatNode(const APInt &DemandedElts, + BitVector *UndefElements = nullptr) const; + /// Returns the splatted constant FP or null if this is not a constant /// FP splat. /// @@ -1956,8 +2086,10 @@ class LabelSDNode : public SDNode { MCSymbol *Label; - LabelSDNode(unsigned Order, const DebugLoc &dl, MCSymbol *L) - : SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) {} + LabelSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl, MCSymbol *L) + : SDNode(Opcode, Order, dl, getSDVTList(MVT::Other)), Label(L) { + assert(LabelSDNode::classof(this) && "not a label opcode"); + } public: MCSymbol *getLabel() const { return Label; } @@ -2049,6 +2181,8 @@ public: : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { LSBaseSDNodeBits.AddressingMode = AM; assert(getAddressingMode() == AM && "Value truncated"); + assert((!MMO->isAtomic() || MMO->isVolatile()) && + "use an AtomicSDNode instead for non-volatile atomics"); } const SDValue &getOffset() const { @@ -2473,18 +2607,6 @@ namespace ISD { cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; } - /// Return true if the node is a math/logic binary operator. This corresponds - /// to the IR function of the same name. - inline bool isBinaryOp(const SDNode *N) { - auto Op = N->getOpcode(); - return (Op == ISD::ADD || Op == ISD::SUB || Op == ISD::MUL || - Op == ISD::AND || Op == ISD::OR || Op == ISD::XOR || - Op == ISD::SHL || Op == ISD::SRL || Op == ISD::SRA || - Op == ISD::SDIV || Op == ISD::UDIV || Op == ISD::SREM || - Op == ISD::UREM || Op == ISD::FADD || Op == ISD::FSUB || - Op == ISD::FMUL || Op == ISD::FDIV || Op == ISD::FREM); - } - /// Attempt to match a unary predicate against a scalar/splat constant or /// every element of a constant BUILD_VECTOR. /// If AllowUndef is true, then UNDEF elements will pass nullptr to Match. @@ -2495,10 +2617,11 @@ namespace ISD { /// Attempt to match a binary predicate against a pair of scalar/splat /// constants or every element of a pair of constant BUILD_VECTORs. /// If AllowUndef is true, then UNDEF elements will pass nullptr to Match. + /// If AllowTypeMismatch is true then RetType + ArgTypes don't need to match. bool matchBinaryPredicate( SDValue LHS, SDValue RHS, std::function<bool(ConstantSDNode *, ConstantSDNode *)> Match, - bool AllowUndefs = false); + bool AllowUndefs = false, bool AllowTypeMismatch = false); } // end namespace ISD } // end namespace llvm diff --git a/include/llvm/CodeGen/SelectionDAGTargetInfo.h b/include/llvm/CodeGen/SelectionDAGTargetInfo.h index 45c1df48a5e6..6f6a9a5ae269 100644 --- a/include/llvm/CodeGen/SelectionDAGTargetInfo.h +++ b/include/llvm/CodeGen/SelectionDAGTargetInfo.h @@ -1,9 +1,8 @@ //==- llvm/CodeGen/SelectionDAGTargetInfo.h - SelectionDAG Info --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -148,6 +147,14 @@ public: return std::make_pair(SDValue(), SDValue()); } + virtual SDValue EmitTargetCodeForSetTag(SelectionDAG &DAG, const SDLoc &dl, + SDValue Chain, SDValue Addr, + SDValue Size, + MachinePointerInfo DstPtrInfo, + bool ZeroData) const { + return SDValue(); + } + // Return true when the decision to generate FMA's (or FMS, FMLA etc) rather // than FMUL and ADD is delegated to the machine combiner. virtual bool generateFMAsInMachineCombiner(CodeGenOpt::Level OptLevel) const { diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index 8c8a7be459fd..2b32a4d30dff 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/SlotIndexes.h - Slot indexes representation -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -302,8 +301,6 @@ class raw_ostream; } }; - template <> struct isPodLike<SlotIndex> { static const bool value = true; }; - inline raw_ostream& operator<<(raw_ostream &os, SlotIndex li) { li.print(os); return os; @@ -311,20 +308,6 @@ class raw_ostream; using IdxMBBPair = std::pair<SlotIndex, MachineBasicBlock *>; - inline bool operator<(SlotIndex V, const IdxMBBPair &IM) { - return V < IM.first; - } - - inline bool operator<(const IdxMBBPair &IM, SlotIndex V) { - return IM.first < V; - } - - struct Idx2MBBCompare { - bool operator()(const IdxMBBPair &LHS, const IdxMBBPair &RHS) const { - return LHS.first < RHS.first; - } - }; - /// SlotIndexes pass. /// /// This pass assigns indexes to each instruction. @@ -336,10 +319,6 @@ class raw_ostream; using IndexList = ilist<IndexListEntry>; IndexList indexList; -#ifdef EXPENSIVE_CHECKS - IndexList graveyardList; -#endif // EXPENSIVE_CHECKS - MachineFunction *mf; using Mi2IndexMap = DenseMap<const MachineInstr *, SlotIndex>; @@ -368,7 +347,7 @@ class raw_ostream; public: static char ID; - SlotIndexes() : MachineFunctionPass(ID) { + SlotIndexes() : MachineFunctionPass(ID), mf(nullptr) { initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); } @@ -385,9 +364,6 @@ class raw_ostream; /// Dump the indexes. void dump() const; - /// Renumber the index list, providing space for new instructions. - void renumberIndexes(); - /// Repair indexes after adding and removing instructions. void repairIndexesInRange(MachineBasicBlock *MBB, MachineBasicBlock::iterator Begin, @@ -516,7 +492,9 @@ class raw_ostream; /// Move iterator to the next IdxMBBPair where the SlotIndex is greater or /// equal to \p To. MBBIndexIterator advanceMBBIndex(MBBIndexIterator I, SlotIndex To) const { - return std::lower_bound(I, idx2MBBMap.end(), To); + return std::partition_point( + I, idx2MBBMap.end(), + [=](const IdxMBBPair &IM) { return IM.first < To; }); } /// Get an iterator pointing to the IdxMBBPair with the biggest SlotIndex @@ -552,29 +530,6 @@ class raw_ostream; return J->second; } - /// Returns the MBB covering the given range, or null if the range covers - /// more than one basic block. - MachineBasicBlock* getMBBCoveringRange(SlotIndex start, SlotIndex end) const { - - assert(start < end && "Backwards ranges not allowed."); - MBBIndexIterator itr = findMBBIndex(start); - if (itr == MBBIndexEnd()) { - itr = std::prev(itr); - return itr->second; - } - - // Check that we don't cross the boundary into this block. - if (itr->first < end) - return nullptr; - - itr = std::prev(itr); - - if (itr->first <= start) - return itr->second; - - return nullptr; - } - /// Insert the given machine instruction into the mapping. Returns the /// assigned index. /// If Late is set and there are null indexes between mi's neighboring @@ -680,33 +635,7 @@ class raw_ostream; idx2MBBMap.push_back(IdxMBBPair(startIdx, mbb)); renumberIndexes(newItr); - llvm::sort(idx2MBBMap, Idx2MBBCompare()); - } - - /// Free the resources that were required to maintain a SlotIndex. - /// - /// Once an index is no longer needed (for instance because the instruction - /// at that index has been moved), the resources required to maintain the - /// index can be relinquished to reduce memory use and improve renumbering - /// performance. Any remaining SlotIndex objects that point to the same - /// index are left 'dangling' (much the same as a dangling pointer to a - /// freed object) and should not be accessed, except to destruct them. - /// - /// Like dangling pointers, access to dangling SlotIndexes can cause - /// painful-to-track-down bugs, especially if the memory for the index - /// previously pointed to has been re-used. To detect dangling SlotIndex - /// bugs, build with EXPENSIVE_CHECKS=1. This will cause "erased" indexes to - /// be retained in a graveyard instead of being freed. Operations on indexes - /// in the graveyard will trigger an assertion. - void eraseIndex(SlotIndex index) { - IndexListEntry *entry = index.listEntry(); -#ifdef EXPENSIVE_CHECKS - indexList.remove(entry); - graveyardList.push_back(entry); - entry->setPoison(); -#else - indexList.erase(entry); -#endif + llvm::sort(idx2MBBMap, less_first()); } }; diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h index 8be9ae378557..d7d88de6f682 100644 --- a/include/llvm/CodeGen/StackMaps.h +++ b/include/llvm/CodeGen/StackMaps.h @@ -1,9 +1,8 @@ //===- StackMaps.h - StackMaps ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/StackProtector.h b/include/llvm/CodeGen/StackProtector.h index a506ac636a17..2bdf4425e24a 100644 --- a/include/llvm/CodeGen/StackProtector.h +++ b/include/llvm/CodeGen/StackProtector.h @@ -1,9 +1,8 @@ //===- StackProtector.h - Stack Protector Insertion -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -62,12 +61,6 @@ private: /// protection when -fstack-protection is used. unsigned SSPBufferSize = 0; - /// VisitedPHIs - The set of PHI nodes visited when determining - /// if a variable's reference has been taken. This set - /// is maintained to ensure we don't visit the same PHI node multiple - /// times. - SmallPtrSet<const PHINode *, 16> VisitedPHIs; - // A prologue is generated. bool HasPrologue = false; diff --git a/include/llvm/CodeGen/SwiftErrorValueTracking.h b/include/llvm/CodeGen/SwiftErrorValueTracking.h new file mode 100644 index 000000000000..fb7a12853c09 --- /dev/null +++ b/include/llvm/CodeGen/SwiftErrorValueTracking.h @@ -0,0 +1,110 @@ +//===- SwiftErrorValueTracking.h - Track swifterror VReg vals --*- C++ -*--===// +// +// 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 implements a limited mem2reg-like analysis to promote uses of function +// arguments and allocas marked with swiftalloc from memory into virtual +// registers tracked by this class. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFTERRORVALUETRACKING_H +#define SWIFTERRORVALUETRACKING_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Register.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/DebugLoc.h" +#include <functional> +#include <type_traits> +#include <utility> + + +namespace llvm { + class Function; + class MachineBasicBlock; + class MachineFunction; + class MachineInstr; + class TargetInstrInfo; + class TargetLowering; + +class SwiftErrorValueTracking { + // Some useful objects to reduce the number of function arguments needed. + MachineFunction *MF; + const Function *Fn; + const TargetLowering *TLI; + const TargetInstrInfo *TII; + + /// A map from swifterror value in a basic block to the virtual register it is + /// currently represented by. + DenseMap<std::pair<const MachineBasicBlock *, const Value *>, Register> + VRegDefMap; + + /// A list of upward exposed vreg uses that need to be satisfied by either a + /// copy def or a phi node at the beginning of the basic block representing + /// the predecessor(s) swifterror value. + DenseMap<std::pair<const MachineBasicBlock *, const Value *>, Register> + VRegUpwardsUse; + + /// A map from instructions that define/use a swifterror value to the virtual + /// register that represents that def/use. + llvm::DenseMap<PointerIntPair<const Instruction *, 1, bool>, Register> + VRegDefUses; + + /// The swifterror argument of the current function. + const Value *SwiftErrorArg; + + using SwiftErrorValues = SmallVector<const Value*, 1>; + /// A function can only have a single swifterror argument. And if it does + /// have a swifterror argument, it must be the first entry in + /// SwiftErrorVals. + SwiftErrorValues SwiftErrorVals; + +public: + /// Initialize data structures for specified new function. + void setFunction(MachineFunction &MF); + + /// Get the (unique) function argument that was marked swifterror, or nullptr + /// if this function has no swifterror args. + const Value *getFunctionArg() const { + return SwiftErrorArg; + } + + /// Get or create the swifterror value virtual register in + /// VRegDefMap for this basic block. + Register getOrCreateVReg(const MachineBasicBlock *, const Value *); + + /// Set the swifterror virtual register in the VRegDefMap for this + /// basic block. + void setCurrentVReg(const MachineBasicBlock *MBB, const Value *, Register); + + /// Get or create the swifterror value virtual register for a def of a + /// swifterror by an instruction. + Register getOrCreateVRegDefAt(const Instruction *, const MachineBasicBlock *, + const Value *); + + /// Get or create the swifterror value virtual register for a use of a + /// swifterror by an instruction. + Register getOrCreateVRegUseAt(const Instruction *, const MachineBasicBlock *, + const Value *); + + /// Create initial definitions of swifterror values in the entry block of the + /// current function. + bool createEntriesInEntryBlock(DebugLoc DbgLoc); + + /// Propagate assigned swifterror vregs through a function, synthesizing PHI + /// nodes when needed to maintain consistency. + void propagateVRegs(); + + void preassignVRegs(MachineBasicBlock *MBB, BasicBlock::const_iterator Begin, + BasicBlock::const_iterator End); +}; + +} + +#endif diff --git a/include/llvm/CodeGen/SwitchLoweringUtils.h b/include/llvm/CodeGen/SwitchLoweringUtils.h new file mode 100644 index 000000000000..62134dc792f7 --- /dev/null +++ b/include/llvm/CodeGen/SwitchLoweringUtils.h @@ -0,0 +1,297 @@ +//===- SwitchLoweringUtils.h - Switch Lowering ------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SWITCHLOWERINGUTILS_H +#define LLVM_CODEGEN_SWITCHLOWERINGUTILS_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/TargetLowering.h" +#include "llvm/IR/Constants.h" +#include "llvm/Support/BranchProbability.h" + +namespace llvm { + +class FunctionLoweringInfo; +class MachineBasicBlock; + +namespace SwitchCG { + +enum CaseClusterKind { + /// A cluster of adjacent case labels with the same destination, or just one + /// case. + CC_Range, + /// A cluster of cases suitable for jump table lowering. + CC_JumpTable, + /// A cluster of cases suitable for bit test lowering. + CC_BitTests +}; + +/// A cluster of case labels. +struct CaseCluster { + CaseClusterKind Kind; + const ConstantInt *Low, *High; + union { + MachineBasicBlock *MBB; + unsigned JTCasesIndex; + unsigned BTCasesIndex; + }; + BranchProbability Prob; + + static CaseCluster range(const ConstantInt *Low, const ConstantInt *High, + MachineBasicBlock *MBB, BranchProbability Prob) { + CaseCluster C; + C.Kind = CC_Range; + C.Low = Low; + C.High = High; + C.MBB = MBB; + C.Prob = Prob; + return C; + } + + static CaseCluster jumpTable(const ConstantInt *Low, const ConstantInt *High, + unsigned JTCasesIndex, BranchProbability Prob) { + CaseCluster C; + C.Kind = CC_JumpTable; + C.Low = Low; + C.High = High; + C.JTCasesIndex = JTCasesIndex; + C.Prob = Prob; + return C; + } + + static CaseCluster bitTests(const ConstantInt *Low, const ConstantInt *High, + unsigned BTCasesIndex, BranchProbability Prob) { + CaseCluster C; + C.Kind = CC_BitTests; + C.Low = Low; + C.High = High; + C.BTCasesIndex = BTCasesIndex; + C.Prob = Prob; + return C; + } +}; + +using CaseClusterVector = std::vector<CaseCluster>; +using CaseClusterIt = CaseClusterVector::iterator; + +/// Sort Clusters and merge adjacent cases. +void sortAndRangeify(CaseClusterVector &Clusters); + +struct CaseBits { + uint64_t Mask = 0; + MachineBasicBlock *BB = nullptr; + unsigned Bits = 0; + BranchProbability ExtraProb; + + CaseBits() = default; + CaseBits(uint64_t mask, MachineBasicBlock *bb, unsigned bits, + BranchProbability Prob) + : Mask(mask), BB(bb), Bits(bits), ExtraProb(Prob) {} +}; + +using CaseBitsVector = std::vector<CaseBits>; + +/// This structure is used to communicate between SelectionDAGBuilder and +/// SDISel for the code generation of additional basic blocks needed by +/// multi-case switch statements. +struct CaseBlock { + // For the GISel interface. + struct PredInfoPair { + CmpInst::Predicate Pred; + // Set when no comparison should be emitted. + bool NoCmp; + }; + union { + // The condition code to use for the case block's setcc node. + // Besides the integer condition codes, this can also be SETTRUE, in which + // case no comparison gets emitted. + ISD::CondCode CC; + struct PredInfoPair PredInfo; + }; + + // The LHS/MHS/RHS of the comparison to emit. + // Emit by default LHS op RHS. MHS is used for range comparisons: + // If MHS is not null: (LHS <= MHS) and (MHS <= RHS). + const Value *CmpLHS, *CmpMHS, *CmpRHS; + + // The block to branch to if the setcc is true/false. + MachineBasicBlock *TrueBB, *FalseBB; + + // The block into which to emit the code for the setcc and branches. + MachineBasicBlock *ThisBB; + + /// The debug location of the instruction this CaseBlock was + /// produced from. + SDLoc DL; + DebugLoc DbgLoc; + + // Branch weights. + BranchProbability TrueProb, FalseProb; + + // Constructor for SelectionDAG. + CaseBlock(ISD::CondCode cc, const Value *cmplhs, const Value *cmprhs, + const Value *cmpmiddle, MachineBasicBlock *truebb, + MachineBasicBlock *falsebb, MachineBasicBlock *me, SDLoc dl, + BranchProbability trueprob = BranchProbability::getUnknown(), + BranchProbability falseprob = BranchProbability::getUnknown()) + : CC(cc), CmpLHS(cmplhs), CmpMHS(cmpmiddle), CmpRHS(cmprhs), + TrueBB(truebb), FalseBB(falsebb), ThisBB(me), DL(dl), + TrueProb(trueprob), FalseProb(falseprob) {} + + // Constructor for GISel. + CaseBlock(CmpInst::Predicate pred, bool nocmp, const Value *cmplhs, + const Value *cmprhs, const Value *cmpmiddle, + MachineBasicBlock *truebb, MachineBasicBlock *falsebb, + MachineBasicBlock *me, DebugLoc dl, + BranchProbability trueprob = BranchProbability::getUnknown(), + BranchProbability falseprob = BranchProbability::getUnknown()) + : PredInfo({pred, nocmp}), CmpLHS(cmplhs), CmpMHS(cmpmiddle), + CmpRHS(cmprhs), TrueBB(truebb), FalseBB(falsebb), ThisBB(me), + DbgLoc(dl), TrueProb(trueprob), FalseProb(falseprob) {} +}; + +struct JumpTable { + /// The virtual register containing the index of the jump table entry + /// to jump to. + unsigned Reg; + /// The JumpTableIndex for this jump table in the function. + unsigned JTI; + /// The MBB into which to emit the code for the indirect jump. + MachineBasicBlock *MBB; + /// The MBB of the default bb, which is a successor of the range + /// check MBB. This is when updating PHI nodes in successors. + MachineBasicBlock *Default; + + JumpTable(unsigned R, unsigned J, MachineBasicBlock *M, MachineBasicBlock *D) + : Reg(R), JTI(J), MBB(M), Default(D) {} +}; +struct JumpTableHeader { + APInt First; + APInt Last; + const Value *SValue; + MachineBasicBlock *HeaderBB; + bool Emitted; + bool OmitRangeCheck; + + JumpTableHeader(APInt F, APInt L, const Value *SV, MachineBasicBlock *H, + bool E = false) + : First(std::move(F)), Last(std::move(L)), SValue(SV), HeaderBB(H), + Emitted(E), OmitRangeCheck(false) {} +}; +using JumpTableBlock = std::pair<JumpTableHeader, JumpTable>; + +struct BitTestCase { + uint64_t Mask; + MachineBasicBlock *ThisBB; + MachineBasicBlock *TargetBB; + BranchProbability ExtraProb; + + BitTestCase(uint64_t M, MachineBasicBlock *T, MachineBasicBlock *Tr, + BranchProbability Prob) + : Mask(M), ThisBB(T), TargetBB(Tr), ExtraProb(Prob) {} +}; + +using BitTestInfo = SmallVector<BitTestCase, 3>; + +struct BitTestBlock { + APInt First; + APInt Range; + const Value *SValue; + unsigned Reg; + MVT RegVT; + bool Emitted; + bool ContiguousRange; + MachineBasicBlock *Parent; + MachineBasicBlock *Default; + BitTestInfo Cases; + BranchProbability Prob; + BranchProbability DefaultProb; + + BitTestBlock(APInt F, APInt R, const Value *SV, unsigned Rg, MVT RgVT, bool E, + bool CR, MachineBasicBlock *P, MachineBasicBlock *D, + BitTestInfo C, BranchProbability Pr) + : First(std::move(F)), Range(std::move(R)), SValue(SV), Reg(Rg), + RegVT(RgVT), Emitted(E), ContiguousRange(CR), Parent(P), Default(D), + Cases(std::move(C)), Prob(Pr) {} +}; + +/// Return the range of value within a range. +uint64_t getJumpTableRange(const CaseClusterVector &Clusters, unsigned First, + unsigned Last); + +/// Return the number of cases within a range. +uint64_t getJumpTableNumCases(const SmallVectorImpl<unsigned> &TotalCases, + unsigned First, unsigned Last); + +struct SwitchWorkListItem { + MachineBasicBlock *MBB; + CaseClusterIt FirstCluster; + CaseClusterIt LastCluster; + const ConstantInt *GE; + const ConstantInt *LT; + BranchProbability DefaultProb; +}; +using SwitchWorkList = SmallVector<SwitchWorkListItem, 4>; + +class SwitchLowering { +public: + SwitchLowering(FunctionLoweringInfo &funcinfo) : FuncInfo(funcinfo) {} + + void init(const TargetLowering &tli, const TargetMachine &tm, + const DataLayout &dl) { + TLI = &tli; + TM = &tm; + DL = &dl; + } + + /// Vector of CaseBlock structures used to communicate SwitchInst code + /// generation information. + std::vector<CaseBlock> SwitchCases; + + /// Vector of JumpTable structures used to communicate SwitchInst code + /// generation information. + std::vector<JumpTableBlock> JTCases; + + /// Vector of BitTestBlock structures used to communicate SwitchInst code + /// generation information. + std::vector<BitTestBlock> BitTestCases; + + void findJumpTables(CaseClusterVector &Clusters, const SwitchInst *SI, + MachineBasicBlock *DefaultMBB); + + bool buildJumpTable(const CaseClusterVector &Clusters, unsigned First, + unsigned Last, const SwitchInst *SI, + MachineBasicBlock *DefaultMBB, CaseCluster &JTCluster); + + + void findBitTestClusters(CaseClusterVector &Clusters, const SwitchInst *SI); + + /// Build a bit test cluster from Clusters[First..Last]. Returns false if it + /// decides it's not a good idea. + bool buildBitTests(CaseClusterVector &Clusters, unsigned First, unsigned Last, + const SwitchInst *SI, CaseCluster &BTCluster); + + virtual void addSuccessorWithProb( + MachineBasicBlock *Src, MachineBasicBlock *Dst, + BranchProbability Prob = BranchProbability::getUnknown()) = 0; + + virtual ~SwitchLowering() = default; + +private: + const TargetLowering *TLI; + const TargetMachine *TM; + const DataLayout *DL; + FunctionLoweringInfo &FuncInfo; +}; + +} // namespace SwitchCG +} // namespace llvm + +#endif // LLVM_CODEGEN_SWITCHLOWERINGUTILS_H + diff --git a/include/llvm/CodeGen/TailDuplicator.h b/include/llvm/CodeGen/TailDuplicator.h index be6562c85f2e..358798d5ed60 100644 --- a/include/llvm/CodeGen/TailDuplicator.h +++ b/include/llvm/CodeGen/TailDuplicator.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/TailDuplicator.h ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/TargetCallingConv.h b/include/llvm/CodeGen/TargetCallingConv.h index 7d138f585171..aebeeecbe506 100644 --- a/include/llvm/CodeGen/TargetCallingConv.h +++ b/include/llvm/CodeGen/TargetCallingConv.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/TargetCallingConv.h - Calling Convention ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -46,9 +45,12 @@ namespace ISD { unsigned IsInConsecutiveRegsLast : 1; unsigned IsInConsecutiveRegs : 1; unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate + unsigned IsPointer : 1; unsigned ByValSize; ///< Byval struct size + unsigned PointerAddrSpace; ///< Address space of pointer argument + public: ArgFlagsTy() : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsNest(0), @@ -56,8 +58,9 @@ namespace ISD { IsSwiftSelf(0), IsSwiftError(0), IsHva(0), IsHvaStart(0), IsSecArgPass(0), ByValAlign(0), OrigAlign(0), IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0), - IsCopyElisionCandidate(0), ByValSize(0) { - static_assert(sizeof(*this) == 2 * sizeof(unsigned), "flags are too big"); + IsCopyElisionCandidate(0), IsPointer(0), ByValSize(0), + PointerAddrSpace(0) { + static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big"); } bool isZExt() const { return IsZExt; } @@ -114,6 +117,9 @@ namespace ISD { bool isCopyElisionCandidate() const { return IsCopyElisionCandidate; } void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; } + bool isPointer() const { return IsPointer; } + void setPointer() { IsPointer = 1; } + unsigned getByValAlign() const { return (1U << ByValAlign) / 2; } void setByValAlign(unsigned A) { ByValAlign = Log2_32(A) + 1; @@ -128,7 +134,10 @@ namespace ISD { unsigned getByValSize() const { return ByValSize; } void setByValSize(unsigned S) { ByValSize = S; } - }; + + unsigned getPointerAddrSpace() const { return PointerAddrSpace; } + void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; } +}; /// InputArg - This struct carries flags and type information about a /// single incoming (formal) argument or incoming (from the perspective diff --git a/include/llvm/CodeGen/TargetFrameLowering.h b/include/llvm/CodeGen/TargetFrameLowering.h index b4d1da941433..878c9ffd2b51 100644 --- a/include/llvm/CodeGen/TargetFrameLowering.h +++ b/include/llvm/CodeGen/TargetFrameLowering.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/TargetFrameLowering.h ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -15,6 +14,7 @@ #define LLVM_CODEGEN_TARGETFRAMELOWERING_H #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/ADT/StringSwitch.h" #include <utility> #include <vector> @@ -24,6 +24,14 @@ namespace llvm { class MachineFunction; class RegScavenger; +namespace TargetStackID { + enum Value { + Default = 0, + SGPRSpill = 1, + NoAlloc = 255 + }; +} + /// Information about stack frame layout on the target. It holds the direction /// of stack growth, the known stack alignment on entry to each function, and /// the offset to the locals area. @@ -262,6 +270,17 @@ public: return getFrameIndexReference(MF, FI, FrameReg); } + /// getNonLocalFrameIndexReference - This method returns the offset used to + /// reference a frame index location. The offset can be from either FP/BP/SP + /// based on which base register is returned by llvm.localaddress. + virtual int getNonLocalFrameIndexReference(const MachineFunction &MF, + int FI) const { + // By default, dispatch to getFrameIndexReference. Interested targets can + // override this. + unsigned FrameReg; + return getFrameIndexReference(MF, FI, FrameReg); + } + /// This method determines which of the registers reported by /// TargetRegisterInfo::getCalleeSavedRegs() should actually get saved. /// The default implementation checks populates the \p SavedRegs bitset with @@ -335,6 +354,16 @@ public: return true; } + virtual bool isSupportedStackID(TargetStackID::Value ID) const { + switch (ID) { + default: + return false; + case TargetStackID::Default: + case TargetStackID::NoAlloc: + return true; + } + } + /// Check if given function is safe for not having callee saved registers. /// This is used when interprocedural register allocation is enabled. static bool isSafeForNoCSROpt(const Function &F) { diff --git a/include/llvm/CodeGen/TargetInstrInfo.h b/include/llvm/CodeGen/TargetInstrInfo.h index 961b90e9bc12..25b04f8c019a 100644 --- a/include/llvm/CodeGen/TargetInstrInfo.h +++ b/include/llvm/CodeGen/TargetInstrInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/TargetInstrInfo.h - Instruction Info --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -27,6 +26,7 @@ #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineOutliner.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/VirtRegMap.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/Support/BranchProbability.h" #include "llvm/Support/ErrorHandling.h" @@ -81,6 +81,7 @@ public: /// Given a machine instruction descriptor, returns the register /// class constraint for OpNum, or NULL. + virtual const TargetRegisterClass *getRegClass(const MCInstrDesc &MCID, unsigned OpNum, const TargetRegisterInfo *TRI, const MachineFunction &MF) const; @@ -429,6 +430,13 @@ public: RegSubRegPair(unsigned Reg = 0, unsigned SubReg = 0) : Reg(Reg), SubReg(SubReg) {} + + bool operator==(const RegSubRegPair& P) const { + return Reg == P.Reg && SubReg == P.SubReg; + } + bool operator!=(const RegSubRegPair& P) const { + return !(*this == P); + } }; /// A pair composed of a pair of a register and a sub-register index, @@ -663,8 +671,9 @@ public: /// is finished. Return the value/register of the new loop count. We need /// this function when peeling off one or more iterations of a loop. This /// function assumes the nth iteration is peeled first. - virtual unsigned reduceLoopCount(MachineBasicBlock &MBB, MachineInstr *IndVar, - MachineInstr &Cmp, + virtual unsigned reduceLoopCount(MachineBasicBlock &MBB, + MachineBasicBlock &PreHeader, + MachineInstr *IndVar, MachineInstr &Cmp, SmallVectorImpl<MachineOperand> &Cond, SmallVectorImpl<MachineInstr *> &PrevInsts, unsigned Iter, unsigned MaxIter) const { @@ -926,9 +935,12 @@ public: /// operand folded, otherwise NULL is returned. /// The new instruction is inserted before MI, and the client is responsible /// for removing the old instruction. + /// If VRM is passed, the assigned physregs can be inspected by target to + /// decide on using an opcode (note that those assignments can still change). MachineInstr *foldMemoryOperand(MachineInstr &MI, ArrayRef<unsigned> Ops, int FI, - LiveIntervals *LIS = nullptr) const; + LiveIntervals *LIS = nullptr, + VirtRegMap *VRM = nullptr) const; /// Same as the previous version except it allows folding of any load and /// store from / to any address, not just from a specific stack slot. @@ -1018,7 +1030,8 @@ protected: foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops, MachineBasicBlock::iterator InsertPt, int FrameIndex, - LiveIntervals *LIS = nullptr) const { + LiveIntervals *LIS = nullptr, + VirtRegMap *VRM = nullptr) const { return nullptr; } @@ -1138,8 +1151,9 @@ public: /// Get the base operand and byte offset of an instruction that reads/writes /// memory. - virtual bool getMemOperandWithOffset(MachineInstr &MI, - MachineOperand *&BaseOp, int64_t &Offset, + virtual bool getMemOperandWithOffset(const MachineInstr &MI, + const MachineOperand *&BaseOp, + int64_t &Offset, const TargetRegisterInfo *TRI) const { return false; } @@ -1164,8 +1178,8 @@ public: /// or /// DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI)); /// to TargetPassConfig::createMachineScheduler() to have an effect. - virtual bool shouldClusterMemOps(MachineOperand &BaseOp1, - MachineOperand &BaseOp2, + virtual bool shouldClusterMemOps(const MachineOperand &BaseOp1, + const MachineOperand &BaseOp2, unsigned NumLoads) const { llvm_unreachable("target did not implement shouldClusterMemOps()"); } @@ -1253,8 +1267,9 @@ public: /// Measure the specified inline asm to determine an approximation of its /// length. - virtual unsigned getInlineAsmLength(const char *Str, - const MCAsmInfo &MAI) const; + virtual unsigned getInlineAsmLength( + const char *Str, const MCAsmInfo &MAI, + const TargetSubtargetInfo *STI = nullptr) const; /// Allocate and return a hazard recognizer to use for this target when /// scheduling the machine instructions before register allocation. @@ -1542,7 +1557,8 @@ public: /// See also MachineInstr::mayAlias, which is implemented on top of this /// function. virtual bool - areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb, + areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, + const MachineInstr &MIb, AliasAnalysis *AA = nullptr) const { assert((MIa.mayLoad() || MIa.mayStore()) && "MIa must load from or modify a memory location"); diff --git a/include/llvm/CodeGen/TargetLowering.h b/include/llvm/CodeGen/TargetLowering.h index 23dbaac03ebe..d5cca60bb1b2 100644 --- a/include/llvm/CodeGen/TargetLowering.h +++ b/include/llvm/CodeGen/TargetLowering.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/TargetLowering.h - Target Lowering Info -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -189,13 +188,18 @@ public: bool IsSwiftSelf : 1; bool IsSwiftError : 1; uint16_t Alignment = 0; + Type *ByValType = nullptr; ArgListEntry() : IsSExt(false), IsZExt(false), IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false), IsInAlloca(false), IsReturned(false), IsSwiftSelf(false), IsSwiftError(false) {} - void setAttributes(ImmutableCallSite *CS, unsigned ArgIdx); + void setAttributes(const CallBase *Call, unsigned ArgIdx); + + void setAttributes(ImmutableCallSite *CS, unsigned ArgIdx) { + return setAttributes(cast<CallBase>(CS->getInstruction()), ArgIdx); + } }; using ArgListTy = std::vector<ArgListEntry>; @@ -235,7 +239,14 @@ public: /// Return the pointer type for the given address space, defaults to /// the pointer type from the data layout. /// FIXME: The default needs to be removed once all the code is updated. - MVT getPointerTy(const DataLayout &DL, uint32_t AS = 0) const { + virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS = 0) const { + return MVT::getIntegerVT(DL.getPointerSizeInBits(AS)); + } + + /// Return the in-memory pointer type for the given address space, defaults to + /// the pointer type from the data layout. FIXME: The default needs to be + /// removed once all the code is updated. + MVT getPointerMemTy(const DataLayout &DL, uint32_t AS = 0) const { return MVT::getIntegerVT(DL.getPointerSizeInBits(AS)); } @@ -291,6 +302,9 @@ public: // The default action for one element vectors is to scalarize if (VT.getVectorNumElements() == 1) return TypeScalarizeVector; + // The default action for an odd-width vector is to widen. + if (!VT.isPow2VectorType()) + return TypeWidenVector; // The default action for other vectors is to promote return TypePromoteInteger; } @@ -387,8 +401,9 @@ public: /// efficiently, casting the load to a smaller vector of larger types and /// loading is more efficient, however, this can be undone by optimizations in /// dag combiner. - virtual bool isLoadBitCastBeneficial(EVT LoadVT, - EVT BitcastVT) const { + virtual bool isLoadBitCastBeneficial(EVT LoadVT, EVT BitcastVT, + const SelectionDAG &DAG, + const MachineMemOperand &MMO) const { // Don't do if we could do an indexed load on the original type, but not on // the new one. if (!LoadVT.isSimple() || !BitcastVT.isSimple()) @@ -402,14 +417,18 @@ public: getTypeToPromoteTo(ISD::LOAD, LoadMVT) == BitcastVT.getSimpleVT()) return false; - return true; + bool Fast = false; + return allowsMemoryAccess(*DAG.getContext(), DAG.getDataLayout(), BitcastVT, + MMO, &Fast) && Fast; } /// Return true if the following transform is beneficial: /// (store (y (conv x)), y*)) -> (store x, (x*)) - virtual bool isStoreBitCastBeneficial(EVT StoreVT, EVT BitcastVT) const { + virtual bool isStoreBitCastBeneficial(EVT StoreVT, EVT BitcastVT, + const SelectionDAG &DAG, + const MachineMemOperand &MMO) const { // Default to the same logic as loads. - return isLoadBitCastBeneficial(StoreVT, BitcastVT); + return isLoadBitCastBeneficial(StoreVT, BitcastVT, DAG, MMO); } /// Return true if it is expected to be cheaper to do a store of a non-zero @@ -421,10 +440,12 @@ public: return false; } - /// Allow store merging after legalization in addition to before legalization. - /// This may catch stores that do not exist earlier (eg, stores created from - /// intrinsics). - virtual bool mergeStoresAfterLegalization() const { return true; } + /// Allow store merging for the specified type after legalization in addition + /// to before legalization. This may transform stores that do not exist + /// earlier (for example, stores created from intrinsics). + virtual bool mergeStoresAfterLegalization(EVT MemVT) const { + return true; + } /// Returns if it's reasonable to merge stores to MemVT size. virtual bool canMergeStoresTo(unsigned AS, EVT MemVT, @@ -521,13 +542,22 @@ public: /// There are two ways to clear extreme bits (either low or high): /// Mask: x & (-1 << y) (the instcombine canonical form) /// Shifts: x >> y << y - /// Return true if the variant with 2 shifts is preferred. + /// Return true if the variant with 2 variable shifts is preferred. /// Return false if there is no preference. - virtual bool preferShiftsToClearExtremeBits(SDValue X) const { + virtual bool shouldFoldMaskToVariableShiftPair(SDValue X) const { // By default, let's assume that no one prefers shifts. return false; } + /// Return true if it is profitable to fold a pair of shifts into a mask. + /// This is usually true on most targets. But some targets, like Thumb1, + /// have immediate shift instructions, but no immediate "and" instruction; + /// this makes the fold unprofitable. + virtual bool shouldFoldConstantShiftPairToMask(const SDNode *N, + CombineLevel Level) const { + return true; + } + /// Should we tranform the IR-optimal check for whether given truncation /// down into KeptBits would be truncating or not: /// (add %x, (1 << (KeptBits-1))) srccond (1 << KeptBits) @@ -541,6 +571,16 @@ public: return false; } + /// These two forms are equivalent: + /// sub %y, (xor %x, -1) + /// add (add %x, 1), %y + /// The variant with two add's is IR-canonical. + /// Some targets may prefer one to the other. + virtual bool preferIncOfAddToSubOfNot(EVT VT) const { + // By default, let's assume that everyone prefers the form with two add's. + return true; + } + /// Return true if the target wants to use the optimization that /// turns ext(promotableInst1(...(promotableInstN(load)))) into /// promotedInst1(...(promotedInstN(ext(load)))). @@ -560,11 +600,6 @@ public: return false; } - /// Return true if target supports floating point exceptions. - bool hasFloatingPointExceptions() const { - return HasFloatingPointExceptions; - } - /// Return true if target always beneficiates from combining into FMA for a /// given value type. This must typically return false on targets where FMA /// takes more cycles to execute than FADD. @@ -619,12 +654,21 @@ public: /// Return the register class that should be used for the specified value /// type. - virtual const TargetRegisterClass *getRegClassFor(MVT VT) const { + virtual const TargetRegisterClass *getRegClassFor(MVT VT, bool isDivergent = false) const { + (void)isDivergent; const TargetRegisterClass *RC = RegClassForVT[VT.SimpleTy]; assert(RC && "This value type is not natively supported!"); return RC; } + /// Allows target to decide about the register class of the + /// specific value that is live outside the defining block. + /// Returns true if the value needs uniform register class. + virtual bool requiresUniformRegister(MachineFunction &MF, + const Value *) const { + return false; + } + /// Return the 'representative' register class for the specified value /// type. /// @@ -643,6 +687,13 @@ public: return RepRegClassCostForVT[VT.SimpleTy]; } + /// Return true if SHIFT instructions should be expanded to SHIFT_PARTS + /// instructions, and false if a library call is preferred (e.g for code-size + /// reasons). + virtual bool shouldExpandShift(SelectionDAG &DAG, SDNode *N) const { + return true; + } + /// Return true if the target has native support for the specified value type. /// This means that it has a register that directly holds it without /// promotions or expansions. @@ -768,7 +819,8 @@ public: /// Returns true if the target can instruction select the specified FP /// immediate natively. If false, the legalizer will materialize the FP /// immediate as a load from a constant pool. - virtual bool isFPImmLegal(const APFloat &/*Imm*/, EVT /*VT*/) const { + virtual bool isFPImmLegal(const APFloat & /*Imm*/, EVT /*VT*/, + bool ForCodeSize = false) const { return false; } @@ -830,6 +882,8 @@ public: default: llvm_unreachable("Unexpected fixed point operation."); case ISD::SMULFIX: + case ISD::SMULFIXSAT: + case ISD::UMULFIX: Supported = isSupportedFixedPointOperation(Op, VT, Scale); break; } @@ -865,6 +919,8 @@ public: case ISD::STRICT_FFLOOR: EqOpc = ISD::FFLOOR; break; case ISD::STRICT_FROUND: EqOpc = ISD::FROUND; break; case ISD::STRICT_FTRUNC: EqOpc = ISD::FTRUNC; break; + case ISD::STRICT_FP_ROUND: EqOpc = ISD::FP_ROUND; break; + case ISD::STRICT_FP_EXTEND: EqOpc = ISD::FP_EXTEND; break; } auto Action = getOperationAction(EqOpc, VT); @@ -931,21 +987,20 @@ public: /// Return true if lowering to a jump table is suitable for a set of case /// clusters which may contain \p NumCases cases, \p Range range of values. - /// FIXME: This function check the maximum table size and density, but the - /// minimum size is not checked. It would be nice if the minimum size is - /// also combined within this function. Currently, the minimum size check is - /// performed in findJumpTable() in SelectionDAGBuiler and - /// getEstimatedNumberOfCaseClusters() in BasicTTIImpl. virtual bool isSuitableForJumpTable(const SwitchInst *SI, uint64_t NumCases, uint64_t Range) const { - const bool OptForSize = SI->getParent()->getParent()->optForSize(); + // FIXME: This function check the maximum table size and density, but the + // minimum size is not checked. It would be nice if the minimum size is + // also combined within this function. Currently, the minimum size check is + // performed in findJumpTable() in SelectionDAGBuiler and + // getEstimatedNumberOfCaseClusters() in BasicTTIImpl. + const bool OptForSize = SI->getParent()->getParent()->hasOptSize(); const unsigned MinDensity = getMinimumJumpTableDensity(OptForSize); - const unsigned MaxJumpTableSize = - OptForSize || getMaximumJumpTableSize() == 0 - ? UINT_MAX - : getMaximumJumpTableSize(); - // Check whether a range of clusters is dense enough for a jump table. - if (Range <= MaxJumpTableSize && + const unsigned MaxJumpTableSize = getMaximumJumpTableSize(); + + // Check whether the number of cases is small enough and + // the range is dense enough for a jump table. + if ((OptForSize || Range <= MaxJumpTableSize) && (NumCases * 100 >= Range * MinDensity)) { return true; } @@ -1140,24 +1195,42 @@ public: EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown = false) const { // Lower scalar pointers to native pointer types. - if (PointerType *PTy = dyn_cast<PointerType>(Ty)) + if (auto *PTy = dyn_cast<PointerType>(Ty)) return getPointerTy(DL, PTy->getAddressSpace()); - if (Ty->isVectorTy()) { - VectorType *VTy = cast<VectorType>(Ty); - Type *Elm = VTy->getElementType(); + if (auto *VTy = dyn_cast<VectorType>(Ty)) { + Type *EltTy = VTy->getElementType(); // Lower vectors of pointers to native pointer types. + if (auto *PTy = dyn_cast<PointerType>(EltTy)) { + EVT PointerTy(getPointerTy(DL, PTy->getAddressSpace())); + EltTy = PointerTy.getTypeForEVT(Ty->getContext()); + } + return EVT::getVectorVT(Ty->getContext(), EVT::getEVT(EltTy, false), + VTy->getNumElements()); + } + + return EVT::getEVT(Ty, AllowUnknown); + } + + EVT getMemValueType(const DataLayout &DL, Type *Ty, + bool AllowUnknown = false) const { + // Lower scalar pointers to native pointer types. + if (PointerType *PTy = dyn_cast<PointerType>(Ty)) + return getPointerMemTy(DL, PTy->getAddressSpace()); + else if (VectorType *VTy = dyn_cast<VectorType>(Ty)) { + Type *Elm = VTy->getElementType(); if (PointerType *PT = dyn_cast<PointerType>(Elm)) { - EVT PointerTy(getPointerTy(DL, PT->getAddressSpace())); + EVT PointerTy(getPointerMemTy(DL, PT->getAddressSpace())); Elm = PointerTy.getTypeForEVT(Ty->getContext()); } - return EVT::getVectorVT(Ty->getContext(), EVT::getEVT(Elm, false), VTy->getNumElements()); } - return EVT::getEVT(Ty, AllowUnknown); + + return getValueType(DL, Ty, AllowUnknown); } + /// Return the MVT corresponding to this LLVM type. See getValueType. MVT getSimpleValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown = false) const { @@ -1327,18 +1400,6 @@ public: return OptSize ? MaxLoadsPerMemcmpOptSize : MaxLoadsPerMemcmp; } - /// For memcmp expansion when the memcmp result is only compared equal or - /// not-equal to 0, allow up to this number of load pairs per block. As an - /// example, this may allow 'memcmp(a, b, 3) == 0' in a single block: - /// a0 = load2bytes &a[0] - /// b0 = load2bytes &b[0] - /// a2 = load1byte &a[2] - /// b2 = load1byte &b[2] - /// r = cmp eq (a0 ^ b0 | a2 ^ b2), 0 - virtual unsigned getMemcmpEqZeroLoadsPerBlock() const { - return 1; - } - /// Get maximum # of store operations permitted for llvm.memmove /// /// This function returns the maximum number of store operations permitted @@ -1358,10 +1419,10 @@ public: /// copy/move/set is converted to a sequence of store operations. Its use /// helps to ensure that such replacements don't generate code that causes an /// alignment error (trap) on the target machine. - virtual bool allowsMisalignedMemoryAccesses(EVT, - unsigned AddrSpace = 0, - unsigned Align = 1, - bool * /*Fast*/ = nullptr) const { + virtual bool allowsMisalignedMemoryAccesses( + EVT, unsigned AddrSpace = 0, unsigned Align = 1, + MachineMemOperand::Flags Flags = MachineMemOperand::MONone, + bool * /*Fast*/ = nullptr) const { return false; } @@ -1369,8 +1430,18 @@ public: /// given address space and alignment. If the access is allowed, the optional /// final parameter returns if the access is also fast (as defined by the /// target). + bool + allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, + unsigned AddrSpace = 0, unsigned Alignment = 1, + MachineMemOperand::Flags Flags = MachineMemOperand::MONone, + bool *Fast = nullptr) const; + + /// Return true if the target supports a memory access of this type for the + /// given MachineMemOperand. If the access is allowed, the optional + /// final parameter returns if the access is also fast (as defined by the + /// target). bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, - unsigned AddrSpace = 0, unsigned Alignment = 1, + const MachineMemOperand &MMO, bool *Fast = nullptr) const; /// Returns the target specific optimal type for load and store operations as @@ -1384,12 +1455,11 @@ public: /// zero. 'MemcpyStrSrc' indicates whether the memcpy source is constant so it /// does not need to be loaded. It returns EVT::Other if the type should be /// determined using generic target-independent logic. - virtual EVT getOptimalMemOpType(uint64_t /*Size*/, - unsigned /*DstAlign*/, unsigned /*SrcAlign*/, - bool /*IsMemset*/, - bool /*ZeroMemset*/, - bool /*MemcpyStrSrc*/, - MachineFunction &/*MF*/) const { + virtual EVT + getOptimalMemOpType(uint64_t /*Size*/, unsigned /*DstAlign*/, + unsigned /*SrcAlign*/, bool /*IsMemset*/, + bool /*ZeroMemset*/, bool /*MemcpyStrSrc*/, + const AttributeList & /*FuncAttributes*/) const { return MVT::Other; } @@ -1515,7 +1585,7 @@ public: /// performs validation and error handling, returns the function. Otherwise, /// returns nullptr. Must be previously inserted by insertSSPDeclarations. /// Should be used only when getIRStackGuard returns nullptr. - virtual Value *getSSPStackGuardCheck(const Module &M) const; + virtual Function *getSSPStackGuardCheck(const Module &M) const; protected: Value *getDefaultSafeStackPointerLocation(IRBuilder<> &IRB, @@ -1537,8 +1607,9 @@ public: } /// Returns true if a cast from SrcAS to DestAS is "cheap", such that e.g. we - /// are happy to sink it into basic blocks. - virtual bool isCheapAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const { + /// are happy to sink it into basic blocks. A cast may be free, but not + /// necessarily a no-op. e.g. a free truncate from a 64-bit to 32-bit pointer. + virtual bool isFreeAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const { return isNoopAddrSpaceCast(SrcAS, DestAS); } @@ -1716,8 +1787,9 @@ public: /// Returns how the IR-level AtomicExpand pass should expand the given /// AtomicRMW, if at all. Default is to never expand. - virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *) const { - return AtomicExpansionKind::None; + virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const { + return RMW->isFloatingPointOperation() ? + AtomicExpansionKind::CmpXChg : AtomicExpansionKind::None; } /// On some platforms, an AtomicRMW that never actually modifies the value @@ -1762,6 +1834,8 @@ public: Action != TypeSplitVector; } + virtual bool isProfitableToCombineMinNumMaxNum(EVT VT) const { return true; } + /// Return true if a select of constants (select Cond, C1, C2) should be /// transformed into simple math ops with the condition value. For example: /// select Cond, C1, C1-1 --> add (zext Cond), C1-1 @@ -1865,12 +1939,6 @@ protected: /// control. void setJumpIsExpensive(bool isExpensive = true); - /// Tells the code generator that this target supports floating point - /// exceptions and cares about preserving floating point exception behavior. - void setHasFloatingPointExceptions(bool FPExceptions = true) { - HasFloatingPointExceptions = FPExceptions; - } - /// Tells the code generator which bitwidths to bypass. void addBypassSlowDiv(unsigned int SlowBitWidth, unsigned int FastBitWidth) { BypassSlowDivWidths[SlowBitWidth] = FastBitWidth; @@ -2159,6 +2227,8 @@ public: case ISD::UADDSAT: case ISD::FMINNUM: case ISD::FMAXNUM: + case ISD::FMINNUM_IEEE: + case ISD::FMAXNUM_IEEE: case ISD::FMINIMUM: case ISD::FMAXIMUM: return true; @@ -2166,6 +2236,30 @@ public: } } + /// Return true if the node is a math/logic binary operator. + virtual bool isBinOp(unsigned Opcode) const { + // A commutative binop must be a binop. + if (isCommutativeBinOp(Opcode)) + return true; + // These are non-commutative binops. + switch (Opcode) { + case ISD::SUB: + case ISD::SHL: + case ISD::SRL: + case ISD::SRA: + case ISD::SDIV: + case ISD::UDIV: + case ISD::SREM: + case ISD::UREM: + case ISD::FSUB: + case ISD::FDIV: + case ISD::FREM: + return true; + default: + return false; + } + } + /// Return true if it's free to truncate a value of type FromTy to type /// ToTy. e.g. On x86 it's free to truncate a i32 value in register EAX to i16 /// by referencing its sub-register AX. @@ -2270,6 +2364,16 @@ public: return false; } + /// Return true if sinking I's operands to the same basic block as I is + /// profitable, e.g. because the operands can be folded into a target + /// instruction during instruction selection. After calling the function + /// \p Ops contains the Uses to sink ordered by dominance (dominating users + /// come first). + virtual bool shouldSinkOperands(Instruction *I, + SmallVectorImpl<Use *> &Ops) const { + return false; + } + /// Return true if the target supplies and combines to a paired load /// two loaded values of type LoadedType next to each other in memory. /// RequiredAlignment gives the minimal alignment constraints that must be met @@ -2415,6 +2519,31 @@ public: return false; } + /// Return true if extraction of a scalar element from the given vector type + /// at the given index is cheap. For example, if scalar operations occur on + /// the same register file as vector operations, then an extract element may + /// be a sub-register rename rather than an actual instruction. + virtual bool isExtractVecEltCheap(EVT VT, unsigned Index) const { + return false; + } + + /// Try to convert math with an overflow comparison into the corresponding DAG + /// node operation. Targets may want to override this independently of whether + /// the operation is legal/custom for the given type because it may obscure + /// matching of other patterns. + virtual bool shouldFormOverflowOp(unsigned Opcode, EVT VT) const { + // TODO: The default logic is inherited from code in CodeGenPrepare. + // The opcode should not make a difference by default? + if (Opcode != ISD::UADDO) + return false; + + // Allow the transform as long as we have an integer type that is not + // obviously illegal and unsupported. + if (VT.isVector()) + return false; + return VT.isSimple() || !isOperationExpand(Opcode, VT); + } + // Return true if it is profitable to use a scalar input to a BUILD_VECTOR // even if the vector itself has multiple uses. virtual bool aggressivelyPreferBuildVectorSources(EVT VecVT) const { @@ -2495,10 +2624,6 @@ private: /// predication. bool JumpIsExpensive; - /// Whether the target supports or cares about preserving floating point - /// exception behavior. - bool HasFloatingPointExceptions; - /// This target prefers to use _setjmp to implement llvm.setjmp. /// /// Defaults to false. @@ -2834,11 +2959,10 @@ public: /// Returns a pair of (return value, chain). /// It is an error to pass RTLIB::UNKNOWN_LIBCALL as \p LC. - std::pair<SDValue, SDValue> makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, - EVT RetVT, ArrayRef<SDValue> Ops, - bool isSigned, const SDLoc &dl, - bool doesNotReturn = false, - bool isReturnValueUsed = true) const; + std::pair<SDValue, SDValue> makeLibCall( + SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef<SDValue> Ops, + bool isSigned, const SDLoc &dl, bool doesNotReturn = false, + bool isReturnValueUsed = true, bool isPostTypeLegalization = false) const; /// Check whether parameters to a call that are passed in callee saved /// registers are the same as from the calling function. This needs to be @@ -2876,6 +3000,20 @@ public: } }; + /// Determines the optimal series of memory ops to replace the memset / memcpy. + /// Return true if the number of memory ops is below the threshold (Limit). + /// It returns the types of the sequence of memory ops to perform + /// memset / memcpy by reference. + bool findOptimalMemOpLowering(std::vector<EVT> &MemOps, + unsigned Limit, uint64_t Size, + unsigned DstAlign, unsigned SrcAlign, + bool IsMemset, + bool ZeroMemset, + bool MemcpyStrSrc, + bool AllowOverlap, + unsigned DstAS, unsigned SrcAS, + const AttributeList &FuncAttributes) const; + /// Check to see if the specified operand of the specified instruction is a /// constant integer. If so, check to see if there are any bits set in the /// constant that are not demanded. If so, shrink the constant and return @@ -3001,6 +3139,10 @@ public: TargetLoweringOpt &TLO, unsigned Depth = 0) const; + /// This method returns the constant pool value that will be loaded by LD. + /// NOTE: You must check for implicit extensions of the constant by LD. + virtual const Constant *getTargetConstantFromLoad(LoadSDNode *LD) const; + /// If \p SNaN is false, \returns true if \p Op is known to never be any /// NaN. If \p sNaN is true, returns if \p Op is known to never be a signaling /// NaN. @@ -3088,15 +3230,6 @@ public: return true; } - /// Return true if it is profitable to fold a pair of shifts into a mask. - /// This is usually true on most targets. But some targets, like Thumb1, - /// have immediate shift instructions, but no immediate "and" instruction; - /// this makes the fold unprofitable. - virtual bool shouldFoldShiftPairToMask(const SDNode *N, - CombineLevel Level) const { - return true; - } - // Return true if it is profitable to combine a BUILD_VECTOR with a stride-pattern // to a shuffle and a truncate. // Example of such a combine: @@ -3430,6 +3563,15 @@ public: return false; } + /// For most targets, an LLVM type must be broken down into multiple + /// smaller types. Usually the halves are ordered according to the endianness + /// but for some platform that would break. So this method will default to + /// matching the endianness but can be overridden. + virtual bool + shouldSplitFunctionArgumentsAsLittleEndian(const DataLayout &DL) const { + return DL.isLittleEndian(); + } + /// Returns a 0 terminated array of registers that can be safely used as /// scratch registers. virtual const MCPhysReg *getScratchRegisters(CallingConv::ID CC) const { @@ -3638,6 +3780,12 @@ public: std::vector<SDValue> &Ops, SelectionDAG &DAG) const; + // Lower custom output constraints. If invalid, return SDValue(). + virtual SDValue LowerAsmOutputForConstraint(SDValue &Chain, SDValue &Flag, + SDLoc DL, + const AsmOperandInfo &OpInfo, + SelectionDAG &DAG) const; + //===--------------------------------------------------------------------===// // Div utility functions // @@ -3840,8 +3988,26 @@ public: /// Method for building the DAG expansion of ISD::SMULFIX. This method accepts /// integers as its arguments. - SDValue getExpandedFixedPointMultiplication(SDNode *Node, - SelectionDAG &DAG) const; + SDValue expandFixedPointMul(SDNode *Node, SelectionDAG &DAG) const; + + /// Method for building the DAG expansion of ISD::U(ADD|SUB)O. Expansion + /// always suceeds and populates the Result and Overflow arguments. + void expandUADDSUBO(SDNode *Node, SDValue &Result, SDValue &Overflow, + SelectionDAG &DAG) const; + + /// Method for building the DAG expansion of ISD::S(ADD|SUB)O. Expansion + /// always suceeds and populates the Result and Overflow arguments. + void expandSADDSUBO(SDNode *Node, SDValue &Result, SDValue &Overflow, + SelectionDAG &DAG) const; + + /// Method for building the DAG expansion of ISD::[US]MULO. Returns whether + /// expansion was successful and populates the Result and Overflow arguments. + bool expandMULO(SDNode *Node, SDValue &Result, SDValue &Overflow, + SelectionDAG &DAG) const; + + /// Expand a VECREDUCE_* into an explicit calculation. If Count is specified, + /// only the first Count elements of the vector are used. + SDValue expandVecReduce(SDNode *Node, SelectionDAG &DAG) const; //===--------------------------------------------------------------------===// // Instruction Emitting Hooks @@ -3894,14 +4060,23 @@ public: SDValue lowerCmpEqZeroToCtlzSrl(SDValue Op, SelectionDAG &DAG) const; private: - SDValue simplifySetCCWithAnd(EVT VT, SDValue N0, SDValue N1, - ISD::CondCode Cond, DAGCombinerInfo &DCI, - const SDLoc &DL) const; + SDValue foldSetCCWithAnd(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, + const SDLoc &DL, DAGCombinerInfo &DCI) const; + SDValue foldSetCCWithBinOp(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, + const SDLoc &DL, DAGCombinerInfo &DCI) const; SDValue optimizeSetCCOfSignedTruncationCheck(EVT SCCVT, SDValue N0, SDValue N1, ISD::CondCode Cond, DAGCombinerInfo &DCI, const SDLoc &DL) const; + + SDValue prepareUREMEqFold(EVT SETCCVT, SDValue REMNode, + SDValue CompTargetNode, ISD::CondCode Cond, + DAGCombinerInfo &DCI, const SDLoc &DL, + SmallVectorImpl<SDNode *> &Created) const; + SDValue buildUREMEqFold(EVT SETCCVT, SDValue REMNode, SDValue CompTargetNode, + ISD::CondCode Cond, DAGCombinerInfo &DCI, + const SDLoc &DL) const; }; /// Given an LLVM IR type and return type attributes, compute the return value diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 052d1f8bc686..a1fb81cb009d 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -1,9 +1,8 @@ //==- llvm/CodeGen/TargetLoweringObjectFileImpl.h - Object Info --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/TargetOpcodes.h b/include/llvm/CodeGen/TargetOpcodes.h index d0d959c4ae11..080a244f6f69 100644 --- a/include/llvm/CodeGen/TargetOpcodes.h +++ b/include/llvm/CodeGen/TargetOpcodes.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/TargetOpcodes.h - Target Indep Opcodes -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/TargetPassConfig.h b/include/llvm/CodeGen/TargetPassConfig.h index 3288711a335d..0bd82aafac37 100644 --- a/include/llvm/CodeGen/TargetPassConfig.h +++ b/include/llvm/CodeGen/TargetPassConfig.h @@ -1,9 +1,8 @@ //===- TargetPassConfig.h - Code Generation pass options --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -25,6 +24,7 @@ class LLVMTargetMachine; struct MachineSchedContext; class PassConfigImpl; class ScheduleDAGInstrs; +class CSEConfigBase; // The old pass manager infrastructure is hidden in a legacy namespace now. namespace legacy { @@ -75,9 +75,6 @@ public: } }; -template <> struct isPodLike<IdentifyingPassPtr> { - static const bool value = true; -}; /// Target-Independent Code Generator Pass Configuration Options. /// @@ -319,6 +316,13 @@ public: /// when GlobalISel failed and isGlobalISelAbortEnabled is false. virtual bool reportDiagnosticWhenGlobalISelFallback() const; + /// Check whether continuous CSE should be enabled in GISel passes. + /// By default, it's enabled for non O0 levels. + virtual bool isGISelCSEEnabled() const; + + /// Returns the CSEConfig object to use for the current optimization level. + virtual std::unique_ptr<CSEConfigBase> getCSEConfig() const; + protected: // Helper to verify the analysis is really immutable. void setOpt(bool &Opt, bool Val); @@ -360,11 +364,11 @@ protected: /// addFastRegAlloc - Add the minimum set of target-independent passes that /// are required for fast register allocation. - virtual void addFastRegAlloc(FunctionPass *RegAllocPass); + virtual void addFastRegAlloc(); /// addOptimizedRegAlloc - Add passes related to register allocation. /// LLVMTargetMachine provides standard regalloc passes for most targets. - virtual void addOptimizedRegAlloc(FunctionPass *RegAllocPass); + virtual void addOptimizedRegAlloc(); /// addPreRewrite - Add passes to the optimized register allocation pipeline /// after register allocation is complete, but before virtual registers are @@ -374,10 +378,18 @@ protected: /// after RABasic or RAGreedy, they should take advantage of LiveRegMatrix. /// When these passes run, VirtRegMap contains legal physreg assignments for /// all virtual registers. + /// + /// Note if the target overloads addRegAssignAndRewriteOptimized, this may not + /// be honored. This is also not generally used for the the fast variant, + /// where the allocation and rewriting are done in one pass. virtual bool addPreRewrite() { return false; } + /// Add passes to be run immediately after virtual registers are rewritten + /// to physical registers. + virtual void addPostRewrite() { } + /// This method may be implemented by targets that want to run passes after /// register allocation pass pipeline but before prolog-epilog insertion. virtual void addPostRegAlloc() { } @@ -431,7 +443,12 @@ protected: /// addMachinePasses helper to create the target-selected or overriden /// regalloc pass. - FunctionPass *createRegAllocPass(bool Optimized); + virtual FunctionPass *createRegAllocPass(bool Optimized); + + /// Add core register alloator passes which do the actual register assignment + /// and rewriting. \returns true if any passes were added. + virtual bool addRegAssignmentFast(); + virtual bool addRegAssignmentOptimized(); }; } // end namespace llvm diff --git a/include/llvm/CodeGen/TargetRegisterInfo.h b/include/llvm/CodeGen/TargetRegisterInfo.h index 0fbff3137653..ddbd677b3eaa 100644 --- a/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/include/llvm/CodeGen/TargetRegisterInfo.h @@ -1,9 +1,8 @@ //==- CodeGen/TargetRegisterInfo.h - Target Register Information -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -521,6 +520,11 @@ public: /// function. Used by MachineRegisterInfo::isConstantPhysReg(). virtual bool isConstantPhysReg(unsigned PhysReg) const { return false; } + /// Returns true if the register class is considered divergent. + virtual bool isDivergentRegClass(const TargetRegisterClass *RC) const { + return false; + } + /// Physical registers that may be modified within a function but are /// guaranteed to be restored before any uses. This is useful for targets that /// have call sequences where a GOT register may be updated by the caller @@ -986,7 +990,7 @@ public: /// getFrameRegister - This method should return the register used as a base /// for values allocated in the current stack frame. - virtual unsigned getFrameRegister(const MachineFunction &MF) const = 0; + virtual Register getFrameRegister(const MachineFunction &MF) const = 0; /// Mark a register and all its aliases as reserved in the given set. void markSuperRegs(BitVector &RegisterSet, unsigned Reg) const; diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h index 6173925e23a1..cce85c8d7b0d 100644 --- a/include/llvm/CodeGen/TargetSchedule.h +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/TargetSchedule.h - Sched Machine Model ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/TargetSubtargetInfo.h b/include/llvm/CodeGen/TargetSubtargetInfo.h index 968e4c4b8102..037fc3ed3243 100644 --- a/include/llvm/CodeGen/TargetSubtargetInfo.h +++ b/include/llvm/CodeGen/TargetSubtargetInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/TargetSubtargetInfo.h - Target Information --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -43,6 +42,7 @@ class RegisterBankInfo; class SDep; class SelectionDAGTargetInfo; struct SubtargetFeatureKV; +struct SubtargetSubTypeKV; struct SubtargetInfoKV; class SUnit; class TargetFrameLowering; @@ -63,8 +63,7 @@ class TargetSubtargetInfo : public MCSubtargetInfo { protected: // Can only create subclasses... TargetSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS, ArrayRef<SubtargetFeatureKV> PF, - ArrayRef<SubtargetFeatureKV> PD, - const SubtargetInfoKV *ProcSched, + ArrayRef<SubtargetSubTypeKV> PD, const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA, const InstrStage *IS, @@ -190,13 +189,13 @@ public: /// TargetLowering preference). It does not yet disable the postRA scheduler. virtual bool enableMachineScheduler() const; - /// Support printing of [latency:throughput] comment in output .S file. - virtual bool supportPrintSchedInfo() const { return false; } - /// True if the machine scheduler should disable the TLI preference /// for preRA scheduling with the source level scheduler. virtual bool enableMachineSchedDefaultSched() const { return true; } + /// True if the subtarget should run MachinePipeliner + virtual bool enableMachinePipeliner() const { return true; }; + /// True if the subtarget should enable joining global copies. /// /// By default this is enabled if the machine scheduler is enabled, but @@ -250,6 +249,10 @@ public: std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const { } + /// Default to DFA for resource management, return false when target will use + /// ProcResource in InstrSchedModel instead. + virtual bool useDFAforSMS() const { return true; } + // For use with PostRAScheduling: get the minimum optimization level needed // to enable post-RA scheduling. virtual CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const { @@ -286,12 +289,16 @@ public: /// possible. virtual bool enableSubRegLiveness() const { return false; } - /// Returns string representation of scheduler comment - std::string getSchedInfoStr(const MachineInstr &MI) const; - std::string getSchedInfoStr(MCInst const &MCI) const override; - /// This is called after a .mir file was loaded. virtual void mirFileLoaded(MachineFunction &MF) const; + + /// True if the register allocator should use the allocation orders exactly as + /// written in the tablegen descriptions, false if it should allocate + /// the specified physical register later if is it callee-saved. + virtual bool ignoreCSRForAllocationOrder(const MachineFunction &MF, + unsigned PhysReg) const { + return false; + } }; } // end namespace llvm diff --git a/include/llvm/CodeGen/UnreachableBlockElim.h b/include/llvm/CodeGen/UnreachableBlockElim.h index 3e7afd4cd433..d52d7c3c5b49 100644 --- a/include/llvm/CodeGen/UnreachableBlockElim.h +++ b/include/llvm/CodeGen/UnreachableBlockElim.h @@ -1,9 +1,8 @@ //===-- UnreachableBlockElim.h - Remove unreachable blocks for codegen --===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index d2ef4a94f8e2..c540c94f79d9 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -1,9 +1,8 @@ //===- CodeGen/ValueTypes.h - Low-Level Target independ. types --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index 0abb4ece1d14..5818ac183fcc 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -1,9 +1,8 @@ //===- ValueTypes.td - ValueType definitions ---------------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -63,89 +62,105 @@ def v32i16 : ValueType<512, 38>; // 32 x i16 vector value def v64i16 : ValueType<1024,39>; // 64 x i16 vector value def v128i16: ValueType<2048,40>; //128 x i16 vector value -def v1i32 : ValueType<32 , 41>; // 1 x i32 vector value -def v2i32 : ValueType<64 , 42>; // 2 x i32 vector value -def v4i32 : ValueType<128, 43>; // 4 x i32 vector value -def v8i32 : ValueType<256, 44>; // 8 x i32 vector value -def v16i32 : ValueType<512, 45>; // 16 x i32 vector value -def v32i32 : ValueType<1024,46>; // 32 x i32 vector value -def v64i32 : ValueType<2048,47>; // 64 x i32 vector value +def v1i32 : ValueType<32 , 41>; // 1 x i32 vector value +def v2i32 : ValueType<64 , 42>; // 2 x i32 vector value +def v3i32 : ValueType<96 , 43>; // 3 x i32 vector value +def v4i32 : ValueType<128, 44>; // 4 x i32 vector value +def v5i32 : ValueType<160, 45>; // 5 x i32 vector value +def v8i32 : ValueType<256, 46>; // 8 x i32 vector value +def v16i32 : ValueType<512, 47>; // 16 x i32 vector value +def v32i32 : ValueType<1024,48>; // 32 x i32 vector value +def v64i32 : ValueType<2048,49>; // 64 x i32 vector value +def v128i32 : ValueType<4096,50>; // 128 x i32 vector value +def v256i32 : ValueType<8182,51>; // 256 x i32 vector value +def v512i32 : ValueType<16384,52>; // 512 x i32 vector value +def v1024i32 : ValueType<32768,53>; // 1024 x i32 vector value +def v2048i32 : ValueType<65536,54>; // 2048 x i32 vector value -def v1i64 : ValueType<64 , 48>; // 1 x i64 vector value -def v2i64 : ValueType<128, 49>; // 2 x i64 vector value -def v4i64 : ValueType<256, 50>; // 4 x i64 vector value -def v8i64 : ValueType<512, 51>; // 8 x i64 vector value -def v16i64 : ValueType<1024,52>; // 16 x i64 vector value -def v32i64 : ValueType<2048,53>; // 32 x i64 vector value +def v1i64 : ValueType<64 , 55>; // 1 x i64 vector value +def v2i64 : ValueType<128, 56>; // 2 x i64 vector value +def v4i64 : ValueType<256, 57>; // 4 x i64 vector value +def v8i64 : ValueType<512, 58>; // 8 x i64 vector value +def v16i64 : ValueType<1024,59>; // 16 x i64 vector value +def v32i64 : ValueType<2048,60>; // 32 x i64 vector value -def v1i128 : ValueType<128, 54>; // 1 x i128 vector value +def v1i128 : ValueType<128, 61>; // 1 x i128 vector value -def nxv1i1 : ValueType<1, 55>; // n x 1 x i1 vector value -def nxv2i1 : ValueType<2, 56>; // n x 2 x i1 vector value -def nxv4i1 : ValueType<4, 57>; // n x 4 x i1 vector value -def nxv8i1 : ValueType<8, 58>; // n x 8 x i1 vector value -def nxv16i1 : ValueType<16, 59>; // n x 16 x i1 vector value -def nxv32i1 : ValueType<32, 60>; // n x 32 x i1 vector value +def nxv1i1 : ValueType<1, 62>; // n x 1 x i1 vector value +def nxv2i1 : ValueType<2, 63>; // n x 2 x i1 vector value +def nxv4i1 : ValueType<4, 64>; // n x 4 x i1 vector value +def nxv8i1 : ValueType<8, 65>; // n x 8 x i1 vector value +def nxv16i1 : ValueType<16, 66>; // n x 16 x i1 vector value +def nxv32i1 : ValueType<32, 67>; // n x 32 x i1 vector value -def nxv1i8 : ValueType<8, 61>; // n x 1 x i8 vector value -def nxv2i8 : ValueType<16, 62>; // n x 2 x i8 vector value -def nxv4i8 : ValueType<32, 63>; // n x 4 x i8 vector value -def nxv8i8 : ValueType<64, 64>; // n x 8 x i8 vector value -def nxv16i8 : ValueType<128, 65>; // n x 16 x i8 vector value -def nxv32i8 : ValueType<256, 66>; // n x 32 x i8 vector value +def nxv1i8 : ValueType<8, 68>; // n x 1 x i8 vector value +def nxv2i8 : ValueType<16, 69>; // n x 2 x i8 vector value +def nxv4i8 : ValueType<32, 70>; // n x 4 x i8 vector value +def nxv8i8 : ValueType<64, 71>; // n x 8 x i8 vector value +def nxv16i8 : ValueType<128, 72>; // n x 16 x i8 vector value +def nxv32i8 : ValueType<256, 73>; // n x 32 x i8 vector value -def nxv1i16 : ValueType<16, 67>; // n x 1 x i16 vector value -def nxv2i16 : ValueType<32, 68>; // n x 2 x i16 vector value -def nxv4i16 : ValueType<64, 69>; // n x 4 x i16 vector value -def nxv8i16 : ValueType<128, 70>; // n x 8 x i16 vector value -def nxv16i16: ValueType<256, 71>; // n x 16 x i16 vector value -def nxv32i16: ValueType<512, 72>; // n x 32 x i16 vector value +def nxv1i16 : ValueType<16, 74>; // n x 1 x i16 vector value +def nxv2i16 : ValueType<32, 75>; // n x 2 x i16 vector value +def nxv4i16 : ValueType<64, 76>; // n x 4 x i16 vector value +def nxv8i16 : ValueType<128, 77>; // n x 8 x i16 vector value +def nxv16i16: ValueType<256, 78>; // n x 16 x i16 vector value +def nxv32i16: ValueType<512, 79>; // n x 32 x i16 vector value -def nxv1i32 : ValueType<32, 73>; // n x 1 x i32 vector value -def nxv2i32 : ValueType<64, 74>; // n x 2 x i32 vector value -def nxv4i32 : ValueType<128, 75>; // n x 4 x i32 vector value -def nxv8i32 : ValueType<256, 76>; // n x 8 x i32 vector value -def nxv16i32: ValueType<512, 77>; // n x 16 x i32 vector value -def nxv32i32: ValueType<1024,78>; // n x 32 x i32 vector value +def nxv1i32 : ValueType<32, 80>; // n x 1 x i32 vector value +def nxv2i32 : ValueType<64, 81>; // n x 2 x i32 vector value +def nxv4i32 : ValueType<128, 82>; // n x 4 x i32 vector value +def nxv8i32 : ValueType<256, 83>; // n x 8 x i32 vector value +def nxv16i32: ValueType<512, 84>; // n x 16 x i32 vector value +def nxv32i32: ValueType<1024,85>; // n x 32 x i32 vector value -def nxv1i64 : ValueType<64, 79>; // n x 1 x i64 vector value -def nxv2i64 : ValueType<128, 80>; // n x 2 x i64 vector value -def nxv4i64 : ValueType<256, 81>; // n x 4 x i64 vector value -def nxv8i64 : ValueType<512, 82>; // n x 8 x i64 vector value -def nxv16i64: ValueType<1024,83>; // n x 16 x i64 vector value -def nxv32i64: ValueType<2048,84>; // n x 32 x i64 vector value +def nxv1i64 : ValueType<64, 86>; // n x 1 x i64 vector value +def nxv2i64 : ValueType<128, 87>; // n x 2 x i64 vector value +def nxv4i64 : ValueType<256, 88>; // n x 4 x i64 vector value +def nxv8i64 : ValueType<512, 89>; // n x 8 x i64 vector value +def nxv16i64: ValueType<1024,90>; // n x 16 x i64 vector value +def nxv32i64: ValueType<2048,91>; // n x 32 x i64 vector value -def v2f16 : ValueType<32 , 85>; // 2 x f16 vector value -def v4f16 : ValueType<64 , 86>; // 4 x f16 vector value -def v8f16 : ValueType<128, 87>; // 8 x f16 vector value -def v1f32 : ValueType<32 , 88>; // 1 x f32 vector value -def v2f32 : ValueType<64 , 89>; // 2 x f32 vector value -def v4f32 : ValueType<128, 90>; // 4 x f32 vector value -def v8f32 : ValueType<256, 91>; // 8 x f32 vector value -def v16f32 : ValueType<512, 92>; // 16 x f32 vector value -def v1f64 : ValueType<64, 93>; // 1 x f64 vector value -def v2f64 : ValueType<128, 94>; // 2 x f64 vector value -def v4f64 : ValueType<256, 95>; // 4 x f64 vector value -def v8f64 : ValueType<512, 96>; // 8 x f64 vector value +def v2f16 : ValueType<32 , 92>; // 2 x f16 vector value +def v4f16 : ValueType<64 , 93>; // 4 x f16 vector value +def v8f16 : ValueType<128, 94>; // 8 x f16 vector value +def v1f32 : ValueType<32 , 95>; // 1 x f32 vector value +def v2f32 : ValueType<64 , 96>; // 2 x f32 vector value +def v3f32 : ValueType<96 , 97>; // 3 x f32 vector value +def v4f32 : ValueType<128, 98>; // 4 x f32 vector value +def v5f32 : ValueType<160, 99>; // 5 x f32 vector value +def v8f32 : ValueType<256, 100>; // 8 x f32 vector value +def v16f32 : ValueType<512, 101>; // 16 x f32 vector value +def v32f32 : ValueType<1024, 102>; // 32 x f32 vector value +def v64f32 : ValueType<2048, 103>; // 64 x f32 vector value +def v128f32 : ValueType<4096, 104>; // 128 x f32 vector value +def v256f32 : ValueType<8182, 105>; // 256 x f32 vector value +def v512f32 : ValueType<16384, 106>; // 512 x f32 vector value +def v1024f32 : ValueType<32768, 107>; // 1024 x f32 vector value +def v2048f32 : ValueType<65536, 108>; // 2048 x f32 vector value +def v1f64 : ValueType<64, 109>; // 1 x f64 vector value +def v2f64 : ValueType<128, 110>; // 2 x f64 vector value +def v4f64 : ValueType<256, 111>; // 4 x f64 vector value +def v8f64 : ValueType<512, 112>; // 8 x f64 vector value -def nxv2f16 : ValueType<32 , 97>; // n x 2 x f16 vector value -def nxv4f16 : ValueType<64 , 98>; // n x 4 x f16 vector value -def nxv8f16 : ValueType<128, 99>; // n x 8 x f16 vector value -def nxv1f32 : ValueType<32 , 100>; // n x 1 x f32 vector value -def nxv2f32 : ValueType<64 , 101>; // n x 2 x f32 vector value -def nxv4f32 : ValueType<128, 102>; // n x 4 x f32 vector value -def nxv8f32 : ValueType<256, 103>; // n x 8 x f32 vector value -def nxv16f32 : ValueType<512, 104>; // n x 16 x f32 vector value -def nxv1f64 : ValueType<64, 105>; // n x 1 x f64 vector value -def nxv2f64 : ValueType<128, 106>; // n x 2 x f64 vector value -def nxv4f64 : ValueType<256, 107>; // n x 4 x f64 vector value -def nxv8f64 : ValueType<512, 108>; // n x 8 x f64 vector value +def nxv2f16 : ValueType<32 , 113>; // n x 2 x f16 vector value +def nxv4f16 : ValueType<64 , 114>; // n x 4 x f16 vector value +def nxv8f16 : ValueType<128, 115>; // n x 8 x f16 vector value +def nxv1f32 : ValueType<32 , 116>; // n x 1 x f32 vector value +def nxv2f32 : ValueType<64 , 117>; // n x 2 x f32 vector value +def nxv4f32 : ValueType<128, 118>; // n x 4 x f32 vector value +def nxv8f32 : ValueType<256, 119>; // n x 8 x f32 vector value +def nxv16f32 : ValueType<512, 120>; // n x 16 x f32 vector value +def nxv1f64 : ValueType<64, 121>; // n x 1 x f64 vector value +def nxv2f64 : ValueType<128, 122>; // n x 2 x f64 vector value +def nxv4f64 : ValueType<256, 123>; // n x 4 x f64 vector value +def nxv8f64 : ValueType<512, 124>; // n x 8 x f64 vector value -def x86mmx : ValueType<64 , 109>; // X86 MMX value -def FlagVT : ValueType<0 , 110>; // Pre-RA sched glue -def isVoid : ValueType<0 , 111>; // Produces no value -def untyped: ValueType<8 , 112>; // Produces an untyped value -def ExceptRef: ValueType<0, 113>; // WebAssembly's except_ref type +def x86mmx : ValueType<64 , 125>; // X86 MMX value +def FlagVT : ValueType<0 , 126>; // Pre-RA sched glue +def isVoid : ValueType<0 , 127>; // Produces no value +def untyped: ValueType<8 , 128>; // Produces an untyped value +def exnref: ValueType<0, 129>; // WebAssembly's exnref type def token : ValueType<0 , 248>; // TokenTy def MetadataVT: ValueType<0, 249>; // Metadata @@ -167,3 +182,14 @@ def iPTR : ValueType<0 , 254>; // Pseudo valuetype to represent "any type of any size". def Any : ValueType<0 , 255>; + +/// This class is for targets that want to use pointer types in patterns +/// with the GlobalISelEmitter. Targets must define their own pointer +/// derived from this class. The scalar argument should be an +/// integer type with the same bit size as the ponter. +/// e.g. def p0 : PtrValueType <i64, 0>; + +class PtrValueType <ValueType scalar, int addrspace> : + ValueType<scalar.Size, scalar.Value> { + int AddrSpace = addrspace; +} diff --git a/include/llvm/CodeGen/VirtRegMap.h b/include/llvm/CodeGen/VirtRegMap.h index 6a8e50a7e5f5..70eb048f05eb 100644 --- a/include/llvm/CodeGen/VirtRegMap.h +++ b/include/llvm/CodeGen/VirtRegMap.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/VirtRegMap.h - Virtual Register Map ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -68,8 +67,10 @@ class TargetInstrInfo; public: static char ID; - VirtRegMap() : MachineFunctionPass(ID), Virt2PhysMap(NO_PHYS_REG), - Virt2StackSlotMap(NO_STACK_SLOT), Virt2SplitMap(0) {} + VirtRegMap() + : MachineFunctionPass(ID), MRI(nullptr), TII(nullptr), TRI(nullptr), + MF(nullptr), Virt2PhysMap(NO_PHYS_REG), + Virt2StackSlotMap(NO_STACK_SLOT), Virt2SplitMap(0) {} VirtRegMap(const VirtRegMap &) = delete; VirtRegMap &operator=(const VirtRegMap &) = delete; @@ -98,8 +99,8 @@ class TargetInstrInfo; /// returns the physical register mapped to the specified /// virtual register - unsigned getPhys(unsigned virtReg) const { - assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + Register getPhys(Register virtReg) const { + assert(virtReg.isVirtual()); return Virt2PhysMap[virtReg]; } diff --git a/include/llvm/CodeGen/WasmEHFuncInfo.h b/include/llvm/CodeGen/WasmEHFuncInfo.h index 219fff988f6e..887a1467b3e4 100644 --- a/include/llvm/CodeGen/WasmEHFuncInfo.h +++ b/include/llvm/CodeGen/WasmEHFuncInfo.h @@ -1,9 +1,8 @@ //===--- llvm/CodeGen/WasmEHFuncInfo.h --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -29,10 +28,6 @@ struct WasmEHFuncInfo { // When there is an entry <A, B>, if an exception is not caught by A, it // should next unwind to the EH pad B. DenseMap<BBOrMBB, BBOrMBB> EHPadUnwindMap; - // For entry <A, B>, A is a BB with an instruction that may throw - // (invoke/cleanupret in LLVM IR, call/rethrow in the backend) and B is an EH - // pad that A unwinds to. - DenseMap<BBOrMBB, BBOrMBB> ThrowUnwindMap; // Helper functions const BasicBlock *getEHPadUnwindDest(const BasicBlock *BB) const { @@ -41,18 +36,9 @@ struct WasmEHFuncInfo { void setEHPadUnwindDest(const BasicBlock *BB, const BasicBlock *Dest) { EHPadUnwindMap[BB] = Dest; } - const BasicBlock *getThrowUnwindDest(BasicBlock *BB) const { - return ThrowUnwindMap.lookup(BB).get<const BasicBlock *>(); - } - void setThrowUnwindDest(const BasicBlock *BB, const BasicBlock *Dest) { - ThrowUnwindMap[BB] = Dest; - } bool hasEHPadUnwindDest(const BasicBlock *BB) const { return EHPadUnwindMap.count(BB); } - bool hasThrowUnwindDest(const BasicBlock *BB) const { - return ThrowUnwindMap.count(BB); - } MachineBasicBlock *getEHPadUnwindDest(MachineBasicBlock *MBB) const { return EHPadUnwindMap.lookup(MBB).get<MachineBasicBlock *>(); @@ -60,18 +46,9 @@ struct WasmEHFuncInfo { void setEHPadUnwindDest(MachineBasicBlock *MBB, MachineBasicBlock *Dest) { EHPadUnwindMap[MBB] = Dest; } - MachineBasicBlock *getThrowUnwindDest(MachineBasicBlock *MBB) const { - return ThrowUnwindMap.lookup(MBB).get<MachineBasicBlock *>(); - } - void setThrowUnwindDest(MachineBasicBlock *MBB, MachineBasicBlock *Dest) { - ThrowUnwindMap[MBB] = Dest; - } bool hasEHPadUnwindDest(MachineBasicBlock *MBB) const { return EHPadUnwindMap.count(MBB); } - bool hasThrowUnwindDest(MachineBasicBlock *MBB) const { - return ThrowUnwindMap.count(MBB); - } }; // Analyze the IR in the given function to build WasmEHFuncInfo. diff --git a/include/llvm/CodeGen/WinEHFuncInfo.h b/include/llvm/CodeGen/WinEHFuncInfo.h index 8043024626a0..f098316de793 100644 --- a/include/llvm/CodeGen/WinEHFuncInfo.h +++ b/include/llvm/CodeGen/WinEHFuncInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/WinEHFuncInfo.h -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // |
