summaryrefslogtreecommitdiff
path: root/include/llvm/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/CodeGen')
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h4
-rw-r--r--include/llvm/CodeGen/BasicTTIImpl.h2
-rw-r--r--include/llvm/CodeGen/GlobalISel/InstructionSelector.h158
-rw-r--r--include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h337
-rw-r--r--include/llvm/CodeGen/GlobalISel/LegalizerHelper.h8
-rw-r--r--include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h53
-rw-r--r--include/llvm/CodeGen/LiveRegUnits.h10
-rw-r--r--include/llvm/CodeGen/MachineFunction.h2
-rw-r--r--include/llvm/CodeGen/MachineMemOperand.h15
-rw-r--r--include/llvm/CodeGen/RuntimeLibcalls.h23
-rw-r--r--include/llvm/CodeGen/ScheduleDAG.h8
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h4
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h8
13 files changed, 607 insertions, 25 deletions
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index c898667f1474..60bbc9aaa5bd 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -608,8 +608,8 @@ private:
// Internal Implementation Details
//===------------------------------------------------------------------===//
- /// This emits visibility information about symbol, if this is suported by the
- /// target.
+ /// This emits visibility information about symbol, if this is supported by
+ /// the target.
void EmitVisibility(MCSymbol *Sym, unsigned Visibility,
bool IsDefinition = true) const;
diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h
index a740df96899d..b59fd60e8aed 100644
--- a/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/include/llvm/CodeGen/BasicTTIImpl.h
@@ -428,7 +428,7 @@ public:
std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(DL, Ty);
- bool IsFloat = Ty->getScalarType()->isFloatingPointTy();
+ bool IsFloat = Ty->isFPOrFPVectorTy();
// Assume that floating point arithmetic operations cost twice as much as
// integer operations.
unsigned OpCost = (IsFloat ? 2 : 1);
diff --git a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
index ec60123e54b1..59a4073646eb 100644
--- a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
+++ b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
@@ -16,14 +16,17 @@
#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
+#include "llvm/ADT/SmallVector.h"
#include <bitset>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <initializer_list>
+#include <vector>
namespace llvm {
+class LLT;
class MachineInstr;
class MachineInstrBuilder;
class MachineOperand;
@@ -58,6 +61,131 @@ public:
}
};
+enum {
+ /// Record the specified instruction
+ /// - NewInsnID - Instruction ID to define
+ /// - InsnID - Instruction ID
+ /// - OpIdx - Operand index
+ GIM_RecordInsn,
+
+ /// Check the feature bits
+ /// - Expected features
+ GIM_CheckFeatures,
+
+ /// Check the opcode on the specified instruction
+ /// - InsnID - Instruction ID
+ /// - Expected opcode
+ GIM_CheckOpcode,
+ /// Check the instruction has the right number of operands
+ /// - InsnID - Instruction ID
+ /// - Expected number of operands
+ GIM_CheckNumOperands,
+
+ /// Check the type for the specified operand
+ /// - InsnID - Instruction ID
+ /// - OpIdx - Operand index
+ /// - Expected type
+ GIM_CheckType,
+ /// Check the register bank for the specified operand
+ /// - InsnID - Instruction ID
+ /// - OpIdx - Operand index
+ /// - Expected register bank (specified as a register class)
+ GIM_CheckRegBankForClass,
+ /// Check the operand matches a complex predicate
+ /// - InsnID - Instruction ID
+ /// - OpIdx - Operand index
+ /// - RendererID - The renderer to hold the result
+ /// - Complex predicate ID
+ GIM_CheckComplexPattern,
+ /// Check the operand is a specific integer
+ /// - InsnID - Instruction ID
+ /// - OpIdx - Operand index
+ /// - Expected integer
+ GIM_CheckConstantInt,
+ /// Check the operand is a specific literal integer (i.e. MO.isImm() or MO.isCImm() is true).
+ /// - InsnID - Instruction ID
+ /// - OpIdx - Operand index
+ /// - Expected integer
+ GIM_CheckLiteralInt,
+ /// Check the operand is a specific intrinsic ID
+ /// - InsnID - Instruction ID
+ /// - OpIdx - Operand index
+ /// - Expected Intrinsic ID
+ GIM_CheckIntrinsicID,
+ /// Check the specified operand is an MBB
+ /// - InsnID - Instruction ID
+ /// - OpIdx - Operand index
+ GIM_CheckIsMBB,
+
+ /// Check if the specified operand is safe to fold into the current
+ /// instruction.
+ /// - InsnID - Instruction ID
+ GIM_CheckIsSafeToFold,
+
+ //=== Renderers ===
+
+ /// Mutate an instruction
+ /// - NewInsnID - Instruction ID to define
+ /// - OldInsnID - Instruction ID to mutate
+ /// - NewOpcode - The new opcode to use
+ GIR_MutateOpcode,
+ /// Build a new instruction
+ /// - InsnID - Instruction ID to define
+ /// - Opcode - The new opcode to use
+ GIR_BuildMI,
+
+ /// Copy an operand to the specified instruction
+ /// - NewInsnID - Instruction ID to modify
+ /// - OldInsnID - Instruction ID to copy from
+ /// - OpIdx - The operand to copy
+ GIR_Copy,
+ /// Copy an operand to the specified instruction
+ /// - NewInsnID - Instruction ID to modify
+ /// - OldInsnID - Instruction ID to copy from
+ /// - OpIdx - The operand to copy
+ /// - SubRegIdx - The subregister to copy
+ GIR_CopySubReg,
+ /// Add an implicit register def to the specified instruction
+ /// - InsnID - Instruction ID to modify
+ /// - RegNum - The register to add
+ GIR_AddImplicitDef,
+ /// Add an implicit register use to the specified instruction
+ /// - InsnID - Instruction ID to modify
+ /// - RegNum - The register to add
+ GIR_AddImplicitUse,
+ /// Add an register to the specified instruction
+ /// - InsnID - Instruction ID to modify
+ /// - RegNum - The register to add
+ GIR_AddRegister,
+ /// Add an immediate to the specified instruction
+ /// - InsnID - Instruction ID to modify
+ /// - Imm - The immediate to add
+ GIR_AddImm,
+ /// Render complex operands to the specified instruction
+ /// - InsnID - Instruction ID to modify
+ /// - RendererID - The renderer to call
+ GIR_ComplexRenderer,
+
+ /// Constrain an instruction operand to a register class.
+ /// - InsnID - Instruction ID to modify
+ /// - OpIdx - Operand index
+ /// - RCEnum - Register class enumeration value
+ GIR_ConstrainOperandRC,
+ /// Constrain an instructions operands according to the instruction
+ /// description.
+ /// - InsnID - Instruction ID to modify
+ GIR_ConstrainSelectedInstOperands,
+ /// Merge all memory operands into instruction.
+ /// - InsnID - Instruction ID to modify
+ GIR_MergeMemOperands,
+ /// Erase from parent.
+ /// - InsnID - Instruction ID to erase
+ GIR_EraseFromParent,
+
+ /// A successful emission
+ GIR_Done,
+};
+
/// Provides the logic to select generic machine instructions.
class InstructionSelector {
public:
@@ -78,9 +206,39 @@ public:
protected:
using ComplexRendererFn = std::function<void(MachineInstrBuilder &)>;
+ using RecordedMIVector = SmallVector<MachineInstr *, 4>;
+ using NewMIVector = SmallVector<MachineInstrBuilder, 4>;
+
+ struct MatcherState {
+ std::vector<ComplexRendererFn> Renderers;
+ RecordedMIVector MIs;
+
+ MatcherState(unsigned MaxRenderers);
+ };
+public:
+ template <class PredicateBitset, class ComplexMatcherMemFn>
+ struct MatcherInfoTy {
+ const LLT *TypeObjects;
+ const PredicateBitset *FeatureBitsets;
+ const std::vector<ComplexMatcherMemFn> ComplexPredicates;
+ };
+
+protected:
InstructionSelector();
+ /// Execute a given matcher table and return true if the match was successful
+ /// and false otherwise.
+ template <class TgtInstructionSelector, class PredicateBitset,
+ class ComplexMatcherMemFn>
+ bool executeMatchTable(
+ TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State,
+ const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> &MatcherInfo,
+ const int64_t *MatchTable, const TargetInstrInfo &TII,
+ MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
+ const RegisterBankInfo &RBI,
+ const PredicateBitset &AvailableFeatures) const;
+
/// Constrain a register operand of an instruction \p I to a specified
/// register class. This could involve inserting COPYs before (for uses) or
/// after (for defs) and may replace the operand of \p I.
diff --git a/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h b/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
new file mode 100644
index 000000000000..98b6b859b9e2
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
@@ -0,0 +1,337 @@
+//==-- 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.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file declares the API for the instruction selector.
+/// This class is responsible for selecting machine instructions.
+/// It's implemented by the target. It's used by the InstructionSelect pass.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
+#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
+
+namespace llvm {
+template <class TgtInstructionSelector, class PredicateBitset,
+ class ComplexMatcherMemFn>
+bool InstructionSelector::executeMatchTable(
+ TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State,
+ const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> &MatcherInfo,
+ const int64_t *MatchTable, const TargetInstrInfo &TII,
+ MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
+ const RegisterBankInfo &RBI,
+ const PredicateBitset &AvailableFeatures) const {
+ const int64_t *Command = MatchTable;
+ while (true) {
+ switch (*Command++) {
+ case GIM_RecordInsn: {
+ int64_t NewInsnID = *Command++;
+ int64_t InsnID = *Command++;
+ int64_t OpIdx = *Command++;
+
+ // As an optimisation we require that MIs[0] is always the root. Refuse
+ // any attempt to modify it.
+ assert(NewInsnID != 0 && "Refusing to modify MIs[0]");
+ (void)NewInsnID;
+
+ MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
+ if (!MO.isReg()) {
+ DEBUG(dbgs() << "Rejected (not a register)\n");
+ return false;
+ }
+ if (TRI.isPhysicalRegister(MO.getReg())) {
+ DEBUG(dbgs() << "Rejected (is a physical register)\n");
+ return false;
+ }
+
+ assert((size_t)NewInsnID == State.MIs.size() &&
+ "Expected to store MIs in order");
+ State.MIs.push_back(MRI.getVRegDef(MO.getReg()));
+ DEBUG(dbgs() << "MIs[" << NewInsnID << "] = GIM_RecordInsn(" << InsnID
+ << ", " << OpIdx << ")\n");
+ break;
+ }
+
+ case GIM_CheckFeatures: {
+ int64_t ExpectedBitsetID = *Command++;
+ DEBUG(dbgs() << "GIM_CheckFeatures(ExpectedBitsetID=" << ExpectedBitsetID
+ << ")\n");
+ if ((AvailableFeatures & MatcherInfo.FeatureBitsets[ExpectedBitsetID]) !=
+ MatcherInfo.FeatureBitsets[ExpectedBitsetID]) {
+ DEBUG(dbgs() << "Rejected\n");
+ return false;
+ }
+ break;
+ }
+
+ case GIM_CheckOpcode: {
+ int64_t InsnID = *Command++;
+ int64_t Expected = *Command++;
+
+ unsigned Opcode = State.MIs[InsnID]->getOpcode();
+ DEBUG(dbgs() << "GIM_CheckOpcode(MIs[" << InsnID << "], ExpectedOpcode="
+ << Expected << ") // Got=" << Opcode << "\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ if (Opcode != Expected)
+ return false;
+ break;
+ }
+ case GIM_CheckNumOperands: {
+ int64_t InsnID = *Command++;
+ int64_t Expected = *Command++;
+ DEBUG(dbgs() << "GIM_CheckNumOperands(MIs[" << InsnID
+ << "], Expected=" << Expected << ")\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ if (State.MIs[InsnID]->getNumOperands() != Expected)
+ return false;
+ break;
+ }
+
+ case GIM_CheckType: {
+ int64_t InsnID = *Command++;
+ int64_t OpIdx = *Command++;
+ int64_t TypeID = *Command++;
+ DEBUG(dbgs() << "GIM_CheckType(MIs[" << InsnID << "]->getOperand("
+ << OpIdx << "), TypeID=" << TypeID << ")\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ if (MRI.getType(State.MIs[InsnID]->getOperand(OpIdx).getReg()) !=
+ MatcherInfo.TypeObjects[TypeID])
+ return false;
+ break;
+ }
+ case GIM_CheckRegBankForClass: {
+ int64_t InsnID = *Command++;
+ int64_t OpIdx = *Command++;
+ int64_t RCEnum = *Command++;
+ DEBUG(dbgs() << "GIM_CheckRegBankForClass(MIs[" << InsnID
+ << "]->getOperand(" << OpIdx << "), RCEnum=" << RCEnum
+ << ")\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ if (&RBI.getRegBankFromRegClass(*TRI.getRegClass(RCEnum)) !=
+ RBI.getRegBank(State.MIs[InsnID]->getOperand(OpIdx).getReg(), MRI, TRI))
+ return false;
+ break;
+ }
+ case GIM_CheckComplexPattern: {
+ int64_t InsnID = *Command++;
+ int64_t OpIdx = *Command++;
+ int64_t RendererID = *Command++;
+ int64_t ComplexPredicateID = *Command++;
+ DEBUG(dbgs() << "State.Renderers[" << RendererID
+ << "] = GIM_CheckComplexPattern(MIs[" << InsnID
+ << "]->getOperand(" << OpIdx
+ << "), ComplexPredicateID=" << ComplexPredicateID << ")\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ // FIXME: Use std::invoke() when it's available.
+ if (!(State.Renderers[RendererID] =
+ (ISel.*MatcherInfo.ComplexPredicates[ComplexPredicateID])(
+ State.MIs[InsnID]->getOperand(OpIdx))))
+ return false;
+ break;
+ }
+ case GIM_CheckConstantInt: {
+ int64_t InsnID = *Command++;
+ int64_t OpIdx = *Command++;
+ int64_t Value = *Command++;
+ DEBUG(dbgs() << "GIM_CheckConstantInt(MIs[" << InsnID << "]->getOperand("
+ << OpIdx << "), Value=" << Value << ")\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ if (!isOperandImmEqual(State.MIs[InsnID]->getOperand(OpIdx), Value, MRI))
+ return false;
+ break;
+ }
+ case GIM_CheckLiteralInt: {
+ int64_t InsnID = *Command++;
+ int64_t OpIdx = *Command++;
+ int64_t Value = *Command++;
+ DEBUG(dbgs() << "GIM_CheckLiteralInt(MIs[" << InsnID << "]->getOperand(" << OpIdx
+ << "), Value=" << Value << ")\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ MachineOperand &OM = State.MIs[InsnID]->getOperand(OpIdx);
+ if (!OM.isCImm() || !OM.getCImm()->equalsInt(Value))
+ return false;
+ break;
+ }
+ case GIM_CheckIntrinsicID: {
+ int64_t InsnID = *Command++;
+ int64_t OpIdx = *Command++;
+ int64_t Value = *Command++;
+ DEBUG(dbgs() << "GIM_CheckIntrinsicID(MIs[" << InsnID << "]->getOperand(" << OpIdx
+ << "), Value=" << Value << ")\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ MachineOperand &OM = State.MIs[InsnID]->getOperand(OpIdx);
+ if (!OM.isIntrinsicID() || OM.getIntrinsicID() != Value)
+ return false;
+ break;
+ }
+ case GIM_CheckIsMBB: {
+ int64_t InsnID = *Command++;
+ int64_t OpIdx = *Command++;
+ DEBUG(dbgs() << "GIM_CheckIsMBB(MIs[" << InsnID << "]->getOperand("
+ << OpIdx << "))\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ if (!State.MIs[InsnID]->getOperand(OpIdx).isMBB())
+ return false;
+ break;
+ }
+
+ case GIM_CheckIsSafeToFold: {
+ int64_t InsnID = *Command++;
+ DEBUG(dbgs() << "GIM_CheckIsSafeToFold(MIs[" << InsnID << "])\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ if (!isObviouslySafeToFold(*State.MIs[InsnID]))
+ return false;
+ break;
+ }
+
+ case GIR_MutateOpcode: {
+ int64_t OldInsnID = *Command++;
+ int64_t NewInsnID = *Command++;
+ int64_t NewOpcode = *Command++;
+ assert((size_t)NewInsnID == OutMIs.size() &&
+ "Expected to store MIs in order");
+ OutMIs.push_back(
+ MachineInstrBuilder(*State.MIs[OldInsnID]->getParent()->getParent(),
+ State.MIs[OldInsnID]));
+ OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode));
+ DEBUG(dbgs() << "GIR_MutateOpcode(OutMIs[" << NewInsnID << "], MIs["
+ << OldInsnID << "], " << NewOpcode << ")\n");
+ break;
+ }
+ case GIR_BuildMI: {
+ int64_t InsnID = *Command++;
+ int64_t Opcode = *Command++;
+ assert((size_t)InsnID == OutMIs.size() &&
+ "Expected to store MIs in order");
+ (void)InsnID;
+ OutMIs.push_back(BuildMI(*State.MIs[0]->getParent(), State.MIs[0],
+ State.MIs[0]->getDebugLoc(), TII.get(Opcode)));
+ DEBUG(dbgs() << "GIR_BuildMI(OutMIs[" << InsnID << "], " << Opcode
+ << ")\n");
+ break;
+ }
+
+ case GIR_Copy: {
+ int64_t NewInsnID = *Command++;
+ int64_t OldInsnID = *Command++;
+ int64_t OpIdx = *Command++;
+ assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
+ OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(OpIdx));
+ DEBUG(dbgs() << "GIR_Copy(OutMIs[" << NewInsnID << "], MIs[" << OldInsnID
+ << "], " << OpIdx << ")\n");
+ break;
+ }
+ case GIR_CopySubReg: {
+ int64_t NewInsnID = *Command++;
+ int64_t OldInsnID = *Command++;
+ int64_t OpIdx = *Command++;
+ int64_t SubRegIdx = *Command++;
+ assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
+ OutMIs[NewInsnID].addReg(State.MIs[OldInsnID]->getOperand(OpIdx).getReg(),
+ 0, SubRegIdx);
+ DEBUG(dbgs() << "GIR_CopySubReg(OutMIs[" << NewInsnID << "], MIs["
+ << OldInsnID << "], " << OpIdx << ", " << SubRegIdx
+ << ")\n");
+ break;
+ }
+ case GIR_AddImplicitDef: {
+ int64_t InsnID = *Command++;
+ int64_t RegNum = *Command++;
+ assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+ OutMIs[InsnID].addDef(RegNum, RegState::Implicit);
+ DEBUG(dbgs() << "GIR_AddImplicitDef(OutMIs[" << InsnID << "], " << RegNum
+ << ")\n");
+ break;
+ }
+ case GIR_AddImplicitUse: {
+ int64_t InsnID = *Command++;
+ int64_t RegNum = *Command++;
+ assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+ OutMIs[InsnID].addUse(RegNum, RegState::Implicit);
+ DEBUG(dbgs() << "GIR_AddImplicitUse(OutMIs[" << InsnID << "], " << RegNum
+ << ")\n");
+ break;
+ }
+ case GIR_AddRegister: {
+ int64_t InsnID = *Command++;
+ int64_t RegNum = *Command++;
+ assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+ OutMIs[InsnID].addReg(RegNum);
+ DEBUG(dbgs() << "GIR_AddRegister(OutMIs[" << InsnID << "], " << RegNum
+ << ")\n");
+ break;
+ }
+ case GIR_AddImm: {
+ int64_t InsnID = *Command++;
+ int64_t Imm = *Command++;
+ assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+ OutMIs[InsnID].addImm(Imm);
+ DEBUG(dbgs() << "GIR_AddImm(OutMIs[" << InsnID << "], " << Imm << ")\n");
+ break;
+ }
+ case GIR_ComplexRenderer: {
+ int64_t InsnID = *Command++;
+ int64_t RendererID = *Command++;
+ assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+ State.Renderers[RendererID](OutMIs[InsnID]);
+ DEBUG(dbgs() << "GIR_ComplexRenderer(OutMIs[" << InsnID << "], "
+ << RendererID << ")\n");
+ break;
+ }
+
+ case GIR_ConstrainOperandRC: {
+ int64_t InsnID = *Command++;
+ int64_t OpIdx = *Command++;
+ int64_t RCEnum = *Command++;
+ assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+ constrainOperandRegToRegClass(*OutMIs[InsnID].getInstr(), OpIdx,
+ *TRI.getRegClass(RCEnum), TII, TRI, RBI);
+ DEBUG(dbgs() << "GIR_ConstrainOperandRC(OutMIs[" << InsnID << "], "
+ << OpIdx << ", " << RCEnum << ")\n");
+ break;
+ }
+ case GIR_ConstrainSelectedInstOperands: {
+ int64_t InsnID = *Command++;
+ assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+ constrainSelectedInstRegOperands(*OutMIs[InsnID].getInstr(), TII, TRI,
+ RBI);
+ DEBUG(dbgs() << "GIR_ConstrainSelectedInstOperands(OutMIs[" << InsnID
+ << "])\n");
+ break;
+ }
+ case GIR_MergeMemOperands: {
+ int64_t InsnID = *Command++;
+ assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+ for (const auto *FromMI : State.MIs)
+ for (const auto &MMO : FromMI->memoperands())
+ OutMIs[InsnID].addMemOperand(MMO);
+ DEBUG(dbgs() << "GIR_MergeMemOperands(OutMIs[" << InsnID << "])\n");
+ break;
+ }
+ case GIR_EraseFromParent: {
+ int64_t InsnID = *Command++;
+ assert(State.MIs[InsnID] &&
+ "Attempted to erase an undefined instruction");
+ State.MIs[InsnID]->eraseFromParent();
+ DEBUG(dbgs() << "GIR_EraseFromParent(MIs[" << InsnID << "])\n");
+ break;
+ }
+
+ case GIR_Done:
+ DEBUG(dbgs() << "GIR_Done");
+ return true;
+
+ default:
+ llvm_unreachable("Unexpected command");
+ }
+ }
+}
+
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
diff --git a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index 5197ba869c0a..1fd45b52e3ac 100644
--- a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -101,11 +101,11 @@ private:
const LegalizerInfo &LI;
};
-/// Helper function that replaces \p MI with a libcall.
+/// Helper function that creates the given libcall.
LegalizerHelper::LegalizeResult
-replaceWithLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder,
- RTLIB::Libcall Libcall, const CallLowering::ArgInfo &Result,
- ArrayRef<CallLowering::ArgInfo> Args);
+createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
+ const CallLowering::ArgInfo &Result,
+ ArrayRef<CallLowering::ArgInfo> Args);
} // End namespace llvm.
diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index c9327d50432e..85e6fef1f3c2 100644
--- a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -19,6 +19,7 @@
#include "llvm/CodeGen/LowLevelType.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugLoc.h"
@@ -59,6 +60,21 @@ class MachineIRBuilder {
}
void validateTruncExt(unsigned Dst, unsigned Src, bool IsExtend);
+ MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Res, unsigned Op0, unsigned Op1);
+
+ unsigned getDestFromArg(unsigned Reg) { return Reg; }
+ unsigned getDestFromArg(LLT Ty) {
+ return getMF().getRegInfo().createGenericVirtualRegister(Ty);
+ }
+ unsigned getDestFromArg(const TargetRegisterClass *RC) {
+ return getMF().getRegInfo().createVirtualRegister(RC);
+ }
+
+ unsigned getRegFromArg(unsigned Reg) { return Reg; }
+
+ unsigned getRegFromArg(const MachineInstrBuilder &MIB) {
+ return MIB->getOperand(0).getReg();
+ }
public:
/// Getter for the function we currently build.
@@ -120,6 +136,22 @@ public:
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildInstr(unsigned Opcode);
+ /// DAG like Generic method for building arbitrary instructions as above.
+ /// \Opc opcode for the instruction.
+ /// \Ty Either LLT/TargetRegisterClass/unsigned types for Dst
+ /// \Args Variadic list of uses of types(unsigned/MachineInstrBuilder)
+ /// Uses of type MachineInstrBuilder will perform
+ /// getOperand(0).getReg() to convert to register.
+ template <typename DstTy, typename... UseArgsTy>
+ MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty,
+ UseArgsTy &&... Args) {
+ auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty));
+ unsigned It[] = {(getRegFromArg(Args))...};
+ for (const auto &i : It)
+ MIB.addUse(i);
+ return MIB;
+ }
+
/// Build but don't insert <empty> = \p Opcode <empty>.
///
/// \pre setMF, setBasicBlock or setMI must have been called.
@@ -188,6 +220,11 @@ public:
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildAdd(unsigned Res, unsigned Op0,
unsigned Op1);
+ template <typename DstTy, typename... UseArgsTy>
+ MachineInstrBuilder buildAdd(DstTy &&Ty, UseArgsTy &&... UseArgs) {
+ unsigned Res = getDestFromArg(Ty);
+ return buildAdd(Res, (getRegFromArg(UseArgs))...);
+ }
/// Build and insert \p Res<def> = G_SUB \p Op0, \p Op1
///
@@ -295,6 +332,18 @@ public:
MachineInstrBuilder buildAnd(unsigned Res, unsigned Op0,
unsigned Op1);
+ /// Build and insert \p Res<def> = G_OR \p Op0, \p Op1
+ ///
+ /// G_OR sets \p Res to the bitwise or of integer parameters \p Op0 and \p
+ /// Op1.
+ ///
+ /// \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 or vector) type).
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildOr(unsigned Res, unsigned Op0, unsigned Op1);
+
/// Build and insert \p Res<def> = G_ANYEXT \p Op0
///
/// G_ANYEXT produces a register of the specified width, with bits 0 to
@@ -416,6 +465,10 @@ public:
/// \return The newly created instruction.
MachineInstrBuilder buildConstant(unsigned Res, int64_t Val);
+ template <typename DstType>
+ MachineInstrBuilder buildConstant(DstType &&Res, int64_t Val) {
+ return buildConstant(getDestFromArg(Res), Val);
+ }
/// Build and insert \p Res = G_FCONSTANT \p Val
///
/// G_FCONSTANT is a floating-point constant with the specified size and
diff --git a/include/llvm/CodeGen/LiveRegUnits.h b/include/llvm/CodeGen/LiveRegUnits.h
index fa1ec867ea3d..c28b1a06854f 100644
--- a/include/llvm/CodeGen/LiveRegUnits.h
+++ b/include/llvm/CodeGen/LiveRegUnits.h
@@ -93,12 +93,14 @@ public:
}
/// Updates liveness when stepping backwards over the instruction \p MI.
+ /// This removes all register units defined or clobbered in \p MI and then
+ /// adds the units used (as in use operands) in \p MI.
void stepBackward(const MachineInstr &MI);
- /// Mark all register units live during instruction \p MI.
- /// This can be used to accumulate live/unoccupied registers over a range of
- /// instructions.
- void accumulateBackward(const MachineInstr &MI);
+ /// Adds all register units used, defined or clobbered in \p MI.
+ /// This is useful when walking over a range of instruction to find registers
+ /// unused over the whole range.
+ void accumulate(const MachineInstr &MI);
/// Adds registers living out of block \p MBB.
/// Live out registers are the union of the live-in registers of the successor
diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h
index f67da7b01c54..19173fa39bdc 100644
--- a/include/llvm/CodeGen/MachineFunction.h
+++ b/include/llvm/CodeGen/MachineFunction.h
@@ -650,7 +650,7 @@ public:
MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s,
unsigned base_alignment, const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr,
- SynchronizationScope SynchScope = CrossThread,
+ SyncScope::ID SSID = SyncScope::System,
AtomicOrdering Ordering = AtomicOrdering::NotAtomic,
AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic);
diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h
index 78adce507b8c..a9de0db05d72 100644
--- a/include/llvm/CodeGen/MachineMemOperand.h
+++ b/include/llvm/CodeGen/MachineMemOperand.h
@@ -114,6 +114,9 @@ public:
MOInvariant = 1u << 5,
// Reserved for use by target-specific passes.
+ // Targets may override getSerializableMachineMemOperandTargetFlags() to
+ // enable MIR serialization/parsing of these flags. If more of these flags
+ // are added, the MIR printing/parsing code will need to be updated as well.
MOTargetFlag1 = 1u << 6,
MOTargetFlag2 = 1u << 7,
MOTargetFlag3 = 1u << 8,
@@ -124,8 +127,8 @@ public:
private:
/// Atomic information for this memory operation.
struct MachineAtomicInfo {
- /// Synchronization scope for this memory operation.
- unsigned SynchScope : 1; // enum SynchronizationScope
+ /// Synchronization scope ID for this memory operation.
+ unsigned SSID : 8; // SyncScope::ID
/// Atomic ordering requirements for this memory operation. For cmpxchg
/// atomic operations, atomic ordering requirements when store occurs.
unsigned Ordering : 4; // enum AtomicOrdering
@@ -152,7 +155,7 @@ public:
unsigned base_alignment,
const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr,
- SynchronizationScope SynchScope = CrossThread,
+ SyncScope::ID SSID = SyncScope::System,
AtomicOrdering Ordering = AtomicOrdering::NotAtomic,
AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic);
@@ -202,9 +205,9 @@ public:
/// Return the range tag for the memory reference.
const MDNode *getRanges() const { return Ranges; }
- /// Return the synchronization scope for this memory operation.
- SynchronizationScope getSynchScope() const {
- return static_cast<SynchronizationScope>(AtomicInfo.SynchScope);
+ /// Returns the synchronization scope ID for this memory operation.
+ SyncScope::ID getSyncScopeID() const {
+ return static_cast<SyncScope::ID>(AtomicInfo.SSID);
}
/// Return the atomic ordering requirements for this memory operation. For
diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h
index 8c3aacaa8efc..08151be11083 100644
--- a/include/llvm/CodeGen/RuntimeLibcalls.h
+++ b/include/llvm/CodeGen/RuntimeLibcalls.h
@@ -340,6 +340,18 @@ namespace RTLIB {
MEMCPY_ELEMENT_UNORDERED_ATOMIC_8,
MEMCPY_ELEMENT_UNORDERED_ATOMIC_16,
+ MEMMOVE_ELEMENT_UNORDERED_ATOMIC_1,
+ MEMMOVE_ELEMENT_UNORDERED_ATOMIC_2,
+ MEMMOVE_ELEMENT_UNORDERED_ATOMIC_4,
+ MEMMOVE_ELEMENT_UNORDERED_ATOMIC_8,
+ MEMMOVE_ELEMENT_UNORDERED_ATOMIC_16,
+
+ MEMSET_ELEMENT_UNORDERED_ATOMIC_1,
+ MEMSET_ELEMENT_UNORDERED_ATOMIC_2,
+ MEMSET_ELEMENT_UNORDERED_ATOMIC_4,
+ MEMSET_ELEMENT_UNORDERED_ATOMIC_8,
+ MEMSET_ELEMENT_UNORDERED_ATOMIC_16,
+
// EXCEPTION HANDLING
UNWIND_RESUME,
@@ -515,6 +527,17 @@ namespace RTLIB {
/// MEMCPY_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or
/// UNKNOW_LIBCALL if there is none.
Libcall getMEMCPY_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);
+
+ /// getMEMMOVE_ELEMENT_UNORDERED_ATOMIC - Return
+ /// MEMMOVE_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or
+ /// UNKNOW_LIBCALL if there is none.
+ Libcall getMEMMOVE_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);
+
+ /// getMEMSET_ELEMENT_UNORDERED_ATOMIC - Return
+ /// MEMSET_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or
+ /// UNKNOW_LIBCALL if there is none.
+ Libcall getMEMSET_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);
+
}
}
diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h
index 4d72eda5c71a..25afc5b506df 100644
--- a/include/llvm/CodeGen/ScheduleDAG.h
+++ b/include/llvm/CodeGen/ScheduleDAG.h
@@ -235,6 +235,9 @@ class TargetRegisterInfo;
"SDep::Output edge cannot use the zero register!");
Contents.Reg = Reg;
}
+
+ raw_ostream &print(raw_ostream &O,
+ const TargetRegisterInfo *TRI = nullptr) const;
};
template <>
@@ -458,7 +461,10 @@ class TargetRegisterInfo;
void dump(const ScheduleDAG *G) const;
void dumpAll(const ScheduleDAG *G) const;
- void print(raw_ostream &O, const ScheduleDAG *G) const;
+ raw_ostream &print(raw_ostream &O,
+ const SUnit *N = nullptr,
+ const SUnit *X = nullptr) const;
+ raw_ostream &print(raw_ostream &O, const ScheduleDAG *G) const;
private:
void ComputeDepth();
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index f3f3003b7e20..55a23c3cca9b 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -927,7 +927,7 @@ public:
SDValue Cmp, SDValue Swp, MachinePointerInfo PtrInfo,
unsigned Alignment, AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
- SynchronizationScope SynchScope);
+ SyncScope::ID SSID);
SDValue getAtomicCmpSwap(unsigned Opcode, const SDLoc &dl, EVT MemVT,
SDVTList VTs, SDValue Chain, SDValue Ptr,
SDValue Cmp, SDValue Swp, MachineMemOperand *MMO);
@@ -937,7 +937,7 @@ public:
SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain,
SDValue Ptr, SDValue Val, const Value *PtrVal,
unsigned Alignment, AtomicOrdering Ordering,
- SynchronizationScope SynchScope);
+ SyncScope::ID SSID);
SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain,
SDValue Ptr, SDValue Val, MachineMemOperand *MMO);
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index d9f8af0e21d1..db42fb6c170c 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -1213,8 +1213,8 @@ public:
/// Returns the Ranges that describes the dereference.
const MDNode *getRanges() const { return MMO->getRanges(); }
- /// Return the synchronization scope for this memory operation.
- SynchronizationScope getSynchScope() const { return MMO->getSynchScope(); }
+ /// Returns the synchronization scope ID for this memory operation.
+ SyncScope::ID getSyncScopeID() const { return MMO->getSyncScopeID(); }
/// Return the atomic ordering requirements for this memory operation. For
/// cmpxchg atomic operations, return the atomic ordering requirements when
@@ -1432,8 +1432,8 @@ public:
int64_t getSExtValue() const { return Value->getSExtValue(); }
bool isOne() const { return Value->isOne(); }
- bool isNullValue() const { return Value->isNullValue(); }
- bool isAllOnesValue() const { return Value->isAllOnesValue(); }
+ bool isNullValue() const { return Value->isZero(); }
+ bool isAllOnesValue() const { return Value->isMinusOne(); }
bool isOpaque() const { return ConstantSDNodeBits.IsOpaque; }