mirror of
https://github.com/hedge-dev/XenonRecomp.git
synced 2025-07-27 07:23:56 +00:00
Initial Commit
This commit is contained in:
63
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/CGPassBuilderOption.h
vendored
Normal file
63
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/CGPassBuilderOption.h
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
//===- CGPassBuilderOption.h - Options for pass builder ---------*- 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 CCState and CCValAssign classes, used for lowering
|
||||
// and implementing calling conventions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TARGET_CGPASSBUILDEROPTION_H
|
||||
#define LLVM_TARGET_CGPASSBUILDEROPTION_H
|
||||
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
enum class RunOutliner { TargetDefault, AlwaysOutline, NeverOutline };
|
||||
enum class RegAllocType { Default, Basic, Fast, Greedy, PBQP };
|
||||
enum class CFLAAType { None, Steensgaard, Andersen, Both };
|
||||
|
||||
// Not one-on-one but mostly corresponding to commandline options in
|
||||
// TargetPassConfig.cpp.
|
||||
struct CGPassBuilderOption {
|
||||
Optional<bool> OptimizeRegAlloc;
|
||||
Optional<bool> EnableIPRA;
|
||||
bool DebugPM = false;
|
||||
bool DisableVerify = false;
|
||||
bool EnableImplicitNullChecks = false;
|
||||
bool EnableBlockPlacementStats = false;
|
||||
bool MISchedPostRA = false;
|
||||
bool EarlyLiveIntervals = false;
|
||||
|
||||
bool DisableLSR = false;
|
||||
bool DisableCGP = false;
|
||||
bool PrintLSR = false;
|
||||
bool DisableMergeICmps = false;
|
||||
bool DisablePartialLibcallInlining = false;
|
||||
bool DisableConstantHoisting = false;
|
||||
bool PrintISelInput = false;
|
||||
bool PrintGCInfo = false;
|
||||
bool RequiresCodeGenSCCOrder = false;
|
||||
|
||||
RunOutliner EnableMachineOutliner = RunOutliner::TargetDefault;
|
||||
RegAllocType RegAlloc = RegAllocType::Default;
|
||||
CFLAAType UseCFLAA = CFLAAType::None;
|
||||
Optional<GlobalISelAbortMode> EnableGlobalISelAbort;
|
||||
|
||||
Optional<bool> VerifyMachineCode;
|
||||
Optional<bool> EnableFastISelOption;
|
||||
Optional<bool> EnableGlobalISelOption;
|
||||
};
|
||||
|
||||
CGPassBuilderOption getCGPassBuilderOption();
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_TARGET_CGPASSBUILDEROPTION_H
|
64
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/CodeGenCWrappers.h
vendored
Normal file
64
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/CodeGenCWrappers.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
//===- llvm/Target/CodeGenCWrappers.h - CodeGen C Wrappers ------*- 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 defines C bindings wrappers for enums in llvm/Support/CodeGen.h
|
||||
// that need them. The wrappers are separated to avoid adding an indirect
|
||||
// dependency on llvm/Config/Targets.def to CodeGen.h.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TARGET_CODEGENCWRAPPERS_H
|
||||
#define LLVM_TARGET_CODEGENCWRAPPERS_H
|
||||
|
||||
#include "llvm-c/TargetMachine.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/Support/CodeGen.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
inline Optional<CodeModel::Model> unwrap(LLVMCodeModel Model, bool &JIT) {
|
||||
JIT = false;
|
||||
switch (Model) {
|
||||
case LLVMCodeModelJITDefault:
|
||||
JIT = true;
|
||||
LLVM_FALLTHROUGH;
|
||||
case LLVMCodeModelDefault:
|
||||
return None;
|
||||
case LLVMCodeModelTiny:
|
||||
return CodeModel::Tiny;
|
||||
case LLVMCodeModelSmall:
|
||||
return CodeModel::Small;
|
||||
case LLVMCodeModelKernel:
|
||||
return CodeModel::Kernel;
|
||||
case LLVMCodeModelMedium:
|
||||
return CodeModel::Medium;
|
||||
case LLVMCodeModelLarge:
|
||||
return CodeModel::Large;
|
||||
}
|
||||
return CodeModel::Small;
|
||||
}
|
||||
|
||||
inline LLVMCodeModel wrap(CodeModel::Model Model) {
|
||||
switch (Model) {
|
||||
case CodeModel::Tiny:
|
||||
return LLVMCodeModelTiny;
|
||||
case CodeModel::Small:
|
||||
return LLVMCodeModelSmall;
|
||||
case CodeModel::Kernel:
|
||||
return LLVMCodeModelKernel;
|
||||
case CodeModel::Medium:
|
||||
return LLVMCodeModelMedium;
|
||||
case CodeModel::Large:
|
||||
return LLVMCodeModelLarge;
|
||||
}
|
||||
llvm_unreachable("Bad CodeModel!");
|
||||
}
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
1443
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/GenericOpcodes.td
vendored
Normal file
1443
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/GenericOpcodes.td
vendored
Normal file
File diff suppressed because it is too large
Load Diff
910
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/Combine.td
vendored
Normal file
910
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/Combine.td
vendored
Normal file
@@ -0,0 +1,910 @@
|
||||
//===- Combine.td - Combine rule definitions ---------------*- tablegen -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Declare GlobalISel combine rules and provide mechanisms to opt-out.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Common base class for GICombineRule and GICombineGroup.
|
||||
class GICombine {
|
||||
// See GICombineGroup. We only declare it here to make the tablegen pass
|
||||
// simpler.
|
||||
list<GICombine> Rules = ?;
|
||||
}
|
||||
|
||||
// A group of combine rules that can be added to a GICombiner or another group.
|
||||
class GICombineGroup<list<GICombine> rules> : GICombine {
|
||||
// The rules contained in this group. The rules in a group are flattened into
|
||||
// a single list and sorted into whatever order is most efficient. However,
|
||||
// they will never be re-ordered such that behaviour differs from the
|
||||
// specified order. It is therefore possible to use the order of rules in this
|
||||
// list to describe priorities.
|
||||
let Rules = rules;
|
||||
}
|
||||
|
||||
class GICombinerHelperArg<string type, string name> {
|
||||
string Type = type;
|
||||
string Name = name;
|
||||
}
|
||||
|
||||
// Declares a combiner helper class
|
||||
class GICombinerHelper<string classname, list<GICombine> rules>
|
||||
: GICombineGroup<rules> {
|
||||
// The class name to use in the generated output.
|
||||
string Classname = classname;
|
||||
// The name of a run-time compiler option that will be generated to disable
|
||||
// specific rules within this combiner.
|
||||
string DisableRuleOption = ?;
|
||||
// The state class to inherit from (if any). The generated helper will inherit
|
||||
// from this class and will forward arguments to its constructors.
|
||||
string StateClass = "";
|
||||
// Any additional arguments that should be appended to the tryCombine*().
|
||||
list<GICombinerHelperArg> AdditionalArguments =
|
||||
[GICombinerHelperArg<"CombinerHelper &", "Helper">];
|
||||
}
|
||||
class GICombineRule<dag defs, dag match, dag apply> : GICombine {
|
||||
/// Defines the external interface of the match rule. This includes:
|
||||
/// * The names of the root nodes (requires at least one)
|
||||
/// See GIDefKind for details.
|
||||
dag Defs = defs;
|
||||
|
||||
/// Defines the things which must be true for the pattern to match
|
||||
/// See GIMatchKind for details.
|
||||
dag Match = match;
|
||||
|
||||
/// Defines the things which happen after the decision is made to apply a
|
||||
/// combine rule.
|
||||
/// See GIApplyKind for details.
|
||||
dag Apply = apply;
|
||||
}
|
||||
|
||||
/// The operator at the root of a GICombineRule.Defs dag.
|
||||
def defs;
|
||||
|
||||
/// All arguments of the defs operator must be subclasses of GIDefKind or
|
||||
/// sub-dags whose operator is GIDefKindWithArgs.
|
||||
class GIDefKind;
|
||||
class GIDefKindWithArgs;
|
||||
/// Declare a root node. There must be at least one of these in every combine
|
||||
/// rule.
|
||||
/// TODO: The plan is to elide `root` definitions and determine it from the DAG
|
||||
/// itself with an override for situations where the usual determination
|
||||
/// is incorrect.
|
||||
def root : GIDefKind;
|
||||
|
||||
/// Declares data that is passed from the match stage to the apply stage.
|
||||
class GIDefMatchData<string type> : GIDefKind {
|
||||
/// A C++ type name indicating the storage type.
|
||||
string Type = type;
|
||||
}
|
||||
|
||||
def extending_load_matchdata : GIDefMatchData<"PreferredTuple">;
|
||||
def indexed_load_store_matchdata : GIDefMatchData<"IndexedLoadStoreMatchInfo">;
|
||||
def instruction_steps_matchdata: GIDefMatchData<"InstructionStepsMatchInfo">;
|
||||
|
||||
/// The operator at the root of a GICombineRule.Match dag.
|
||||
def match;
|
||||
/// All arguments of the match operator must be either:
|
||||
/// * A subclass of GIMatchKind
|
||||
/// * A subclass of GIMatchKindWithArgs
|
||||
/// * A subclass of Instruction
|
||||
/// * A MIR code block (deprecated)
|
||||
/// The GIMatchKind and GIMatchKindWithArgs cases are described in more detail
|
||||
/// in their definitions below.
|
||||
/// For the Instruction case, these are collected into a DAG where operand names
|
||||
/// that occur multiple times introduce edges.
|
||||
class GIMatchKind;
|
||||
class GIMatchKindWithArgs;
|
||||
|
||||
/// In lieu of having proper macro support. Trivial one-off opcode checks can be
|
||||
/// performed with this.
|
||||
def wip_match_opcode : GIMatchKindWithArgs;
|
||||
|
||||
/// The operator at the root of a GICombineRule.Apply dag.
|
||||
def apply;
|
||||
/// All arguments of the apply operator must be subclasses of GIApplyKind, or
|
||||
/// sub-dags whose operator is GIApplyKindWithArgs, or an MIR block
|
||||
/// (deprecated).
|
||||
class GIApplyKind;
|
||||
class GIApplyKindWithArgs;
|
||||
|
||||
def register_matchinfo: GIDefMatchData<"Register">;
|
||||
def int64_matchinfo: GIDefMatchData<"int64_t">;
|
||||
def apint_matchinfo : GIDefMatchData<"APInt">;
|
||||
def build_fn_matchinfo :
|
||||
GIDefMatchData<"std::function<void(MachineIRBuilder &)>">;
|
||||
|
||||
def copy_prop : GICombineRule<
|
||||
(defs root:$d),
|
||||
(match (COPY $d, $s):$mi,
|
||||
[{ return Helper.matchCombineCopy(*${mi}); }]),
|
||||
(apply [{ Helper.applyCombineCopy(*${mi}); }])>;
|
||||
|
||||
def extending_loads : GICombineRule<
|
||||
(defs root:$root, extending_load_matchdata:$matchinfo),
|
||||
(match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD):$root,
|
||||
[{ return Helper.matchCombineExtendingLoads(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyCombineExtendingLoads(*${root}, ${matchinfo}); }])>;
|
||||
|
||||
def load_and_mask : GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_AND):$root,
|
||||
[{ return Helper.matchCombineLoadWithAndMask(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
|
||||
def combines_for_extload: GICombineGroup<[extending_loads, load_and_mask]>;
|
||||
|
||||
def sext_trunc_sextload : GICombineRule<
|
||||
(defs root:$d),
|
||||
(match (wip_match_opcode G_SEXT_INREG):$d,
|
||||
[{ return Helper.matchSextTruncSextLoad(*${d}); }]),
|
||||
(apply [{ Helper.applySextTruncSextLoad(*${d}); }])>;
|
||||
|
||||
def sext_inreg_of_load_matchdata : GIDefMatchData<"std::tuple<Register, unsigned>">;
|
||||
def sext_inreg_of_load : GICombineRule<
|
||||
(defs root:$root, sext_inreg_of_load_matchdata:$matchinfo),
|
||||
(match (wip_match_opcode G_SEXT_INREG):$root,
|
||||
[{ return Helper.matchSextInRegOfLoad(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applySextInRegOfLoad(*${root}, ${matchinfo}); }])>;
|
||||
|
||||
def combine_indexed_load_store : GICombineRule<
|
||||
(defs root:$root, indexed_load_store_matchdata:$matchinfo),
|
||||
(match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD, G_STORE):$root,
|
||||
[{ return Helper.matchCombineIndexedLoadStore(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyCombineIndexedLoadStore(*${root}, ${matchinfo}); }])>;
|
||||
|
||||
def opt_brcond_by_inverting_cond_matchdata : GIDefMatchData<"MachineInstr *">;
|
||||
def opt_brcond_by_inverting_cond : GICombineRule<
|
||||
(defs root:$root, opt_brcond_by_inverting_cond_matchdata:$matchinfo),
|
||||
(match (wip_match_opcode G_BR):$root,
|
||||
[{ return Helper.matchOptBrCondByInvertingCond(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyOptBrCondByInvertingCond(*${root}, ${matchinfo}); }])>;
|
||||
|
||||
def ptr_add_immed_matchdata : GIDefMatchData<"PtrAddChain">;
|
||||
def ptr_add_immed_chain : GICombineRule<
|
||||
(defs root:$d, ptr_add_immed_matchdata:$matchinfo),
|
||||
(match (wip_match_opcode G_PTR_ADD):$d,
|
||||
[{ return Helper.matchPtrAddImmedChain(*${d}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyPtrAddImmedChain(*${d}, ${matchinfo}); }])>;
|
||||
|
||||
// Fold shift (shift base x), y -> shift base, (x+y), if shifts are same
|
||||
def shift_immed_matchdata : GIDefMatchData<"RegisterImmPair">;
|
||||
def shift_immed_chain : GICombineRule<
|
||||
(defs root:$d, shift_immed_matchdata:$matchinfo),
|
||||
(match (wip_match_opcode G_SHL, G_ASHR, G_LSHR, G_SSHLSAT, G_USHLSAT):$d,
|
||||
[{ return Helper.matchShiftImmedChain(*${d}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyShiftImmedChain(*${d}, ${matchinfo}); }])>;
|
||||
|
||||
// Transform shift (logic (shift X, C0), Y), C1
|
||||
// -> logic (shift X, (C0+C1)), (shift Y, C1), if shifts are same
|
||||
def shift_of_shifted_logic_matchdata : GIDefMatchData<"ShiftOfShiftedLogic">;
|
||||
def shift_of_shifted_logic_chain : GICombineRule<
|
||||
(defs root:$d, shift_of_shifted_logic_matchdata:$matchinfo),
|
||||
(match (wip_match_opcode G_SHL, G_ASHR, G_LSHR, G_USHLSAT, G_SSHLSAT):$d,
|
||||
[{ return Helper.matchShiftOfShiftedLogic(*${d}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyShiftOfShiftedLogic(*${d}, ${matchinfo}); }])>;
|
||||
|
||||
def mul_to_shl_matchdata : GIDefMatchData<"unsigned">;
|
||||
def mul_to_shl : GICombineRule<
|
||||
(defs root:$d, mul_to_shl_matchdata:$matchinfo),
|
||||
(match (G_MUL $d, $op1, $op2):$mi,
|
||||
[{ return Helper.matchCombineMulToShl(*${mi}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyCombineMulToShl(*${mi}, ${matchinfo}); }])>;
|
||||
|
||||
// shl ([asz]ext x), y => zext (shl x, y), if shift does not overflow int
|
||||
def reduce_shl_of_extend_matchdata : GIDefMatchData<"RegisterImmPair">;
|
||||
def reduce_shl_of_extend : GICombineRule<
|
||||
(defs root:$dst, reduce_shl_of_extend_matchdata:$matchinfo),
|
||||
(match (G_SHL $dst, $src0, $src1):$mi,
|
||||
[{ return Helper.matchCombineShlOfExtend(*${mi}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyCombineShlOfExtend(*${mi}, ${matchinfo}); }])>;
|
||||
|
||||
def narrow_binop_feeding_and : GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_AND):$root,
|
||||
[{ return Helper.matchNarrowBinopFeedingAnd(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
|
||||
|
||||
// [us]itofp(undef) = 0, because the result value is bounded.
|
||||
def undef_to_fp_zero : GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_UITOFP, G_SITOFP):$root,
|
||||
[{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
|
||||
(apply [{ Helper.replaceInstWithFConstant(*${root}, 0.0); }])>;
|
||||
|
||||
def undef_to_int_zero: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_AND, G_MUL):$root,
|
||||
[{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
|
||||
(apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>;
|
||||
|
||||
def undef_to_negative_one: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_OR):$root,
|
||||
[{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
|
||||
(apply [{ Helper.replaceInstWithConstant(*${root}, -1); }])>;
|
||||
|
||||
def binop_left_undef_to_zero: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_SHL):$root,
|
||||
[{ return Helper.matchOperandIsUndef(*${root}, 1); }]),
|
||||
(apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>;
|
||||
|
||||
// Instructions where if any source operand is undef, the instruction can be
|
||||
// replaced with undef.
|
||||
def propagate_undef_any_op: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_ADD, G_FPTOSI, G_FPTOUI, G_SUB, G_XOR, G_TRUNC):$root,
|
||||
[{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
|
||||
(apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
|
||||
|
||||
// Instructions where if all source operands are undef, the instruction can be
|
||||
// replaced with undef.
|
||||
def propagate_undef_all_ops: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_SHUFFLE_VECTOR):$root,
|
||||
[{ return Helper.matchAllExplicitUsesAreUndef(*${root}); }]),
|
||||
(apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
|
||||
|
||||
// Replace a G_SHUFFLE_VECTOR with an undef mask with a G_IMPLICIT_DEF.
|
||||
def propagate_undef_shuffle_mask: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_SHUFFLE_VECTOR):$root,
|
||||
[{ return Helper.matchUndefShuffleVectorMask(*${root}); }]),
|
||||
(apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
|
||||
|
||||
// Fold (cond ? x : x) -> x
|
||||
def select_same_val: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_SELECT):$root,
|
||||
[{ return Helper.matchSelectSameVal(*${root}); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }])
|
||||
>;
|
||||
|
||||
// Fold (undef ? x : y) -> y
|
||||
def select_undef_cmp: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_SELECT):$root,
|
||||
[{ return Helper.matchUndefSelectCmp(*${root}); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }])
|
||||
>;
|
||||
|
||||
// Fold (true ? x : y) -> x
|
||||
// Fold (false ? x : y) -> y
|
||||
def select_constant_cmp_matchdata : GIDefMatchData<"unsigned">;
|
||||
def select_constant_cmp: GICombineRule<
|
||||
(defs root:$root, select_constant_cmp_matchdata:$matchinfo),
|
||||
(match (wip_match_opcode G_SELECT):$root,
|
||||
[{ return Helper.matchConstantSelectCmp(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, ${matchinfo}); }])
|
||||
>;
|
||||
|
||||
// Fold x op 0 -> x
|
||||
def right_identity_zero: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_SUB, G_ADD, G_OR, G_XOR, G_SHL, G_ASHR, G_LSHR,
|
||||
G_PTR_ADD, G_ROTL, G_ROTR):$root,
|
||||
[{ return Helper.matchConstantOp(${root}->getOperand(2), 0); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
|
||||
>;
|
||||
|
||||
// Fold x op 1 -> x
|
||||
def right_identity_one: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_MUL):$root,
|
||||
[{ return Helper.matchConstantOp(${root}->getOperand(2), 1); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
|
||||
>;
|
||||
|
||||
// Fold (x op x) - > x
|
||||
def binop_same_val: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_AND, G_OR):$root,
|
||||
[{ return Helper.matchBinOpSameVal(*${root}); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
|
||||
>;
|
||||
|
||||
// Fold (0 op x) - > 0
|
||||
def binop_left_to_zero: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_SDIV, G_UDIV, G_SREM, G_UREM):$root,
|
||||
[{ return Helper.matchOperandIsZero(*${root}, 1); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
|
||||
>;
|
||||
|
||||
def urem_pow2_to_mask : GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_UREM):$root,
|
||||
[{ return Helper.matchOperandIsKnownToBeAPowerOfTwo(*${root}, 2); }]),
|
||||
(apply [{ Helper.applySimplifyURemByPow2(*${root}); }])
|
||||
>;
|
||||
|
||||
// Transform d = [su]div(x, y) and r = [su]rem(x, y) - > d, r = [su]divrem(x, y)
|
||||
def div_rem_to_divrem_matchdata : GIDefMatchData<"MachineInstr *">;
|
||||
def div_rem_to_divrem : GICombineRule<
|
||||
(defs root:$root, div_rem_to_divrem_matchdata:$matchinfo),
|
||||
(match (wip_match_opcode G_SDIV, G_UDIV, G_SREM, G_UREM):$root,
|
||||
[{ return Helper.matchCombineDivRem(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyCombineDivRem(*${root}, ${matchinfo}); }])
|
||||
>;
|
||||
|
||||
// Fold (x op 0) - > 0
|
||||
def binop_right_to_zero: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_MUL):$root,
|
||||
[{ return Helper.matchOperandIsZero(*${root}, 2); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }])
|
||||
>;
|
||||
|
||||
// Erase stores of undef values.
|
||||
def erase_undef_store : GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_STORE):$root,
|
||||
[{ return Helper.matchUndefStore(*${root}); }]),
|
||||
(apply [{ return Helper.eraseInst(*${root}); }])
|
||||
>;
|
||||
|
||||
def simplify_add_to_sub_matchinfo: GIDefMatchData<"std::tuple<Register, Register>">;
|
||||
def simplify_add_to_sub: GICombineRule <
|
||||
(defs root:$root, simplify_add_to_sub_matchinfo:$info),
|
||||
(match (wip_match_opcode G_ADD):$root,
|
||||
[{ return Helper.matchSimplifyAddToSub(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applySimplifyAddToSub(*${root}, ${info});}])
|
||||
>;
|
||||
|
||||
// Fold fp_op(cst) to the constant result of the floating point operation.
|
||||
def constant_fp_op_matchinfo: GIDefMatchData<"Optional<APFloat>">;
|
||||
def constant_fp_op: GICombineRule <
|
||||
(defs root:$root, constant_fp_op_matchinfo:$info),
|
||||
(match (wip_match_opcode G_FNEG, G_FABS, G_FPTRUNC, G_FSQRT, G_FLOG2):$root,
|
||||
[{ return Helper.matchCombineConstantFoldFpUnary(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyCombineConstantFoldFpUnary(*${root}, ${info}); }])
|
||||
>;
|
||||
|
||||
// Fold int2ptr(ptr2int(x)) -> x
|
||||
def p2i_to_i2p: GICombineRule<
|
||||
(defs root:$root, register_matchinfo:$info),
|
||||
(match (wip_match_opcode G_INTTOPTR):$root,
|
||||
[{ return Helper.matchCombineI2PToP2I(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyCombineI2PToP2I(*${root}, ${info}); }])
|
||||
>;
|
||||
|
||||
// Fold ptr2int(int2ptr(x)) -> x
|
||||
def i2p_to_p2i: GICombineRule<
|
||||
(defs root:$root, register_matchinfo:$info),
|
||||
(match (wip_match_opcode G_PTRTOINT):$root,
|
||||
[{ return Helper.matchCombineP2IToI2P(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyCombineP2IToI2P(*${root}, ${info}); }])
|
||||
>;
|
||||
|
||||
// Fold add ptrtoint(x), y -> ptrtoint (ptr_add x), y
|
||||
def add_p2i_to_ptradd_matchinfo : GIDefMatchData<"std::pair<Register, bool>">;
|
||||
def add_p2i_to_ptradd : GICombineRule<
|
||||
(defs root:$root, add_p2i_to_ptradd_matchinfo:$info),
|
||||
(match (wip_match_opcode G_ADD):$root,
|
||||
[{ return Helper.matchCombineAddP2IToPtrAdd(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyCombineAddP2IToPtrAdd(*${root}, ${info}); }])
|
||||
>;
|
||||
|
||||
// Fold (ptr_add (int2ptr C1), C2) -> C1 + C2
|
||||
def const_ptradd_to_i2p_matchinfo : GIDefMatchData<"APInt">;
|
||||
def const_ptradd_to_i2p: GICombineRule<
|
||||
(defs root:$root, const_ptradd_to_i2p_matchinfo:$info),
|
||||
(match (wip_match_opcode G_PTR_ADD):$root,
|
||||
[{ return Helper.matchCombineConstPtrAddToI2P(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyCombineConstPtrAddToI2P(*${root}, ${info}); }])
|
||||
>;
|
||||
|
||||
// Simplify: (logic_op (op x...), (op y...)) -> (op (logic_op x, y))
|
||||
def hoist_logic_op_with_same_opcode_hands: GICombineRule <
|
||||
(defs root:$root, instruction_steps_matchdata:$info),
|
||||
(match (wip_match_opcode G_AND, G_OR, G_XOR):$root,
|
||||
[{ return Helper.matchHoistLogicOpWithSameOpcodeHands(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildInstructionSteps(*${root}, ${info});}])
|
||||
>;
|
||||
|
||||
// Fold ashr (shl x, C), C -> sext_inreg (C)
|
||||
def shl_ashr_to_sext_inreg_matchinfo : GIDefMatchData<"std::tuple<Register, int64_t>">;
|
||||
def shl_ashr_to_sext_inreg : GICombineRule<
|
||||
(defs root:$root, shl_ashr_to_sext_inreg_matchinfo:$info),
|
||||
(match (wip_match_opcode G_ASHR): $root,
|
||||
[{ return Helper.matchAshrShlToSextInreg(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyAshShlToSextInreg(*${root}, ${info});}])
|
||||
>;
|
||||
|
||||
// Fold and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0
|
||||
def overlapping_and: GICombineRule <
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_AND):$root,
|
||||
[{ return Helper.matchOverlappingAnd(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])
|
||||
>;
|
||||
|
||||
// Fold (x & y) -> x or (x & y) -> y when (x & y) is known to equal x or equal y.
|
||||
def redundant_and: GICombineRule <
|
||||
(defs root:$root, register_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_AND):$root,
|
||||
[{ return Helper.matchRedundantAnd(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }])
|
||||
>;
|
||||
|
||||
// Fold (x | y) -> x or (x | y) -> y when (x | y) is known to equal x or equal y.
|
||||
def redundant_or: GICombineRule <
|
||||
(defs root:$root, register_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_OR):$root,
|
||||
[{ return Helper.matchRedundantOr(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }])
|
||||
>;
|
||||
|
||||
// If the input is already sign extended, just drop the extension.
|
||||
// sext_inreg x, K ->
|
||||
// if computeNumSignBits(x) >= (x.getScalarSizeInBits() - K + 1)
|
||||
def redundant_sext_inreg: GICombineRule <
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_SEXT_INREG):$root,
|
||||
[{ return Helper.matchRedundantSExtInReg(*${root}); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
|
||||
>;
|
||||
|
||||
// Fold (anyext (trunc x)) -> x if the source type is same as
|
||||
// the destination type.
|
||||
def anyext_trunc_fold: GICombineRule <
|
||||
(defs root:$root, register_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_ANYEXT):$root,
|
||||
[{ return Helper.matchCombineAnyExtTrunc(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }])
|
||||
>;
|
||||
|
||||
// Fold (zext (trunc x)) -> x if the source type is same as the destination type
|
||||
// and truncated bits are known to be zero.
|
||||
def zext_trunc_fold_matchinfo : GIDefMatchData<"Register">;
|
||||
def zext_trunc_fold: GICombineRule <
|
||||
(defs root:$root, zext_trunc_fold_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_ZEXT):$root,
|
||||
[{ return Helper.matchCombineZextTrunc(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }])
|
||||
>;
|
||||
|
||||
// Fold ([asz]ext ([asz]ext x)) -> ([asz]ext x).
|
||||
def ext_ext_fold_matchinfo : GIDefMatchData<"std::tuple<Register, unsigned>">;
|
||||
def ext_ext_fold: GICombineRule <
|
||||
(defs root:$root, ext_ext_fold_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_ANYEXT, G_SEXT, G_ZEXT):$root,
|
||||
[{ return Helper.matchCombineExtOfExt(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyCombineExtOfExt(*${root}, ${matchinfo}); }])
|
||||
>;
|
||||
|
||||
def not_cmp_fold_matchinfo : GIDefMatchData<"SmallVector<Register, 4>">;
|
||||
def not_cmp_fold : GICombineRule<
|
||||
(defs root:$d, not_cmp_fold_matchinfo:$info),
|
||||
(match (wip_match_opcode G_XOR): $d,
|
||||
[{ return Helper.matchNotCmp(*${d}, ${info}); }]),
|
||||
(apply [{ Helper.applyNotCmp(*${d}, ${info}); }])
|
||||
>;
|
||||
|
||||
// Fold (fneg (fneg x)) -> x.
|
||||
def fneg_fneg_fold: GICombineRule <
|
||||
(defs root:$root, register_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_FNEG):$root,
|
||||
[{ return Helper.matchCombineFNegOfFNeg(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }])
|
||||
>;
|
||||
|
||||
// Fold (unmerge(merge x, y, z)) -> z, y, z.
|
||||
def unmerge_merge_matchinfo : GIDefMatchData<"SmallVector<Register, 8>">;
|
||||
def unmerge_merge : GICombineRule<
|
||||
(defs root:$d, unmerge_merge_matchinfo:$info),
|
||||
(match (wip_match_opcode G_UNMERGE_VALUES): $d,
|
||||
[{ return Helper.matchCombineUnmergeMergeToPlainValues(*${d}, ${info}); }]),
|
||||
(apply [{ Helper.applyCombineUnmergeMergeToPlainValues(*${d}, ${info}); }])
|
||||
>;
|
||||
|
||||
// Fold merge(unmerge).
|
||||
def merge_unmerge : GICombineRule<
|
||||
(defs root:$d, register_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_MERGE_VALUES):$d,
|
||||
[{ return Helper.matchCombineMergeUnmerge(*${d}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.replaceSingleDefInstWithReg(*${d}, ${matchinfo}); }])
|
||||
>;
|
||||
|
||||
// Fold (fabs (fabs x)) -> (fabs x).
|
||||
def fabs_fabs_fold: GICombineRule<
|
||||
(defs root:$root, register_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_FABS):$root,
|
||||
[{ return Helper.matchCombineFAbsOfFAbs(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }])
|
||||
>;
|
||||
|
||||
// Fold (fabs (fneg x)) -> (fabs x).
|
||||
def fabs_fneg_fold: GICombineRule <
|
||||
(defs root:$root, build_fn_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_FABS):$root,
|
||||
[{ return Helper.matchCombineFAbsOfFNeg(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
|
||||
|
||||
// Fold (unmerge cst) -> cst1, cst2, ...
|
||||
def unmerge_cst_matchinfo : GIDefMatchData<"SmallVector<APInt, 8>">;
|
||||
def unmerge_cst : GICombineRule<
|
||||
(defs root:$d, unmerge_cst_matchinfo:$info),
|
||||
(match (wip_match_opcode G_UNMERGE_VALUES): $d,
|
||||
[{ return Helper.matchCombineUnmergeConstant(*${d}, ${info}); }]),
|
||||
(apply [{ Helper.applyCombineUnmergeConstant(*${d}, ${info}); }])
|
||||
>;
|
||||
|
||||
// Fold (unmerge undef) -> undef, undef, ...
|
||||
def unmerge_undef : GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_UNMERGE_VALUES): $root,
|
||||
[{ return Helper.matchCombineUnmergeUndef(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])
|
||||
>;
|
||||
|
||||
// Transform x,y<dead> = unmerge z -> x = trunc z.
|
||||
def unmerge_dead_to_trunc : GICombineRule<
|
||||
(defs root:$d),
|
||||
(match (wip_match_opcode G_UNMERGE_VALUES): $d,
|
||||
[{ return Helper.matchCombineUnmergeWithDeadLanesToTrunc(*${d}); }]),
|
||||
(apply [{ Helper.applyCombineUnmergeWithDeadLanesToTrunc(*${d}); }])
|
||||
>;
|
||||
|
||||
// Transform x,y = unmerge(zext(z)) -> x = zext z; y = 0.
|
||||
def unmerge_zext_to_zext : GICombineRule<
|
||||
(defs root:$d),
|
||||
(match (wip_match_opcode G_UNMERGE_VALUES): $d,
|
||||
[{ return Helper.matchCombineUnmergeZExtToZExt(*${d}); }]),
|
||||
(apply [{ Helper.applyCombineUnmergeZExtToZExt(*${d}); }])
|
||||
>;
|
||||
|
||||
// Fold trunc ([asz]ext x) -> x or ([asz]ext x) or (trunc x).
|
||||
def trunc_ext_fold_matchinfo : GIDefMatchData<"std::pair<Register, unsigned>">;
|
||||
def trunc_ext_fold: GICombineRule <
|
||||
(defs root:$root, trunc_ext_fold_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_TRUNC):$root,
|
||||
[{ return Helper.matchCombineTruncOfExt(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyCombineTruncOfExt(*${root}, ${matchinfo}); }])
|
||||
>;
|
||||
|
||||
// Fold trunc (shl x, K) -> shl (trunc x), K => K < VT.getScalarSizeInBits().
|
||||
def trunc_shl_matchinfo : GIDefMatchData<"std::pair<Register, Register>">;
|
||||
def trunc_shl: GICombineRule <
|
||||
(defs root:$root, trunc_shl_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_TRUNC):$root,
|
||||
[{ return Helper.matchCombineTruncOfShl(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyCombineTruncOfShl(*${root}, ${matchinfo}); }])
|
||||
>;
|
||||
|
||||
// Transform (mul x, -1) -> (sub 0, x)
|
||||
def mul_by_neg_one: GICombineRule <
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_MUL):$root,
|
||||
[{ return Helper.matchConstantOp(${root}->getOperand(2), -1); }]),
|
||||
(apply [{ Helper.applyCombineMulByNegativeOne(*${root}); }])
|
||||
>;
|
||||
|
||||
// Fold (xor (and x, y), y) -> (and (not x), y)
|
||||
def xor_of_and_with_same_reg_matchinfo :
|
||||
GIDefMatchData<"std::pair<Register, Register>">;
|
||||
def xor_of_and_with_same_reg: GICombineRule <
|
||||
(defs root:$root, xor_of_and_with_same_reg_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_XOR):$root,
|
||||
[{ return Helper.matchXorOfAndWithSameReg(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyXorOfAndWithSameReg(*${root}, ${matchinfo}); }])
|
||||
>;
|
||||
|
||||
// Transform (ptr_add 0, x) -> (int_to_ptr x)
|
||||
def ptr_add_with_zero: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_PTR_ADD):$root,
|
||||
[{ return Helper.matchPtrAddZero(*${root}); }]),
|
||||
(apply [{ Helper.applyPtrAddZero(*${root}); }])>;
|
||||
|
||||
def regs_small_vec : GIDefMatchData<"SmallVector<Register, 4>">;
|
||||
def combine_insert_vec_elts_build_vector : GICombineRule<
|
||||
(defs root:$root, regs_small_vec:$info),
|
||||
(match (wip_match_opcode G_INSERT_VECTOR_ELT):$root,
|
||||
[{ return Helper.matchCombineInsertVecElts(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyCombineInsertVecElts(*${root}, ${info}); }])>;
|
||||
|
||||
def load_or_combine : GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_OR):$root,
|
||||
[{ return Helper.matchLoadOrCombine(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
|
||||
def truncstore_merge_matcdata : GIDefMatchData<"MergeTruncStoresInfo">;
|
||||
def truncstore_merge : GICombineRule<
|
||||
(defs root:$root, truncstore_merge_matcdata:$info),
|
||||
(match (wip_match_opcode G_STORE):$root,
|
||||
[{ return Helper.matchTruncStoreMerge(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyTruncStoreMerge(*${root}, ${info}); }])>;
|
||||
|
||||
def extend_through_phis_matchdata: GIDefMatchData<"MachineInstr*">;
|
||||
def extend_through_phis : GICombineRule<
|
||||
(defs root:$root, extend_through_phis_matchdata:$matchinfo),
|
||||
(match (wip_match_opcode G_PHI):$root,
|
||||
[{ return Helper.matchExtendThroughPhis(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyExtendThroughPhis(*${root}, ${matchinfo}); }])>;
|
||||
|
||||
// Currently only the one combine above.
|
||||
def insert_vec_elt_combines : GICombineGroup<
|
||||
[combine_insert_vec_elts_build_vector]>;
|
||||
|
||||
def extract_vec_elt_build_vec : GICombineRule<
|
||||
(defs root:$root, register_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_EXTRACT_VECTOR_ELT):$root,
|
||||
[{ return Helper.matchExtractVecEltBuildVec(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyExtractVecEltBuildVec(*${root}, ${matchinfo}); }])>;
|
||||
|
||||
// Fold away full elt extracts from a build_vector.
|
||||
def extract_all_elts_from_build_vector_matchinfo :
|
||||
GIDefMatchData<"SmallVector<std::pair<Register, MachineInstr*>>">;
|
||||
def extract_all_elts_from_build_vector : GICombineRule<
|
||||
(defs root:$root, extract_all_elts_from_build_vector_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_BUILD_VECTOR):$root,
|
||||
[{ return Helper.matchExtractAllEltsFromBuildVector(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyExtractAllEltsFromBuildVector(*${root}, ${matchinfo}); }])>;
|
||||
|
||||
def extract_vec_elt_combines : GICombineGroup<[
|
||||
extract_vec_elt_build_vec,
|
||||
extract_all_elts_from_build_vector]>;
|
||||
|
||||
def funnel_shift_from_or_shift : GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_OR):$root,
|
||||
[{ return Helper.matchOrShiftToFunnelShift(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])
|
||||
>;
|
||||
|
||||
def funnel_shift_to_rotate : GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_FSHL, G_FSHR):$root,
|
||||
[{ return Helper.matchFunnelShiftToRotate(*${root}); }]),
|
||||
(apply [{ Helper.applyFunnelShiftToRotate(*${root}); }])
|
||||
>;
|
||||
|
||||
def rotate_out_of_range : GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_ROTR, G_ROTL):$root,
|
||||
[{ return Helper.matchRotateOutOfRange(*${root}); }]),
|
||||
(apply [{ Helper.applyRotateOutOfRange(*${root}); }])
|
||||
>;
|
||||
|
||||
def icmp_to_true_false_known_bits : GICombineRule<
|
||||
(defs root:$d, int64_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_ICMP):$d,
|
||||
[{ return Helper.matchICmpToTrueFalseKnownBits(*${d}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.replaceInstWithConstant(*${d}, ${matchinfo}); }])>;
|
||||
|
||||
def icmp_to_lhs_known_bits : GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_ICMP):$root,
|
||||
[{ return Helper.matchICmpToLHSKnownBits(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
def and_or_disjoint_mask : GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_AND):$root,
|
||||
[{ return Helper.matchAndOrDisjointMask(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildFnNoErase(*${root}, ${info}); }])>;
|
||||
|
||||
def bitfield_extract_from_and : GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_AND):$root,
|
||||
[{ return Helper.matchBitfieldExtractFromAnd(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
def funnel_shift_combines : GICombineGroup<[funnel_shift_from_or_shift,
|
||||
funnel_shift_to_rotate]>;
|
||||
|
||||
def bitfield_extract_from_sext_inreg : GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_SEXT_INREG):$root,
|
||||
[{ return Helper.matchBitfieldExtractFromSExtInReg(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
def bitfield_extract_from_shr : GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_ASHR, G_LSHR):$root,
|
||||
[{ return Helper.matchBitfieldExtractFromShr(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
def bitfield_extract_from_shr_and : GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_ASHR, G_LSHR):$root,
|
||||
[{ return Helper.matchBitfieldExtractFromShrAnd(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
def form_bitfield_extract : GICombineGroup<[bitfield_extract_from_sext_inreg,
|
||||
bitfield_extract_from_and,
|
||||
bitfield_extract_from_shr,
|
||||
bitfield_extract_from_shr_and]>;
|
||||
|
||||
def udiv_by_const : GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_UDIV):$root,
|
||||
[{ return Helper.matchUDivByConst(*${root}); }]),
|
||||
(apply [{ Helper.applyUDivByConst(*${root}); }])>;
|
||||
|
||||
def intdiv_combines : GICombineGroup<[udiv_by_const]>;
|
||||
|
||||
def reassoc_ptradd : GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_PTR_ADD):$root,
|
||||
[{ return Helper.matchReassocPtrAdd(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
|
||||
|
||||
def reassocs : GICombineGroup<[reassoc_ptradd]>;
|
||||
|
||||
// Constant fold operations.
|
||||
def constant_fold : GICombineRule<
|
||||
(defs root:$d, apint_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR):$d,
|
||||
[{ return Helper.matchConstantFold(*${d}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.replaceInstWithConstant(*${d}, ${matchinfo}); }])>;
|
||||
|
||||
def mulo_by_2: GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_UMULO, G_SMULO):$root,
|
||||
[{ return Helper.matchMulOBy2(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
|
||||
|
||||
def mulh_to_lshr : GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_UMULH):$root,
|
||||
[{ return Helper.matchUMulHToLShr(*${root}); }]),
|
||||
(apply [{ Helper.applyUMulHToLShr(*${root}); }])>;
|
||||
|
||||
def mulh_combines : GICombineGroup<[mulh_to_lshr]>;
|
||||
|
||||
def redundant_neg_operands: GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMAD, G_FMA):$root,
|
||||
[{ return Helper.matchRedundantNegOperands(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
|
||||
|
||||
// Transform (fadd x, (fmul y, z)) -> (fma y, z, x)
|
||||
// (fadd x, (fmul y, z)) -> (fmad y, z, x)
|
||||
// Transform (fadd (fmul x, y), z) -> (fma x, y, z)
|
||||
// (fadd (fmul x, y), z) -> (fmad x, y, z)
|
||||
def combine_fadd_fmul_to_fmad_or_fma: GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_FADD):$root,
|
||||
[{ return Helper.matchCombineFAddFMulToFMadOrFMA(*${root},
|
||||
${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
// Transform (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z)
|
||||
// -> (fmad (fpext x), (fpext y), z)
|
||||
// Transform (fadd x, (fpext (fmul y, z))) -> (fma (fpext y), (fpext z), x)
|
||||
// -> (fmad (fpext y), (fpext z), x)
|
||||
def combine_fadd_fpext_fmul_to_fmad_or_fma: GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_FADD):$root,
|
||||
[{ return Helper.matchCombineFAddFpExtFMulToFMadOrFMA(*${root},
|
||||
${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
// Transform (fadd (fma x, y, (fmul z, u)), v) -> (fma x, y, (fma z, u, v))
|
||||
// (fadd (fmad x, y, (fmul z, u)), v) -> (fmad x, y, (fmad z, u, v))
|
||||
// Transform (fadd v, (fma x, y, (fmul z, u))) -> (fma x, y, (fma z, u, v))
|
||||
// (fadd v, (fmad x, y, (fmul z, u))) -> (fmad x, y, (fmad z, u, v))
|
||||
def combine_fadd_fma_fmul_to_fmad_or_fma: GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_FADD):$root,
|
||||
[{ return Helper.matchCombineFAddFMAFMulToFMadOrFMA(*${root},
|
||||
${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
// Transform (fadd (fma x, y, (fpext (fmul u, v))), z) ->
|
||||
// (fma x, y, (fma (fpext u), (fpext v), z))
|
||||
def combine_fadd_fpext_fma_fmul_to_fmad_or_fma: GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_FADD):$root,
|
||||
[{ return Helper.matchCombineFAddFpExtFMulToFMadOrFMAAggressive(
|
||||
*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
// Transform (fsub (fmul x, y), z) -> (fma x, y, -z)
|
||||
// -> (fmad x, y, -z)
|
||||
def combine_fsub_fmul_to_fmad_or_fma: GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_FSUB):$root,
|
||||
[{ return Helper.matchCombineFSubFMulToFMadOrFMA(*${root},
|
||||
${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
// Transform (fsub (fneg (fmul, x, y)), z) -> (fma (fneg x), y, (fneg z))
|
||||
// (fsub x, (fneg (fmul, y, z))) -> (fma y, z, x)
|
||||
def combine_fsub_fneg_fmul_to_fmad_or_fma: GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_FSUB):$root,
|
||||
[{ return Helper.matchCombineFSubFNegFMulToFMadOrFMA(*${root},
|
||||
${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
// Transform (fsub (fpext (fmul x, y)), z) ->
|
||||
// (fma (fpext x), (fpext y), (fneg z))
|
||||
def combine_fsub_fpext_fmul_to_fmad_or_fma: GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_FSUB):$root,
|
||||
[{ return Helper.matchCombineFSubFpExtFMulToFMadOrFMA(*${root},
|
||||
${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
// Transform (fsub (fneg (fpext (fmul x, y))), z) ->
|
||||
// (fneg (fma (fpext x), (fpext y), z))
|
||||
def combine_fsub_fpext_fneg_fmul_to_fmad_or_fma: GICombineRule<
|
||||
(defs root:$root, build_fn_matchinfo:$info),
|
||||
(match (wip_match_opcode G_FSUB):$root,
|
||||
[{ return Helper.matchCombineFSubFpExtFNegFMulToFMadOrFMA(
|
||||
*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
// FIXME: These should use the custom predicate feature once it lands.
|
||||
def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
|
||||
undef_to_negative_one,
|
||||
binop_left_undef_to_zero,
|
||||
propagate_undef_any_op,
|
||||
propagate_undef_all_ops,
|
||||
propagate_undef_shuffle_mask,
|
||||
erase_undef_store,
|
||||
unmerge_undef]>;
|
||||
|
||||
def identity_combines : GICombineGroup<[select_same_val, right_identity_zero,
|
||||
binop_same_val, binop_left_to_zero,
|
||||
binop_right_to_zero, p2i_to_i2p,
|
||||
i2p_to_p2i, anyext_trunc_fold,
|
||||
fneg_fneg_fold, right_identity_one]>;
|
||||
|
||||
def const_combines : GICombineGroup<[constant_fp_op, const_ptradd_to_i2p,
|
||||
overlapping_and, mulo_by_2]>;
|
||||
|
||||
def known_bits_simplifications : GICombineGroup<[
|
||||
redundant_and, redundant_sext_inreg, redundant_or, urem_pow2_to_mask,
|
||||
zext_trunc_fold, icmp_to_true_false_known_bits, icmp_to_lhs_known_bits]>;
|
||||
|
||||
def width_reduction_combines : GICombineGroup<[reduce_shl_of_extend,
|
||||
narrow_binop_feeding_and]>;
|
||||
|
||||
def phi_combines : GICombineGroup<[extend_through_phis]>;
|
||||
|
||||
def select_combines : GICombineGroup<[select_undef_cmp, select_constant_cmp]>;
|
||||
|
||||
def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, add_p2i_to_ptradd,
|
||||
mul_by_neg_one]>;
|
||||
|
||||
def fma_combines : GICombineGroup<[combine_fadd_fmul_to_fmad_or_fma,
|
||||
combine_fadd_fpext_fmul_to_fmad_or_fma, combine_fadd_fma_fmul_to_fmad_or_fma,
|
||||
combine_fadd_fpext_fma_fmul_to_fmad_or_fma, combine_fsub_fmul_to_fmad_or_fma,
|
||||
combine_fsub_fneg_fmul_to_fmad_or_fma, combine_fsub_fpext_fmul_to_fmad_or_fma,
|
||||
combine_fsub_fpext_fneg_fmul_to_fmad_or_fma]>;
|
||||
|
||||
def all_combines : GICombineGroup<[trivial_combines, insert_vec_elt_combines,
|
||||
extract_vec_elt_combines, combines_for_extload,
|
||||
combine_indexed_load_store, undef_combines, identity_combines, phi_combines,
|
||||
simplify_add_to_sub, hoist_logic_op_with_same_opcode_hands,
|
||||
reassocs, ptr_add_immed_chain,
|
||||
shl_ashr_to_sext_inreg, sext_inreg_of_load,
|
||||
width_reduction_combines, select_combines,
|
||||
known_bits_simplifications, ext_ext_fold,
|
||||
not_cmp_fold, opt_brcond_by_inverting_cond,
|
||||
unmerge_merge, fabs_fabs_fold, unmerge_cst, unmerge_dead_to_trunc,
|
||||
unmerge_zext_to_zext, merge_unmerge, trunc_ext_fold, trunc_shl,
|
||||
const_combines, xor_of_and_with_same_reg, ptr_add_with_zero,
|
||||
shift_immed_chain, shift_of_shifted_logic_chain, load_or_combine,
|
||||
truncstore_merge, div_rem_to_divrem, funnel_shift_combines,
|
||||
form_bitfield_extract, constant_fold, fabs_fneg_fold,
|
||||
intdiv_combines, mulh_combines, redundant_neg_operands,
|
||||
and_or_disjoint_mask, fma_combines]>;
|
||||
|
||||
// A combine group used to for prelegalizer combiners at -O0. The combines in
|
||||
// this group have been selected based on experiments to balance code size and
|
||||
// compile time performance.
|
||||
def optnone_combines : GICombineGroup<[trivial_combines,
|
||||
ptr_add_immed_chain, combines_for_extload,
|
||||
not_cmp_fold, opt_brcond_by_inverting_cond]>;
|
15
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/RegisterBank.td
vendored
Normal file
15
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/RegisterBank.td
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
//===- RegisterBank.td - Register bank definitions ---------*- tablegen -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class RegisterBank<string name, list<RegisterClass> classes> {
|
||||
string Name = name;
|
||||
list<RegisterClass> RegisterClasses = classes;
|
||||
}
|
221
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
vendored
Normal file
221
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
//===- TargetGlobalISel.td - Common code for GlobalISel ----*- tablegen -*-===//
|
||||
//
|
||||
// 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 defines the target-independent interfaces used to support
|
||||
// SelectionDAG instruction selection patterns (specified in
|
||||
// TargetSelectionDAG.td) when generating GlobalISel instruction selectors.
|
||||
//
|
||||
// This is intended as a compatibility layer, to enable reuse of target
|
||||
// descriptions written for SelectionDAG without requiring explicit GlobalISel
|
||||
// support. It will eventually supersede SelectionDAG patterns.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Declare that a generic Instruction is 'equivalent' to an SDNode, that is,
|
||||
// SelectionDAG patterns involving the SDNode can be transformed to match the
|
||||
// Instruction instead.
|
||||
class GINodeEquiv<Instruction i, SDNode node> {
|
||||
Instruction I = i;
|
||||
SDNode Node = node;
|
||||
|
||||
// SelectionDAG has separate nodes for atomic and non-atomic memory operations
|
||||
// (ISD::LOAD, ISD::ATOMIC_LOAD, ISD::STORE, ISD::ATOMIC_STORE) but GlobalISel
|
||||
// stores this information in the MachineMemoryOperand.
|
||||
bit CheckMMOIsNonAtomic = false;
|
||||
bit CheckMMOIsAtomic = false;
|
||||
|
||||
// SelectionDAG has one node for all loads and uses predicates to
|
||||
// differentiate them. GlobalISel on the other hand uses separate opcodes.
|
||||
// When this is true, the resulting opcode is G_LOAD/G_SEXTLOAD/G_ZEXTLOAD
|
||||
// depending on the predicates on the node.
|
||||
Instruction IfSignExtend = ?;
|
||||
Instruction IfZeroExtend = ?;
|
||||
|
||||
// SelectionDAG has one setcc for all compares. This differentiates
|
||||
// for G_ICMP and G_FCMP.
|
||||
Instruction IfFloatingPoint = ?;
|
||||
}
|
||||
|
||||
// These are defined in the same order as the G_* instructions.
|
||||
def : GINodeEquiv<G_ANYEXT, anyext>;
|
||||
def : GINodeEquiv<G_SEXT, sext>;
|
||||
def : GINodeEquiv<G_ZEXT, zext>;
|
||||
def : GINodeEquiv<G_TRUNC, trunc>;
|
||||
def : GINodeEquiv<G_BITCAST, bitconvert>;
|
||||
// G_INTTOPTR - SelectionDAG has no equivalent.
|
||||
// G_PTRTOINT - SelectionDAG has no equivalent.
|
||||
def : GINodeEquiv<G_CONSTANT, imm>;
|
||||
// timm must not be materialized and therefore has no GlobalISel equivalent
|
||||
def : GINodeEquiv<G_FCONSTANT, fpimm>;
|
||||
def : GINodeEquiv<G_IMPLICIT_DEF, undef>;
|
||||
def : GINodeEquiv<G_FRAME_INDEX, frameindex>;
|
||||
def : GINodeEquiv<G_BLOCK_ADDR, blockaddress>;
|
||||
def : GINodeEquiv<G_ADD, add>;
|
||||
def : GINodeEquiv<G_SUB, sub>;
|
||||
def : GINodeEquiv<G_MUL, mul>;
|
||||
def : GINodeEquiv<G_UMULH, mulhu>;
|
||||
def : GINodeEquiv<G_SMULH, mulhs>;
|
||||
def : GINodeEquiv<G_SDIV, sdiv>;
|
||||
def : GINodeEquiv<G_UDIV, udiv>;
|
||||
def : GINodeEquiv<G_SREM, srem>;
|
||||
def : GINodeEquiv<G_UREM, urem>;
|
||||
def : GINodeEquiv<G_AND, and>;
|
||||
def : GINodeEquiv<G_OR, or>;
|
||||
def : GINodeEquiv<G_XOR, xor>;
|
||||
def : GINodeEquiv<G_SHL, shl>;
|
||||
def : GINodeEquiv<G_LSHR, srl>;
|
||||
def : GINodeEquiv<G_ASHR, sra>;
|
||||
def : GINodeEquiv<G_SADDSAT, saddsat>;
|
||||
def : GINodeEquiv<G_UADDSAT, uaddsat>;
|
||||
def : GINodeEquiv<G_SSUBSAT, ssubsat>;
|
||||
def : GINodeEquiv<G_USUBSAT, usubsat>;
|
||||
def : GINodeEquiv<G_SSHLSAT, sshlsat>;
|
||||
def : GINodeEquiv<G_USHLSAT, ushlsat>;
|
||||
def : GINodeEquiv<G_SMULFIX, smulfix>;
|
||||
def : GINodeEquiv<G_UMULFIX, umulfix>;
|
||||
def : GINodeEquiv<G_SMULFIXSAT, smulfixsat>;
|
||||
def : GINodeEquiv<G_UMULFIXSAT, umulfixsat>;
|
||||
def : GINodeEquiv<G_SDIVFIX, sdivfix>;
|
||||
def : GINodeEquiv<G_UDIVFIX, udivfix>;
|
||||
def : GINodeEquiv<G_SDIVFIXSAT, sdivfixsat>;
|
||||
def : GINodeEquiv<G_UDIVFIXSAT, udivfixsat>;
|
||||
def : GINodeEquiv<G_SELECT, select>;
|
||||
def : GINodeEquiv<G_FNEG, fneg>;
|
||||
def : GINodeEquiv<G_FPEXT, fpextend>;
|
||||
def : GINodeEquiv<G_FPTRUNC, fpround>;
|
||||
def : GINodeEquiv<G_FPTOSI, fp_to_sint>;
|
||||
def : GINodeEquiv<G_FPTOUI, fp_to_uint>;
|
||||
def : GINodeEquiv<G_SITOFP, sint_to_fp>;
|
||||
def : GINodeEquiv<G_UITOFP, uint_to_fp>;
|
||||
def : GINodeEquiv<G_FADD, fadd>;
|
||||
def : GINodeEquiv<G_FSUB, fsub>;
|
||||
def : GINodeEquiv<G_FMA, fma>;
|
||||
def : GINodeEquiv<G_FMAD, fmad>;
|
||||
def : GINodeEquiv<G_FMUL, fmul>;
|
||||
def : GINodeEquiv<G_FDIV, fdiv>;
|
||||
def : GINodeEquiv<G_FREM, frem>;
|
||||
def : GINodeEquiv<G_FPOW, fpow>;
|
||||
def : GINodeEquiv<G_FEXP2, fexp2>;
|
||||
def : GINodeEquiv<G_FLOG2, flog2>;
|
||||
def : GINodeEquiv<G_FCANONICALIZE, fcanonicalize>;
|
||||
def : GINodeEquiv<G_INTRINSIC, intrinsic_wo_chain>;
|
||||
// ISD::INTRINSIC_VOID can also be handled with G_INTRINSIC_W_SIDE_EFFECTS.
|
||||
def : GINodeEquiv<G_INTRINSIC_W_SIDE_EFFECTS, intrinsic_void>;
|
||||
def : GINodeEquiv<G_INTRINSIC_W_SIDE_EFFECTS, intrinsic_w_chain>;
|
||||
def : GINodeEquiv<G_BR, br>;
|
||||
def : GINodeEquiv<G_BSWAP, bswap>;
|
||||
def : GINodeEquiv<G_BITREVERSE, bitreverse>;
|
||||
def : GINodeEquiv<G_FSHL, fshl>;
|
||||
def : GINodeEquiv<G_FSHR, fshr>;
|
||||
def : GINodeEquiv<G_CTLZ, ctlz>;
|
||||
def : GINodeEquiv<G_CTTZ, cttz>;
|
||||
def : GINodeEquiv<G_CTLZ_ZERO_UNDEF, ctlz_zero_undef>;
|
||||
def : GINodeEquiv<G_CTTZ_ZERO_UNDEF, cttz_zero_undef>;
|
||||
def : GINodeEquiv<G_CTPOP, ctpop>;
|
||||
def : GINodeEquiv<G_EXTRACT_VECTOR_ELT, extractelt>;
|
||||
def : GINodeEquiv<G_CONCAT_VECTORS, concat_vectors>;
|
||||
def : GINodeEquiv<G_BUILD_VECTOR, build_vector>;
|
||||
def : GINodeEquiv<G_FCEIL, fceil>;
|
||||
def : GINodeEquiv<G_FCOS, fcos>;
|
||||
def : GINodeEquiv<G_FSIN, fsin>;
|
||||
def : GINodeEquiv<G_FABS, fabs>;
|
||||
def : GINodeEquiv<G_FSQRT, fsqrt>;
|
||||
def : GINodeEquiv<G_FFLOOR, ffloor>;
|
||||
def : GINodeEquiv<G_FRINT, frint>;
|
||||
def : GINodeEquiv<G_FNEARBYINT, fnearbyint>;
|
||||
def : GINodeEquiv<G_INTRINSIC_TRUNC, ftrunc>;
|
||||
def : GINodeEquiv<G_INTRINSIC_ROUND, fround>;
|
||||
def : GINodeEquiv<G_INTRINSIC_LRINT, lrint>;
|
||||
def : GINodeEquiv<G_FCOPYSIGN, fcopysign>;
|
||||
def : GINodeEquiv<G_SMIN, smin>;
|
||||
def : GINodeEquiv<G_SMAX, smax>;
|
||||
def : GINodeEquiv<G_UMIN, umin>;
|
||||
def : GINodeEquiv<G_UMAX, umax>;
|
||||
def : GINodeEquiv<G_ABS, abs>;
|
||||
def : GINodeEquiv<G_FMINNUM, fminnum>;
|
||||
def : GINodeEquiv<G_FMAXNUM, fmaxnum>;
|
||||
def : GINodeEquiv<G_FMINNUM_IEEE, fminnum_ieee>;
|
||||
def : GINodeEquiv<G_FMAXNUM_IEEE, fmaxnum_ieee>;
|
||||
def : GINodeEquiv<G_READCYCLECOUNTER, readcyclecounter>;
|
||||
def : GINodeEquiv<G_ROTR, rotr>;
|
||||
def : GINodeEquiv<G_ROTL, rotl>;
|
||||
def : GINodeEquiv<G_LROUND, lround>;
|
||||
def : GINodeEquiv<G_LLROUND, llround>;
|
||||
|
||||
def : GINodeEquiv<G_STRICT_FADD, strict_fadd>;
|
||||
def : GINodeEquiv<G_STRICT_FSUB, strict_fsub>;
|
||||
def : GINodeEquiv<G_STRICT_FMUL, strict_fmul>;
|
||||
def : GINodeEquiv<G_STRICT_FDIV, strict_fdiv>;
|
||||
def : GINodeEquiv<G_STRICT_FREM, strict_frem>;
|
||||
def : GINodeEquiv<G_STRICT_FMA, strict_fma>;
|
||||
def : GINodeEquiv<G_STRICT_FSQRT, strict_fsqrt>;
|
||||
|
||||
// Broadly speaking G_LOAD is equivalent to ISD::LOAD but there are some
|
||||
// complications that tablegen must take care of. For example, Predicates such
|
||||
// as isSignExtLoad require that this is not a perfect 1:1 mapping since a
|
||||
// sign-extending load is (G_SEXTLOAD x) in GlobalISel. Additionally,
|
||||
// G_LOAD handles both atomic and non-atomic loads where as SelectionDAG had
|
||||
// separate nodes for them. This GINodeEquiv maps the non-atomic loads to
|
||||
// G_LOAD with a non-atomic MachineMemOperand.
|
||||
def : GINodeEquiv<G_LOAD, ld> {
|
||||
let CheckMMOIsNonAtomic = true;
|
||||
let IfSignExtend = G_SEXTLOAD;
|
||||
let IfZeroExtend = G_ZEXTLOAD;
|
||||
}
|
||||
|
||||
def : GINodeEquiv<G_ICMP, setcc> {
|
||||
let IfFloatingPoint = G_FCMP;
|
||||
}
|
||||
|
||||
// Broadly speaking G_STORE is equivalent to ISD::STORE but there are some
|
||||
// complications that tablegen must take care of. For example, predicates such
|
||||
// as isTruncStore require that this is not a perfect 1:1 mapping since a
|
||||
// truncating store is (G_STORE (G_TRUNCATE x)) in GlobalISel. Additionally,
|
||||
// G_STORE handles both atomic and non-atomic stores where as SelectionDAG had
|
||||
// separate nodes for them. This GINodeEquiv maps the non-atomic stores to
|
||||
// G_STORE with a non-atomic MachineMemOperand.
|
||||
def : GINodeEquiv<G_STORE, st> { let CheckMMOIsNonAtomic = true; }
|
||||
|
||||
def : GINodeEquiv<G_LOAD, atomic_load> {
|
||||
let CheckMMOIsNonAtomic = false;
|
||||
let CheckMMOIsAtomic = true;
|
||||
}
|
||||
|
||||
// Operands are swapped for atomic_store vs. regular store
|
||||
def : GINodeEquiv<G_STORE, atomic_store> {
|
||||
let CheckMMOIsNonAtomic = false;
|
||||
let CheckMMOIsAtomic = true;
|
||||
}
|
||||
|
||||
def : GINodeEquiv<G_ATOMIC_CMPXCHG, atomic_cmp_swap>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_XCHG, atomic_swap>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_ADD, atomic_load_add>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_SUB, atomic_load_sub>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_AND, atomic_load_and>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_NAND, atomic_load_nand>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_OR, atomic_load_or>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_XOR, atomic_load_xor>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_MIN, atomic_load_min>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_MAX, atomic_load_max>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_UMIN, atomic_load_umin>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_UMAX, atomic_load_umax>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_FADD, atomic_load_fadd>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_FSUB, atomic_load_fsub>;
|
||||
def : GINodeEquiv<G_FENCE, atomic_fence>;
|
||||
|
||||
// Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern.
|
||||
// Should be used on defs that subclass GIComplexOperandMatcher<>.
|
||||
class GIComplexPatternEquiv<ComplexPattern seldag> {
|
||||
ComplexPattern SelDAGEquivalent = seldag;
|
||||
}
|
||||
|
||||
// Specifies the GlobalISel equivalents for SelectionDAG's SDNodeXForm.
|
||||
// Should be used on defs that subclass GICustomOperandRenderer<>.
|
||||
class GISDNodeXFormEquiv<SDNodeXForm seldag> {
|
||||
SDNodeXForm SelDAGEquivalent = seldag;
|
||||
}
|
65
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/Target.td
vendored
Normal file
65
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/Target.td
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
//===- Target.td - Define GlobalISel rules -----------------*- tablegen -*-===//
|
||||
//
|
||||
// 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 defines the target-independent interfaces used to support
|
||||
// SelectionDAG instruction selection patterns (specified in
|
||||
// TargetSelectionDAG.td) when generating GlobalISel instruction selectors.
|
||||
//
|
||||
// This is intended as a compatibility layer, to enable reuse of target
|
||||
// descriptions written for SelectionDAG without requiring explicit GlobalISel
|
||||
// support. It will eventually supersede SelectionDAG patterns.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Definitions that inherit from LLT define types that will be used in the
|
||||
// GlobalISel matcher.
|
||||
class LLT;
|
||||
|
||||
def s32 : LLT;
|
||||
def s64 : LLT;
|
||||
|
||||
// Defines a matcher for complex operands. This is analogous to ComplexPattern
|
||||
// from SelectionDAG.
|
||||
//
|
||||
// Definitions that inherit from this may also inherit from
|
||||
// GIComplexPatternEquiv to enable the import of SelectionDAG patterns involving
|
||||
// those ComplexPatterns.
|
||||
class GIComplexOperandMatcher<LLT type, string matcherfn> {
|
||||
// The expected type of the root of the match.
|
||||
//
|
||||
// TODO: We should probably support, any-type, any-scalar, and multiple types
|
||||
// in the future.
|
||||
LLT Type = type;
|
||||
|
||||
// The function that determines whether the operand matches. It should be of
|
||||
// the form:
|
||||
// ComplexRendererFn select(MachineOperand &Root) const;
|
||||
// where Root is the root of the match. The function should return nullptr
|
||||
// on match failure, or a ComplexRendererFn that renders the operand in case
|
||||
// of a successful match.
|
||||
string MatcherFn = matcherfn;
|
||||
}
|
||||
|
||||
// Defines a custom renderer. This is analogous to SDNodeXForm from
|
||||
// SelectionDAG. Unlike SDNodeXForm, this matches a MachineInstr and
|
||||
// renders directly to the result instruction without an intermediate node.
|
||||
//
|
||||
// Definitions that inherit from this may also inherit from GISDNodeXFormEquiv
|
||||
// to enable the import of SelectionDAG patterns involving those SDNodeXForms.
|
||||
class GICustomOperandRenderer<string rendererfn> {
|
||||
// The function renders the operand(s) of the matched instruction to
|
||||
// the specified instruction. It should be of the form:
|
||||
// void render(MachineInstrBuilder &MIB, const MachineInstr &MI,
|
||||
// int OpIdx = -1)
|
||||
//
|
||||
// If OpIdx is specified (i.e. not invalid/negative), this
|
||||
// references the source operand MI.getOperand(OpIdx). Otherwise,
|
||||
// this is the value defined by MI. This is to support the case
|
||||
// where there is no corresponding instruction to match.
|
||||
string RendererFn = rendererfn;
|
||||
}
|
1743
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/Target.td
vendored
Normal file
1743
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/Target.td
vendored
Normal file
File diff suppressed because it is too large
Load Diff
221
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetCallingConv.td
vendored
Normal file
221
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetCallingConv.td
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
//===- TargetCallingConv.td - Target Calling Conventions ---*- tablegen -*-===//
|
||||
//
|
||||
// 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 defines the target-independent interfaces with which targets
|
||||
// describe their calling conventions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class CCAction;
|
||||
class CallingConv;
|
||||
|
||||
/// CCCustom - Calls a custom arg handling function.
|
||||
class CCCustom<string fn> : CCAction {
|
||||
string FuncName = fn;
|
||||
}
|
||||
|
||||
/// CCPredicateAction - Instances of this class check some predicate, then
|
||||
/// delegate to another action if the predicate is true.
|
||||
class CCPredicateAction<CCAction A> : CCAction {
|
||||
CCAction SubAction = A;
|
||||
}
|
||||
|
||||
/// CCIfType - If the current argument is one of the specified types, apply
|
||||
/// Action A.
|
||||
class CCIfType<list<ValueType> vts, CCAction A> : CCPredicateAction<A> {
|
||||
list<ValueType> VTs = vts;
|
||||
}
|
||||
|
||||
/// CCIf - If the predicate matches, apply A.
|
||||
class CCIf<string predicate, CCAction A> : CCPredicateAction<A> {
|
||||
string Predicate = predicate;
|
||||
}
|
||||
|
||||
/// CCIfByVal - If the current argument has ByVal parameter attribute, apply
|
||||
/// Action A.
|
||||
class CCIfByVal<CCAction A> : CCIf<"ArgFlags.isByVal()", A> {
|
||||
}
|
||||
|
||||
/// CCIfPreallocated - If the current argument has Preallocated parameter attribute,
|
||||
/// apply Action A.
|
||||
class CCIfPreallocated<CCAction A> : CCIf<"ArgFlags.isPreallocated()", A> {
|
||||
}
|
||||
|
||||
/// CCIfSwiftSelf - If the current argument has swiftself parameter attribute,
|
||||
/// apply Action A.
|
||||
class CCIfSwiftSelf<CCAction A> : CCIf<"ArgFlags.isSwiftSelf()", A> {
|
||||
}
|
||||
|
||||
/// CCIfSwiftAsync - If the current argument has swiftasync parameter attribute,
|
||||
/// apply Action A.
|
||||
class CCIfSwiftAsync<CCAction A> : CCIf<"ArgFlags.isSwiftAsync()", A> {
|
||||
}
|
||||
|
||||
/// CCIfSwiftError - If the current argument has swifterror parameter attribute,
|
||||
/// apply Action A.
|
||||
class CCIfSwiftError<CCAction A> : CCIf<"ArgFlags.isSwiftError()", A> {
|
||||
}
|
||||
|
||||
/// CCIfCFGuardTarget - If the current argument has cfguardtarget parameter
|
||||
/// attribute, apply Action A.
|
||||
class CCIfCFGuardTarget<CCAction A> : CCIf<"ArgFlags.isCFGuardTarget()", A> {
|
||||
}
|
||||
|
||||
/// CCIfConsecutiveRegs - If the current argument has InConsecutiveRegs
|
||||
/// parameter attribute, apply Action A.
|
||||
class CCIfConsecutiveRegs<CCAction A> : CCIf<"ArgFlags.isInConsecutiveRegs()", A> {
|
||||
}
|
||||
|
||||
/// CCIfCC - Match if the current calling convention is 'CC'.
|
||||
class CCIfCC<string CC, CCAction A>
|
||||
: CCIf<!strconcat("State.getCallingConv() == ", CC), A> {}
|
||||
|
||||
/// CCIfInReg - If this argument is marked with the 'inreg' attribute, apply
|
||||
/// the specified action.
|
||||
class CCIfInReg<CCAction A> : CCIf<"ArgFlags.isInReg()", A> {}
|
||||
|
||||
/// CCIfNest - If this argument is marked with the 'nest' attribute, apply
|
||||
/// the specified action.
|
||||
class CCIfNest<CCAction A> : CCIf<"ArgFlags.isNest()", A> {}
|
||||
|
||||
/// CCIfSplit - If this argument is marked with the 'split' attribute, apply
|
||||
/// the specified action.
|
||||
class CCIfSplit<CCAction A> : CCIf<"ArgFlags.isSplit()", A> {}
|
||||
|
||||
/// CCIfSRet - If this argument is marked with the 'sret' attribute, apply
|
||||
/// the specified action.
|
||||
class CCIfSRet<CCAction A> : CCIf<"ArgFlags.isSRet()", A> {}
|
||||
|
||||
/// CCIfVarArg - If the current function is vararg - apply the action
|
||||
class CCIfVarArg<CCAction A> : CCIf<"State.isVarArg()", A> {}
|
||||
|
||||
/// CCIfNotVarArg - If the current function is not vararg - apply the action
|
||||
class CCIfNotVarArg<CCAction A> : CCIf<"!State.isVarArg()", A> {}
|
||||
|
||||
/// CCIfPtrAddrSpace - If the top-level parent of the current argument has
|
||||
/// pointer type in the specified address-space.
|
||||
class CCIfPtrAddrSpace<int AS, CCAction A>
|
||||
: CCIf<"(ArgFlags.isPointer() && ArgFlags.getPointerAddrSpace() == " # AS # ")", A> {}
|
||||
|
||||
/// CCIfPtr - If the top-level parent of the current argument had
|
||||
/// pointer type in some address-space.
|
||||
class CCIfPtr<CCAction A> : CCIf<"ArgFlags.isPointer()", A> {}
|
||||
|
||||
/// CCAssignToReg - This action matches if there is a register in the specified
|
||||
/// list that is still available. If so, it assigns the value to the first
|
||||
/// available register and succeeds.
|
||||
class CCAssignToReg<list<Register> regList> : CCAction {
|
||||
list<Register> RegList = regList;
|
||||
}
|
||||
|
||||
/// CCAssignToRegWithShadow - Same as CCAssignToReg, but with list of registers
|
||||
/// which became shadowed, when some register is used.
|
||||
class CCAssignToRegWithShadow<list<Register> regList,
|
||||
list<Register> shadowList> : CCAction {
|
||||
list<Register> RegList = regList;
|
||||
list<Register> ShadowRegList = shadowList;
|
||||
}
|
||||
|
||||
/// CCAssignToStack - This action always matches: it assigns the value to a
|
||||
/// stack slot of the specified size and alignment on the stack. If size is
|
||||
/// zero then the ABI size is used; if align is zero then the ABI alignment
|
||||
/// is used - these may depend on the target or subtarget.
|
||||
class CCAssignToStack<int size, int align> : CCAction {
|
||||
int Size = size;
|
||||
int Align = align;
|
||||
}
|
||||
|
||||
/// CCAssignToStackWithShadow - Same as CCAssignToStack, but with a list of
|
||||
/// registers to be shadowed. Note that, unlike CCAssignToRegWithShadow, this
|
||||
/// shadows ALL of the registers in shadowList.
|
||||
class CCAssignToStackWithShadow<int size,
|
||||
int align,
|
||||
list<Register> shadowList> : CCAction {
|
||||
int Size = size;
|
||||
int Align = align;
|
||||
list<Register> ShadowRegList = shadowList;
|
||||
}
|
||||
|
||||
/// CCPassByVal - This action always matches: it assigns the value to a stack
|
||||
/// slot to implement ByVal aggregate parameter passing. Size and alignment
|
||||
/// specify the minimum size and alignment for the stack slot.
|
||||
class CCPassByVal<int size, int align> : CCAction {
|
||||
int Size = size;
|
||||
int Align = align;
|
||||
}
|
||||
|
||||
/// CCPromoteToType - If applied, this promotes the specified current value to
|
||||
/// the specified type.
|
||||
class CCPromoteToType<ValueType destTy> : CCAction {
|
||||
ValueType DestTy = destTy;
|
||||
}
|
||||
|
||||
/// CCPromoteToUpperBitsInType - If applied, this promotes the specified current
|
||||
/// value to the specified type and shifts the value into the upper bits.
|
||||
class CCPromoteToUpperBitsInType<ValueType destTy> : CCAction {
|
||||
ValueType DestTy = destTy;
|
||||
}
|
||||
|
||||
/// CCBitConvertToType - If applied, this bitconverts the specified current
|
||||
/// value to the specified type.
|
||||
class CCBitConvertToType<ValueType destTy> : CCAction {
|
||||
ValueType DestTy = destTy;
|
||||
}
|
||||
|
||||
/// CCTruncToType - If applied, this truncates the specified current value to
|
||||
/// the specified type.
|
||||
class CCTruncToType<ValueType destTy> : CCAction {
|
||||
ValueType DestTy = destTy;
|
||||
}
|
||||
|
||||
/// CCPassIndirect - If applied, this stores the value to stack and passes the pointer
|
||||
/// as normal argument.
|
||||
class CCPassIndirect<ValueType destTy> : CCAction {
|
||||
ValueType DestTy = destTy;
|
||||
}
|
||||
|
||||
/// CCDelegateTo - This action invokes the specified sub-calling-convention. It
|
||||
/// is successful if the specified CC matches.
|
||||
class CCDelegateTo<CallingConv cc> : CCAction {
|
||||
CallingConv CC = cc;
|
||||
}
|
||||
|
||||
/// CallingConv - An instance of this is used to define each calling convention
|
||||
/// that the target supports.
|
||||
class CallingConv<list<CCAction> actions> {
|
||||
list<CCAction> Actions = actions;
|
||||
|
||||
/// If true, this calling convention will be emitted as externally visible in
|
||||
/// the llvm namespaces instead of as a static function.
|
||||
bit Entry = false;
|
||||
|
||||
bit Custom = false;
|
||||
}
|
||||
|
||||
/// CustomCallingConv - An instance of this is used to declare calling
|
||||
/// conventions that are implemented using a custom function of the same name.
|
||||
class CustomCallingConv : CallingConv<[]> {
|
||||
let Custom = true;
|
||||
}
|
||||
|
||||
/// CalleeSavedRegs - A list of callee saved registers for a given calling
|
||||
/// convention. The order of registers is used by PrologEpilogInsertion when
|
||||
/// allocation stack slots for saved registers.
|
||||
///
|
||||
/// For each CalleeSavedRegs def, TableGen will emit a FOO_SaveList array for
|
||||
/// returning from getCalleeSavedRegs(), and a FOO_RegMask bit mask suitable for
|
||||
/// returning from getCallPreservedMask().
|
||||
class CalleeSavedRegs<dag saves> {
|
||||
dag SaveList = saves;
|
||||
|
||||
// Registers that are also preserved across function calls, but should not be
|
||||
// included in the generated FOO_SaveList array. These registers will be
|
||||
// included in the FOO_RegMask bit mask. This can be used for registers that
|
||||
// are saved automatically, like the SPARC register windows.
|
||||
dag OtherPreserved;
|
||||
}
|
377
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetInstrPredicate.td
vendored
Normal file
377
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetInstrPredicate.td
vendored
Normal file
@@ -0,0 +1,377 @@
|
||||
//===- TargetInstrPredicate.td - ---------------------------*- tablegen -*-===//
|
||||
//
|
||||
// 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 defines class MCInstPredicate and its subclasses.
|
||||
//
|
||||
// MCInstPredicate definitions are used by target scheduling models to describe
|
||||
// constraints on instructions.
|
||||
//
|
||||
// Here is an example of an MCInstPredicate definition in TableGen:
|
||||
//
|
||||
// def MCInstPredicateExample : CheckAll<[
|
||||
// CheckOpcode<[BLR]>,
|
||||
// CheckIsRegOperand<0>,
|
||||
// CheckNot<CheckRegOperand<0, LR>>]>;
|
||||
//
|
||||
// The syntax for MCInstPredicate is declarative, and predicate definitions can
|
||||
// be composed together in order to generate more complex constraints.
|
||||
//
|
||||
// The `CheckAll` from the example defines a composition of three different
|
||||
// predicates. Definition `MCInstPredicateExample` identifies instructions
|
||||
// whose opcode is BLR, and whose first operand is a register different from
|
||||
// register `LR`.
|
||||
//
|
||||
// Every MCInstPredicate class has a well-known semantic in tablegen. For
|
||||
// example, `CheckOpcode` is a special type of predicate used to describe a
|
||||
// constraint on the value of an instruction opcode.
|
||||
//
|
||||
// MCInstPredicate definitions are typically used by scheduling models to
|
||||
// construct MCSchedPredicate definitions (see the definition of class
|
||||
// MCSchedPredicate in llvm/Target/TargetSchedule.td).
|
||||
// In particular, an MCSchedPredicate can be used instead of a SchedPredicate
|
||||
// when defining the set of SchedReadVariant and SchedWriteVariant of a
|
||||
// processor scheduling model.
|
||||
//
|
||||
// The `MCInstPredicateExample` definition above is equivalent (and therefore
|
||||
// could replace) the following definition from a previous ExynosM3 model (see
|
||||
// AArch64SchedExynosM3.td):
|
||||
//
|
||||
// def M3BranchLinkFastPred : SchedPredicate<[{
|
||||
// MI->getOpcode() == AArch64::BLR &&
|
||||
// MI->getOperand(0).isReg() &&
|
||||
// MI->getOperand(0).getReg() != AArch64::LR}]>;
|
||||
//
|
||||
// The main advantage of using MCInstPredicate instead of SchedPredicate is
|
||||
// portability: users don't need to specify predicates in C++. As a consequence
|
||||
// of this, MCInstPredicate definitions are not bound to a particular
|
||||
// representation (i.e. MachineInstr vs MCInst).
|
||||
//
|
||||
// Tablegen backends know how to expand MCInstPredicate definitions into actual
|
||||
// C++ code that works on MachineInstr (and/or MCInst).
|
||||
//
|
||||
// Instances of class PredicateExpander (see utils/Tablegen/PredicateExpander.h)
|
||||
// know how to expand a predicate. For each MCInstPredicate class, there must be
|
||||
// an "expand" method available in the PredicateExpander interface.
|
||||
//
|
||||
// For example, a `CheckOpcode` predicate is expanded using method
|
||||
// `PredicateExpander::expandCheckOpcode()`.
|
||||
//
|
||||
// New MCInstPredicate classes must be added to this file. For each new class
|
||||
// XYZ, an "expandXYZ" method must be added to the PredicateExpander.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Forward declarations.
|
||||
class Instruction;
|
||||
class SchedMachineModel;
|
||||
|
||||
// A generic machine instruction predicate.
|
||||
class MCInstPredicate;
|
||||
|
||||
class MCTrue : MCInstPredicate; // A predicate that always evaluates to True.
|
||||
class MCFalse : MCInstPredicate; // A predicate that always evaluates to False.
|
||||
def TruePred : MCTrue;
|
||||
def FalsePred : MCFalse;
|
||||
|
||||
// A predicate used to negate the outcome of another predicate.
|
||||
// It allows to easily express "set difference" operations. For example, it
|
||||
// makes it easy to describe a check that tests if an opcode is not part of a
|
||||
// set of opcodes.
|
||||
class CheckNot<MCInstPredicate P> : MCInstPredicate {
|
||||
MCInstPredicate Pred = P;
|
||||
}
|
||||
|
||||
// This class is used as a building block to define predicates on instruction
|
||||
// operands. It is used to reference a specific machine operand.
|
||||
class MCOperandPredicate<int Index> : MCInstPredicate {
|
||||
int OpIndex = Index;
|
||||
}
|
||||
|
||||
// Return true if machine operand at position `Index` is a register operand.
|
||||
class CheckIsRegOperand<int Index> : MCOperandPredicate<Index>;
|
||||
|
||||
// Return true if machine operand at position `Index` is an immediate operand.
|
||||
class CheckIsImmOperand<int Index> : MCOperandPredicate<Index>;
|
||||
|
||||
// Check if machine operands at index `First` and index `Second` both reference
|
||||
// the same register.
|
||||
class CheckSameRegOperand<int First, int Second> : MCInstPredicate {
|
||||
int FirstIndex = First;
|
||||
int SecondIndex = Second;
|
||||
}
|
||||
|
||||
// Base class for checks on register/immediate operands.
|
||||
// It allows users to define checks like:
|
||||
// MyFunction(MI->getOperand(Index).getImm()) == Val;
|
||||
//
|
||||
// In the example above, `MyFunction` is a function that takes as input an
|
||||
// immediate operand value, and returns another value. Field `FunctionMapper` is
|
||||
// the name of the function to call on the operand value.
|
||||
class CheckOperandBase<int Index, string Fn = ""> : MCOperandPredicate<Index> {
|
||||
string FunctionMapper = Fn;
|
||||
}
|
||||
|
||||
// Check that the machine register operand at position `Index` references
|
||||
// register R. This predicate assumes that we already checked that the machine
|
||||
// operand at position `Index` is a register operand.
|
||||
class CheckRegOperand<int Index, Register R> : CheckOperandBase<Index> {
|
||||
Register Reg = R;
|
||||
}
|
||||
|
||||
// Check if register operand at index `Index` is the invalid register.
|
||||
class CheckInvalidRegOperand<int Index> : CheckOperandBase<Index>;
|
||||
|
||||
// Return true if machine operand at position `Index` is a valid
|
||||
// register operand.
|
||||
class CheckValidRegOperand<int Index> :
|
||||
CheckNot<CheckInvalidRegOperand<Index>>;
|
||||
|
||||
// Check that the operand at position `Index` is immediate `Imm`.
|
||||
// If field `FunctionMapper` is a non-empty string, then function
|
||||
// `FunctionMapper` is applied to the operand value, and the return value is then
|
||||
// compared against `Imm`.
|
||||
class CheckImmOperand<int Index, int Imm> : CheckOperandBase<Index> {
|
||||
int ImmVal = Imm;
|
||||
}
|
||||
|
||||
// Similar to CheckImmOperand, however the immediate is not a literal number.
|
||||
// This is useful when we want to compare the value of an operand against an
|
||||
// enum value, and we know the actual integer value of that enum.
|
||||
class CheckImmOperand_s<int Index, string Value> : CheckOperandBase<Index> {
|
||||
string ImmVal = Value;
|
||||
}
|
||||
|
||||
// Expands to a call to `FunctionMapper` if field `FunctionMapper` is set.
|
||||
// Otherwise, it expands to a CheckNot<CheckInvalidRegOperand<Index>>.
|
||||
class CheckRegOperandSimple<int Index> : CheckOperandBase<Index>;
|
||||
|
||||
// Expands to a call to `FunctionMapper` if field `FunctionMapper` is set.
|
||||
// Otherwise, it simply evaluates to TruePred.
|
||||
class CheckImmOperandSimple<int Index> : CheckOperandBase<Index>;
|
||||
|
||||
// Check that the operand at position `Index` is immediate value zero.
|
||||
class CheckZeroOperand<int Index> : CheckImmOperand<Index, 0>;
|
||||
|
||||
// Check that the instruction has exactly `Num` operands.
|
||||
class CheckNumOperands<int Num> : MCInstPredicate {
|
||||
int NumOps = Num;
|
||||
}
|
||||
|
||||
// Check that the instruction opcode is one of the opcodes in set `Opcodes`.
|
||||
// This is a simple set membership query. The easier way to check if an opcode
|
||||
// is not a member of the set is by using a `CheckNot<CheckOpcode<[...]>>`
|
||||
// sequence.
|
||||
class CheckOpcode<list<Instruction> Opcodes> : MCInstPredicate {
|
||||
list<Instruction> ValidOpcodes = Opcodes;
|
||||
}
|
||||
|
||||
// Check that the instruction opcode is a pseudo opcode member of the set
|
||||
// `Opcodes`. This check is always expanded to "false" if we are generating
|
||||
// code for MCInst.
|
||||
class CheckPseudo<list<Instruction> Opcodes> : CheckOpcode<Opcodes>;
|
||||
|
||||
// A non-portable predicate. Only to use as a last resort when a block of code
|
||||
// cannot possibly be converted in a declarative way using other MCInstPredicate
|
||||
// classes. This check is always expanded to "false" when generating code for
|
||||
// MCInst.
|
||||
class CheckNonPortable<string Code> : MCInstPredicate {
|
||||
string CodeBlock = Code;
|
||||
}
|
||||
|
||||
// A sequence of predicates. It is used as the base class for CheckAll, and
|
||||
// CheckAny. It allows to describe compositions of predicates.
|
||||
class CheckPredicateSequence<list<MCInstPredicate> Preds> : MCInstPredicate {
|
||||
list<MCInstPredicate> Predicates = Preds;
|
||||
}
|
||||
|
||||
// Check that all of the predicates in `Preds` evaluate to true.
|
||||
class CheckAll<list<MCInstPredicate> Sequence>
|
||||
: CheckPredicateSequence<Sequence>;
|
||||
|
||||
// Check that at least one of the predicates in `Preds` evaluates to true.
|
||||
class CheckAny<list<MCInstPredicate> Sequence>
|
||||
: CheckPredicateSequence<Sequence>;
|
||||
|
||||
|
||||
// Used to expand the body of a function predicate. See the definition of
|
||||
// TIIPredicate below.
|
||||
class MCStatement;
|
||||
|
||||
// Expands to a return statement. The return expression is a boolean expression
|
||||
// described by a MCInstPredicate.
|
||||
class MCReturnStatement<MCInstPredicate predicate> : MCStatement {
|
||||
MCInstPredicate Pred = predicate;
|
||||
}
|
||||
|
||||
// Used to automatically construct cases of a switch statement where the switch
|
||||
// variable is an instruction opcode. There is a 'case' for every opcode in the
|
||||
// `opcodes` list, and each case is associated with MCStatement `caseStmt`.
|
||||
class MCOpcodeSwitchCase<list<Instruction> opcodes, MCStatement caseStmt> {
|
||||
list<Instruction> Opcodes = opcodes;
|
||||
MCStatement CaseStmt = caseStmt;
|
||||
}
|
||||
|
||||
// Expands to a switch statement. The switch variable is an instruction opcode.
|
||||
// The auto-generated switch is populated by a number of cases based on the
|
||||
// `cases` list in input. A default case is automatically generated, and it
|
||||
// evaluates to `default`.
|
||||
class MCOpcodeSwitchStatement<list<MCOpcodeSwitchCase> cases,
|
||||
MCStatement default> : MCStatement {
|
||||
list<MCOpcodeSwitchCase> Cases = cases;
|
||||
MCStatement DefaultCase = default;
|
||||
}
|
||||
|
||||
// Base class for function predicates.
|
||||
class FunctionPredicateBase<string name, MCStatement body> {
|
||||
string FunctionName = name;
|
||||
MCStatement Body = body;
|
||||
}
|
||||
|
||||
// Check that a call to method `Name` in class "XXXInstrInfo" (where XXX is
|
||||
// the name of a target) returns true.
|
||||
//
|
||||
// TIIPredicate definitions are used to model calls to the target-specific
|
||||
// InstrInfo. A TIIPredicate is treated specially by the InstrInfoEmitter
|
||||
// tablegen backend, which will use it to automatically generate a definition in
|
||||
// the target specific `InstrInfo` class.
|
||||
//
|
||||
// There cannot be multiple TIIPredicate definitions with the same name for the
|
||||
// same target.
|
||||
class TIIPredicate<string Name, MCStatement body>
|
||||
: FunctionPredicateBase<Name, body>, MCInstPredicate;
|
||||
|
||||
// A function predicate that takes as input a machine instruction, and returns
|
||||
// a boolean value.
|
||||
//
|
||||
// This predicate is expanded into a function call by the PredicateExpander.
|
||||
// In particular, the PredicateExpander would either expand this predicate into
|
||||
// a call to `MCInstFn`, or into a call to`MachineInstrFn` depending on whether
|
||||
// it is lowering predicates for MCInst or MachineInstr.
|
||||
//
|
||||
// In this context, `MCInstFn` and `MachineInstrFn` are both function names.
|
||||
class CheckFunctionPredicate<string MCInstFn, string MachineInstrFn> : MCInstPredicate {
|
||||
string MCInstFnName = MCInstFn;
|
||||
string MachineInstrFnName = MachineInstrFn;
|
||||
}
|
||||
|
||||
// Similar to CheckFunctionPredicate. However it assumes that MachineInstrFn is
|
||||
// a method in TargetInstrInfo, and MCInstrFn takes an extra pointer to
|
||||
// MCInstrInfo.
|
||||
//
|
||||
// It Expands to:
|
||||
// - TIIPointer->MachineInstrFn(MI)
|
||||
// - MCInstrFn(MI, MCII);
|
||||
class CheckFunctionPredicateWithTII<string MCInstFn, string MachineInstrFn, string
|
||||
TIIPointer = "TII"> : MCInstPredicate {
|
||||
string MCInstFnName = MCInstFn;
|
||||
string TIIPtrName = TIIPointer;
|
||||
string MachineInstrFnName = MachineInstrFn;
|
||||
}
|
||||
|
||||
// Used to classify machine instructions based on a machine instruction
|
||||
// predicate.
|
||||
//
|
||||
// Let IC be an InstructionEquivalenceClass definition, and MI a machine
|
||||
// instruction. We say that MI belongs to the equivalence class described by IC
|
||||
// if and only if the following two conditions are met:
|
||||
// a) MI's opcode is in the `opcodes` set, and
|
||||
// b) `Predicate` evaluates to true when applied to MI.
|
||||
//
|
||||
// Instances of this class can be used by processor scheduling models to
|
||||
// describe instructions that have a property in common. For example,
|
||||
// InstructionEquivalenceClass definitions can be used to identify the set of
|
||||
// dependency breaking instructions for a processor model.
|
||||
//
|
||||
// An (optional) list of operand indices can be used to further describe
|
||||
// properties that apply to instruction operands. For example, it can be used to
|
||||
// identify register uses of a dependency breaking instructions that are not in
|
||||
// a RAW dependency.
|
||||
class InstructionEquivalenceClass<list<Instruction> opcodes,
|
||||
MCInstPredicate pred,
|
||||
list<int> operands = []> {
|
||||
list<Instruction> Opcodes = opcodes;
|
||||
MCInstPredicate Predicate = pred;
|
||||
list<int> OperandIndices = operands;
|
||||
}
|
||||
|
||||
// Used by processor models to describe dependency breaking instructions.
|
||||
//
|
||||
// This is mainly an alias for InstructionEquivalenceClass. Input operand
|
||||
// `BrokenDeps` identifies the set of "broken dependencies". There is one bit
|
||||
// per each implicit and explicit input operand. An empty set of broken
|
||||
// dependencies means: "explicit input register operands are independent."
|
||||
class DepBreakingClass<list<Instruction> opcodes, MCInstPredicate pred,
|
||||
list<int> BrokenDeps = []>
|
||||
: InstructionEquivalenceClass<opcodes, pred, BrokenDeps>;
|
||||
|
||||
// A function descriptor used to describe the signature of a predicate methods
|
||||
// which will be expanded by the STIPredicateExpander into a tablegen'd
|
||||
// XXXGenSubtargetInfo class member definition (here, XXX is a target name).
|
||||
//
|
||||
// It describes the signature of a TargetSubtarget hook, as well as a few extra
|
||||
// properties. Examples of extra properties are:
|
||||
// - The default return value for the auto-generate function hook.
|
||||
// - A list of subtarget hooks (Delegates) that are called from this function.
|
||||
//
|
||||
class STIPredicateDecl<string name, MCInstPredicate default = FalsePred,
|
||||
bit overrides = true, bit expandForMC = true,
|
||||
bit updatesOpcodeMask = false,
|
||||
list<STIPredicateDecl> delegates = []> {
|
||||
string Name = name;
|
||||
|
||||
MCInstPredicate DefaultReturnValue = default;
|
||||
|
||||
// True if this method is declared as virtual in class TargetSubtargetInfo.
|
||||
bit OverridesBaseClassMember = overrides;
|
||||
|
||||
// True if we need an equivalent predicate function in the MC layer.
|
||||
bit ExpandForMC = expandForMC;
|
||||
|
||||
// True if the autogenerated method has a extra in/out APInt param used as a
|
||||
// mask of operands.
|
||||
bit UpdatesOpcodeMask = updatesOpcodeMask;
|
||||
|
||||
// A list of STIPredicates used by this definition to delegate part of the
|
||||
// computation. For example, STIPredicateFunction `isDependencyBreaking()`
|
||||
// delegates to `isZeroIdiom()` part of its computation.
|
||||
list<STIPredicateDecl> Delegates = delegates;
|
||||
}
|
||||
|
||||
// A predicate function definition member of class `XXXGenSubtargetInfo`.
|
||||
//
|
||||
// If `Declaration.ExpandForMC` is true, then SubtargetEmitter
|
||||
// will also expand another definition of this method that accepts a MCInst.
|
||||
class STIPredicate<STIPredicateDecl declaration,
|
||||
list<InstructionEquivalenceClass> classes> {
|
||||
STIPredicateDecl Declaration = declaration;
|
||||
list<InstructionEquivalenceClass> Classes = classes;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
// Convenience classes and definitions used by processor scheduling models to
|
||||
// describe dependency breaking instructions and move elimination candidates.
|
||||
let UpdatesOpcodeMask = true in {
|
||||
|
||||
def IsZeroIdiomDecl : STIPredicateDecl<"isZeroIdiom">;
|
||||
|
||||
let Delegates = [IsZeroIdiomDecl] in
|
||||
def IsDepBreakingDecl : STIPredicateDecl<"isDependencyBreaking">;
|
||||
|
||||
} // UpdatesOpcodeMask
|
||||
|
||||
def IsOptimizableRegisterMoveDecl
|
||||
: STIPredicateDecl<"isOptimizableRegisterMove">;
|
||||
|
||||
class IsZeroIdiomFunction<list<DepBreakingClass> classes>
|
||||
: STIPredicate<IsZeroIdiomDecl, classes>;
|
||||
|
||||
class IsDepBreakingFunction<list<DepBreakingClass> classes>
|
||||
: STIPredicate<IsDepBreakingDecl, classes>;
|
||||
|
||||
class IsOptimizableRegisterMove<list<InstructionEquivalenceClass> classes>
|
||||
: STIPredicate<IsOptimizableRegisterMoveDecl, classes>;
|
68
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetIntrinsicInfo.h
vendored
Normal file
68
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetIntrinsicInfo.h
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
//===-- llvm/Target/TargetIntrinsicInfo.h - Instruction Info ----*- 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 describes the target intrinsic instructions to the code generator.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TARGET_TARGETINTRINSICINFO_H
|
||||
#define LLVM_TARGET_TARGETINTRINSICINFO_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Function;
|
||||
class Module;
|
||||
class Type;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
///
|
||||
/// TargetIntrinsicInfo - Interface to description of machine instruction set
|
||||
///
|
||||
class TargetIntrinsicInfo {
|
||||
TargetIntrinsicInfo(const TargetIntrinsicInfo &) = delete;
|
||||
void operator=(const TargetIntrinsicInfo &) = delete;
|
||||
public:
|
||||
TargetIntrinsicInfo();
|
||||
virtual ~TargetIntrinsicInfo();
|
||||
|
||||
/// Return the name of a target intrinsic, e.g. "llvm.bfin.ssync".
|
||||
/// The Tys and numTys parameters are for intrinsics with overloaded types
|
||||
/// (e.g., those using iAny or fAny). For a declaration for an overloaded
|
||||
/// intrinsic, Tys should point to an array of numTys pointers to Type,
|
||||
/// and must provide exactly one type for each overloaded type in the
|
||||
/// intrinsic.
|
||||
virtual std::string getName(unsigned IID, Type **Tys = nullptr,
|
||||
unsigned numTys = 0) const = 0;
|
||||
|
||||
/// Look up target intrinsic by name. Return intrinsic ID or 0 for unknown
|
||||
/// names.
|
||||
virtual unsigned lookupName(const char *Name, unsigned Len) const =0;
|
||||
|
||||
unsigned lookupName(StringRef Name) const {
|
||||
return lookupName(Name.data(), Name.size());
|
||||
}
|
||||
|
||||
/// Return the target intrinsic ID of a function, or 0.
|
||||
virtual unsigned getIntrinsicID(const Function *F) const;
|
||||
|
||||
/// Returns true if the intrinsic can be overloaded.
|
||||
virtual bool isOverloaded(unsigned IID) const = 0;
|
||||
|
||||
/// Create or insert an LLVM Function declaration for an intrinsic,
|
||||
/// and return it. The Tys and numTys are for intrinsics with overloaded
|
||||
/// types. See above for more information.
|
||||
virtual Function *getDeclaration(Module *M, unsigned ID, Type **Tys = nullptr,
|
||||
unsigned numTys = 0) const = 0;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
162
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetItinerary.td
vendored
Normal file
162
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetItinerary.td
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
//===- TargetItinerary.td - Target Itinerary Description --*- tablegen -*-====//
|
||||
//
|
||||
// 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 defines the target-independent scheduling interfaces
|
||||
// which should be implemented by each target that uses instruction
|
||||
// itineraries for scheduling. Itineraries are detailed reservation
|
||||
// tables for each instruction class. They are most appropriate for
|
||||
// in-order machine with complicated scheduling or bundling constraints.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Processor functional unit - These values represent the function units
|
||||
// available across all chip sets for the target. Eg., IntUnit, FPUnit, ...
|
||||
// These may be independent values for each chip set or may be shared across
|
||||
// all chip sets of the target. Each functional unit is treated as a resource
|
||||
// during scheduling and has an affect instruction order based on availability
|
||||
// during a time interval.
|
||||
//
|
||||
class FuncUnit;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pipeline bypass / forwarding - These values specifies the symbolic names of
|
||||
// pipeline bypasses which can be used to forward results of instructions
|
||||
// that are forwarded to uses.
|
||||
class Bypass;
|
||||
def NoBypass : Bypass;
|
||||
|
||||
class ReservationKind<bits<1> val> {
|
||||
int Value = val;
|
||||
}
|
||||
|
||||
def Required : ReservationKind<0>;
|
||||
def Reserved : ReservationKind<1>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction stage - These values represent a non-pipelined step in
|
||||
// the execution of an instruction. Cycles represents the number of
|
||||
// discrete time slots needed to complete the stage. Units represent
|
||||
// the choice of functional units that can be used to complete the
|
||||
// stage. Eg. IntUnit1, IntUnit2. TimeInc indicates how many cycles
|
||||
// should elapse from the start of this stage to the start of the next
|
||||
// stage in the itinerary. For example:
|
||||
//
|
||||
// A stage is specified in one of two ways:
|
||||
//
|
||||
// InstrStage<1, [FU_x, FU_y]> - TimeInc defaults to Cycles
|
||||
// InstrStage<1, [FU_x, FU_y], 0> - TimeInc explicit
|
||||
//
|
||||
|
||||
class InstrStage<int cycles, list<FuncUnit> units,
|
||||
int timeinc = -1,
|
||||
ReservationKind kind = Required> {
|
||||
int Cycles = cycles; // length of stage in machine cycles
|
||||
list<FuncUnit> Units = units; // choice of functional units
|
||||
int TimeInc = timeinc; // cycles till start of next stage
|
||||
int Kind = kind.Value; // kind of FU reservation
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction itinerary - An itinerary represents a sequential series of steps
|
||||
// required to complete an instruction. Itineraries are represented as lists of
|
||||
// instruction stages.
|
||||
//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction itinerary classes - These values represent 'named' instruction
|
||||
// itinerary. Using named itineraries simplifies managing groups of
|
||||
// instructions across chip sets. An instruction uses the same itinerary class
|
||||
// across all chip sets. Thus a new chip set can be added without modifying
|
||||
// instruction information.
|
||||
//
|
||||
class InstrItinClass;
|
||||
def NoItinerary : InstrItinClass;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction itinerary data - These values provide a runtime map of an
|
||||
// instruction itinerary class (name) to its itinerary data.
|
||||
//
|
||||
// NumMicroOps represents the number of micro-operations that each instruction
|
||||
// in the class are decoded to. If the number is zero, then it means the
|
||||
// instruction can decode into variable number of micro-ops and it must be
|
||||
// determined dynamically. This directly relates to the itineraries
|
||||
// global IssueWidth property, which constrains the number of microops
|
||||
// that can issue per cycle.
|
||||
//
|
||||
// OperandCycles are optional "cycle counts". They specify the cycle after
|
||||
// instruction issue the values which correspond to specific operand indices
|
||||
// are defined or read. Bypasses are optional "pipeline forwarding paths", if
|
||||
// a def by an instruction is available on a specific bypass and the use can
|
||||
// read from the same bypass, then the operand use latency is reduced by one.
|
||||
//
|
||||
// InstrItinData<IIC_iLoad_i , [InstrStage<1, [A9_Pipe1]>,
|
||||
// InstrStage<1, [A9_AGU]>],
|
||||
// [3, 1], [A9_LdBypass]>,
|
||||
// InstrItinData<IIC_iMVNr , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>],
|
||||
// [1, 1], [NoBypass, A9_LdBypass]>,
|
||||
//
|
||||
// In this example, the instruction of IIC_iLoadi reads its input on cycle 1
|
||||
// (after issue) and the result of the load is available on cycle 3. The result
|
||||
// is available via forwarding path A9_LdBypass. If it's used by the first
|
||||
// source operand of instructions of IIC_iMVNr class, then the operand latency
|
||||
// is reduced by 1.
|
||||
class InstrItinData<InstrItinClass Class, list<InstrStage> stages,
|
||||
list<int> operandcycles = [],
|
||||
list<Bypass> bypasses = [], int uops = 1> {
|
||||
InstrItinClass TheClass = Class;
|
||||
int NumMicroOps = uops;
|
||||
list<InstrStage> Stages = stages;
|
||||
list<int> OperandCycles = operandcycles;
|
||||
list<Bypass> Bypasses = bypasses;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Processor itineraries - These values represent the set of all itinerary
|
||||
// classes for a given chip set.
|
||||
//
|
||||
// Set property values to -1 to use the default.
|
||||
// See InstrItineraryProps for comments and defaults.
|
||||
class ProcessorItineraries<list<FuncUnit> fu, list<Bypass> bp,
|
||||
list<InstrItinData> iid> {
|
||||
list<FuncUnit> FU = fu;
|
||||
list<Bypass> BP = bp;
|
||||
list<InstrItinData> IID = iid;
|
||||
// The packetizer automaton to use for this itinerary. By default all
|
||||
// itineraries for a target are bundled up into the same automaton. This only
|
||||
// works correctly when there are no conflicts in functional unit IDs between
|
||||
// itineraries. For example, given two itineraries A<[SLOT_A]>, B<[SLOT_B]>,
|
||||
// SLOT_A and SLOT_B will be assigned the same functional unit index, and
|
||||
// the generated packetizer will confuse instructions referencing these slots.
|
||||
//
|
||||
// To avoid this, setting PacketizerNamespace to non-"" will cause this
|
||||
// itinerary to be generated in a different automaton. The subtarget will need
|
||||
// to declare a method "create##Namespace##DFAPacketizer()".
|
||||
string PacketizerNamespace = "";
|
||||
}
|
||||
|
||||
// NoItineraries - A marker that can be used by processors without schedule
|
||||
// info. Subtargets using NoItineraries can bypass the scheduler's
|
||||
// expensive HazardRecognizer because no reservation table is needed.
|
||||
def NoItineraries : ProcessorItineraries<[], [], []>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Combo Function Unit data - This is a map of combo function unit names to
|
||||
// the list of functional units that are included in the combination.
|
||||
//
|
||||
class ComboFuncData<FuncUnit ComboFunc, list<FuncUnit> funclist> {
|
||||
FuncUnit TheComboFunc = ComboFunc;
|
||||
list<FuncUnit> FuncList = funclist;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Combo Function Units - This is a list of all combo function unit data.
|
||||
class ComboFuncUnits<list<ComboFuncData> cfd> {
|
||||
list<ComboFuncData> CFD = cfd;
|
||||
}
|
||||
|
294
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetLoweringObjectFile.h
vendored
Normal file
294
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetLoweringObjectFile.h
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
//===-- llvm/Target/TargetLoweringObjectFile.h - Object Info ----*- 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 implements classes used to handle lowerings specific to common
|
||||
// object file formats.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H
|
||||
#define LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H
|
||||
|
||||
#include "llvm/MC/MCObjectFileInfo.h"
|
||||
#include "llvm/MC/MCRegister.h"
|
||||
#include <cstdint>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Constant;
|
||||
class DataLayout;
|
||||
class Function;
|
||||
class GlobalObject;
|
||||
class GlobalValue;
|
||||
class MachineBasicBlock;
|
||||
class MachineModuleInfo;
|
||||
class Mangler;
|
||||
class MCContext;
|
||||
class MCExpr;
|
||||
class MCSection;
|
||||
class MCSymbol;
|
||||
class MCSymbolRefExpr;
|
||||
class MCStreamer;
|
||||
class MCValue;
|
||||
class Module;
|
||||
class SectionKind;
|
||||
class StringRef;
|
||||
class TargetMachine;
|
||||
class DSOLocalEquivalent;
|
||||
|
||||
class TargetLoweringObjectFile : public MCObjectFileInfo {
|
||||
/// Name-mangler for global names.
|
||||
Mangler *Mang = nullptr;
|
||||
|
||||
protected:
|
||||
bool SupportIndirectSymViaGOTPCRel = false;
|
||||
bool SupportGOTPCRelWithOffset = true;
|
||||
bool SupportDebugThreadLocalLocation = true;
|
||||
bool SupportDSOLocalEquivalentLowering = false;
|
||||
|
||||
/// PersonalityEncoding, LSDAEncoding, TTypeEncoding - Some encoding values
|
||||
/// for EH.
|
||||
unsigned PersonalityEncoding = 0;
|
||||
unsigned LSDAEncoding = 0;
|
||||
unsigned TTypeEncoding = 0;
|
||||
unsigned CallSiteEncoding = 0;
|
||||
|
||||
/// This section contains the static constructor pointer list.
|
||||
MCSection *StaticCtorSection = nullptr;
|
||||
|
||||
/// This section contains the static destructor pointer list.
|
||||
MCSection *StaticDtorSection = nullptr;
|
||||
|
||||
const TargetMachine *TM = nullptr;
|
||||
|
||||
public:
|
||||
TargetLoweringObjectFile() = default;
|
||||
TargetLoweringObjectFile(const TargetLoweringObjectFile &) = delete;
|
||||
TargetLoweringObjectFile &
|
||||
operator=(const TargetLoweringObjectFile &) = delete;
|
||||
virtual ~TargetLoweringObjectFile();
|
||||
|
||||
Mangler &getMangler() const { return *Mang; }
|
||||
|
||||
/// This method must be called before any actual lowering is done. This
|
||||
/// specifies the current context for codegen, and gives the lowering
|
||||
/// implementations a chance to set up their default sections.
|
||||
virtual void Initialize(MCContext &ctx, const TargetMachine &TM);
|
||||
|
||||
virtual void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM,
|
||||
const MCSymbol *Sym) const;
|
||||
|
||||
/// Emit the module-level metadata that the platform cares about.
|
||||
virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M) const {}
|
||||
|
||||
/// Emit Call Graph Profile metadata.
|
||||
void emitCGProfileMetadata(MCStreamer &Streamer, Module &M) const;
|
||||
|
||||
/// Get the module-level metadata that the platform cares about.
|
||||
virtual void getModuleMetadata(Module &M) {}
|
||||
|
||||
/// Given a constant with the SectionKind, return a section that it should be
|
||||
/// placed in.
|
||||
virtual MCSection *getSectionForConstant(const DataLayout &DL,
|
||||
SectionKind Kind, const Constant *C,
|
||||
Align &Alignment) const;
|
||||
|
||||
virtual MCSection *
|
||||
getSectionForMachineBasicBlock(const Function &F,
|
||||
const MachineBasicBlock &MBB,
|
||||
const TargetMachine &TM) const;
|
||||
|
||||
virtual MCSection *
|
||||
getUniqueSectionForFunction(const Function &F,
|
||||
const TargetMachine &TM) const;
|
||||
|
||||
/// Classify the specified global variable into a set of target independent
|
||||
/// categories embodied in SectionKind.
|
||||
static SectionKind getKindForGlobal(const GlobalObject *GO,
|
||||
const TargetMachine &TM);
|
||||
|
||||
/// This method computes the appropriate section to emit the specified global
|
||||
/// variable or function definition. This should not be passed external (or
|
||||
/// available externally) globals.
|
||||
MCSection *SectionForGlobal(const GlobalObject *GO, SectionKind Kind,
|
||||
const TargetMachine &TM) const;
|
||||
|
||||
/// This method computes the appropriate section to emit the specified global
|
||||
/// variable or function definition. This should not be passed external (or
|
||||
/// available externally) globals.
|
||||
MCSection *SectionForGlobal(const GlobalObject *GO,
|
||||
const TargetMachine &TM) const;
|
||||
|
||||
virtual void getNameWithPrefix(SmallVectorImpl<char> &OutName,
|
||||
const GlobalValue *GV,
|
||||
const TargetMachine &TM) const;
|
||||
|
||||
virtual MCSection *getSectionForJumpTable(const Function &F,
|
||||
const TargetMachine &TM) const;
|
||||
virtual MCSection *getSectionForLSDA(const Function &, const MCSymbol &,
|
||||
const TargetMachine &) const {
|
||||
return LSDASection;
|
||||
}
|
||||
|
||||
virtual bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference,
|
||||
const Function &F) const;
|
||||
|
||||
/// Targets should implement this method to assign a section to globals with
|
||||
/// an explicit section specified. The implementation of this method can
|
||||
/// assume that GO->hasSection() is true.
|
||||
virtual MCSection *
|
||||
getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
|
||||
const TargetMachine &TM) const = 0;
|
||||
|
||||
/// Return an MCExpr to use for a reference to the specified global variable
|
||||
/// from exception handling information.
|
||||
virtual const MCExpr *getTTypeGlobalReference(const GlobalValue *GV,
|
||||
unsigned Encoding,
|
||||
const TargetMachine &TM,
|
||||
MachineModuleInfo *MMI,
|
||||
MCStreamer &Streamer) const;
|
||||
|
||||
/// Return the MCSymbol for a private symbol with global value name as its
|
||||
/// base, with the specified suffix.
|
||||
MCSymbol *getSymbolWithGlobalValueBase(const GlobalValue *GV,
|
||||
StringRef Suffix,
|
||||
const TargetMachine &TM) const;
|
||||
|
||||
// The symbol that gets passed to .cfi_personality.
|
||||
virtual MCSymbol *getCFIPersonalitySymbol(const GlobalValue *GV,
|
||||
const TargetMachine &TM,
|
||||
MachineModuleInfo *MMI) const;
|
||||
|
||||
unsigned getPersonalityEncoding() const { return PersonalityEncoding; }
|
||||
unsigned getLSDAEncoding() const { return LSDAEncoding; }
|
||||
unsigned getTTypeEncoding() const { return TTypeEncoding; }
|
||||
unsigned getCallSiteEncoding() const;
|
||||
|
||||
const MCExpr *getTTypeReference(const MCSymbolRefExpr *Sym, unsigned Encoding,
|
||||
MCStreamer &Streamer) const;
|
||||
|
||||
virtual MCSection *getStaticCtorSection(unsigned Priority,
|
||||
const MCSymbol *KeySym) const {
|
||||
return StaticCtorSection;
|
||||
}
|
||||
|
||||
virtual MCSection *getStaticDtorSection(unsigned Priority,
|
||||
const MCSymbol *KeySym) const {
|
||||
return StaticDtorSection;
|
||||
}
|
||||
|
||||
/// Create a symbol reference to describe the given TLS variable when
|
||||
/// emitting the address in debug info.
|
||||
virtual const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const;
|
||||
|
||||
virtual const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
|
||||
const GlobalValue *RHS,
|
||||
const TargetMachine &TM) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Target supports a native lowering of a dso_local_equivalent constant
|
||||
/// without needing to replace it with equivalent IR.
|
||||
bool supportDSOLocalEquivalentLowering() const {
|
||||
return SupportDSOLocalEquivalentLowering;
|
||||
}
|
||||
|
||||
virtual const MCExpr *lowerDSOLocalEquivalent(const DSOLocalEquivalent *Equiv,
|
||||
const TargetMachine &TM) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Target supports replacing a data "PC"-relative access to a symbol
|
||||
/// through another symbol, by accessing the later via a GOT entry instead?
|
||||
bool supportIndirectSymViaGOTPCRel() const {
|
||||
return SupportIndirectSymViaGOTPCRel;
|
||||
}
|
||||
|
||||
/// Target GOT "PC"-relative relocation supports encoding an additional
|
||||
/// binary expression with an offset?
|
||||
bool supportGOTPCRelWithOffset() const {
|
||||
return SupportGOTPCRelWithOffset;
|
||||
}
|
||||
|
||||
/// Target supports TLS offset relocation in debug section?
|
||||
bool supportDebugThreadLocalLocation() const {
|
||||
return SupportDebugThreadLocalLocation;
|
||||
}
|
||||
|
||||
/// Returns the register used as static base in RWPI variants.
|
||||
virtual MCRegister getStaticBase() const { return MCRegister::NoRegister; }
|
||||
|
||||
/// Get the target specific RWPI relocation.
|
||||
virtual const MCExpr *getIndirectSymViaRWPI(const MCSymbol *Sym) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Get the target specific PC relative GOT entry relocation
|
||||
virtual const MCExpr *getIndirectSymViaGOTPCRel(const GlobalValue *GV,
|
||||
const MCSymbol *Sym,
|
||||
const MCValue &MV,
|
||||
int64_t Offset,
|
||||
MachineModuleInfo *MMI,
|
||||
MCStreamer &Streamer) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// If supported, return the section to use for the llvm.commandline
|
||||
/// metadata. Otherwise, return nullptr.
|
||||
virtual MCSection *getSectionForCommandLines() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// On targets that use separate function descriptor symbols, return a section
|
||||
/// for the descriptor given its symbol. Use only with defined functions.
|
||||
virtual MCSection *
|
||||
getSectionForFunctionDescriptor(const Function *F,
|
||||
const TargetMachine &TM) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// On targets that support TOC entries, return a section for the entry given
|
||||
/// the symbol it refers to.
|
||||
/// TODO: Implement this interface for existing ELF targets.
|
||||
virtual MCSection *getSectionForTOCEntry(const MCSymbol *S,
|
||||
const TargetMachine &TM) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// On targets that associate external references with a section, return such
|
||||
/// a section for the given external global.
|
||||
virtual MCSection *
|
||||
getSectionForExternalReference(const GlobalObject *GO,
|
||||
const TargetMachine &TM) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Targets that have a special convention for their symbols could use
|
||||
/// this hook to return a specialized symbol.
|
||||
virtual MCSymbol *getTargetSymbol(const GlobalValue *GV,
|
||||
const TargetMachine &TM) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// If supported, return the function entry point symbol.
|
||||
/// Otherwise, returns nulltpr.
|
||||
/// Func must be a function or an alias which has a function as base object.
|
||||
virtual MCSymbol *getFunctionEntryPointSymbol(const GlobalValue *Func,
|
||||
const TargetMachine &TM) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual MCSection *SelectSectionForGlobal(const GlobalObject *GO,
|
||||
SectionKind Kind,
|
||||
const TargetMachine &TM) const = 0;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H
|
513
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetMachine.h
vendored
Normal file
513
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetMachine.h
vendored
Normal file
@@ -0,0 +1,513 @@
|
||||
//===-- llvm/Target/TargetMachine.h - Target Information --------*- 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 defines the TargetMachine and LLVMTargetMachine classes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TARGET_TARGETMACHINE_H
|
||||
#define LLVM_TARGET_TARGETMACHINE_H
|
||||
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/CodeGen.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/PGOOptions.h"
|
||||
#include "llvm/Target/CGPassBuilderOption.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AAManager;
|
||||
template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
|
||||
class PassManager;
|
||||
using ModulePassManager = PassManager<Module>;
|
||||
|
||||
class Function;
|
||||
class GlobalValue;
|
||||
class MachineFunctionPassManager;
|
||||
class MachineFunctionAnalysisManager;
|
||||
class MachineModuleInfoWrapperPass;
|
||||
class Mangler;
|
||||
class MCAsmInfo;
|
||||
class MCContext;
|
||||
class MCInstrInfo;
|
||||
class MCRegisterInfo;
|
||||
class MCStreamer;
|
||||
class MCSubtargetInfo;
|
||||
class MCSymbol;
|
||||
class raw_pwrite_stream;
|
||||
class PassBuilder;
|
||||
class PassManagerBuilder;
|
||||
struct PerFunctionMIParsingState;
|
||||
class SMDiagnostic;
|
||||
class SMRange;
|
||||
class Target;
|
||||
class TargetIntrinsicInfo;
|
||||
class TargetIRAnalysis;
|
||||
class TargetTransformInfo;
|
||||
class TargetLoweringObjectFile;
|
||||
class TargetPassConfig;
|
||||
class TargetSubtargetInfo;
|
||||
|
||||
// The old pass manager infrastructure is hidden in a legacy namespace now.
|
||||
namespace legacy {
|
||||
class PassManagerBase;
|
||||
}
|
||||
using legacy::PassManagerBase;
|
||||
|
||||
namespace yaml {
|
||||
struct MachineFunctionInfo;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// Primary interface to the complete machine description for the target
|
||||
/// machine. All target-specific information should be accessible through this
|
||||
/// interface.
|
||||
///
|
||||
class TargetMachine {
|
||||
protected: // Can only create subclasses.
|
||||
TargetMachine(const Target &T, StringRef DataLayoutString,
|
||||
const Triple &TargetTriple, StringRef CPU, StringRef FS,
|
||||
const TargetOptions &Options);
|
||||
|
||||
/// The Target that this machine was created for.
|
||||
const Target &TheTarget;
|
||||
|
||||
/// DataLayout for the target: keep ABI type size and alignment.
|
||||
///
|
||||
/// The DataLayout is created based on the string representation provided
|
||||
/// during construction. It is kept here only to avoid reparsing the string
|
||||
/// but should not really be used during compilation, because it has an
|
||||
/// internal cache that is context specific.
|
||||
const DataLayout DL;
|
||||
|
||||
/// Triple string, CPU name, and target feature strings the TargetMachine
|
||||
/// instance is created with.
|
||||
Triple TargetTriple;
|
||||
std::string TargetCPU;
|
||||
std::string TargetFS;
|
||||
|
||||
Reloc::Model RM = Reloc::Static;
|
||||
CodeModel::Model CMModel = CodeModel::Small;
|
||||
CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
|
||||
|
||||
/// Contains target specific asm information.
|
||||
std::unique_ptr<const MCAsmInfo> AsmInfo;
|
||||
std::unique_ptr<const MCRegisterInfo> MRI;
|
||||
std::unique_ptr<const MCInstrInfo> MII;
|
||||
std::unique_ptr<const MCSubtargetInfo> STI;
|
||||
|
||||
unsigned RequireStructuredCFG : 1;
|
||||
unsigned O0WantsFastISel : 1;
|
||||
|
||||
// PGO related tunables.
|
||||
Optional<PGOOptions> PGOOption = None;
|
||||
|
||||
public:
|
||||
const TargetOptions DefaultOptions;
|
||||
mutable TargetOptions Options;
|
||||
|
||||
TargetMachine(const TargetMachine &) = delete;
|
||||
void operator=(const TargetMachine &) = delete;
|
||||
virtual ~TargetMachine();
|
||||
|
||||
const Target &getTarget() const { return TheTarget; }
|
||||
|
||||
const Triple &getTargetTriple() const { return TargetTriple; }
|
||||
StringRef getTargetCPU() const { return TargetCPU; }
|
||||
StringRef getTargetFeatureString() const { return TargetFS; }
|
||||
void setTargetFeatureString(StringRef FS) { TargetFS = std::string(FS); }
|
||||
|
||||
/// Virtual method implemented by subclasses that returns a reference to that
|
||||
/// target's TargetSubtargetInfo-derived member variable.
|
||||
virtual const TargetSubtargetInfo *getSubtargetImpl(const Function &) const {
|
||||
return nullptr;
|
||||
}
|
||||
virtual TargetLoweringObjectFile *getObjFileLowering() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Allocate and return a default initialized instance of the YAML
|
||||
/// representation for the MachineFunctionInfo.
|
||||
virtual yaml::MachineFunctionInfo *createDefaultFuncInfoYAML() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Allocate and initialize an instance of the YAML representation of the
|
||||
/// MachineFunctionInfo.
|
||||
virtual yaml::MachineFunctionInfo *
|
||||
convertFuncInfoToYAML(const MachineFunction &MF) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Parse out the target's MachineFunctionInfo from the YAML representation.
|
||||
virtual bool parseMachineFunctionInfo(const yaml::MachineFunctionInfo &,
|
||||
PerFunctionMIParsingState &PFS,
|
||||
SMDiagnostic &Error,
|
||||
SMRange &SourceRange) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// This method returns a pointer to the specified type of
|
||||
/// TargetSubtargetInfo. In debug builds, it verifies that the object being
|
||||
/// returned is of the correct type.
|
||||
template <typename STC> const STC &getSubtarget(const Function &F) const {
|
||||
return *static_cast<const STC*>(getSubtargetImpl(F));
|
||||
}
|
||||
|
||||
/// Create a DataLayout.
|
||||
const DataLayout createDataLayout() const { return DL; }
|
||||
|
||||
/// Test if a DataLayout if compatible with the CodeGen for this target.
|
||||
///
|
||||
/// The LLVM Module owns a DataLayout that is used for the target independent
|
||||
/// optimizations and code generation. This hook provides a target specific
|
||||
/// check on the validity of this DataLayout.
|
||||
bool isCompatibleDataLayout(const DataLayout &Candidate) const {
|
||||
return DL == Candidate;
|
||||
}
|
||||
|
||||
/// Get the pointer size for this target.
|
||||
///
|
||||
/// This is the only time the DataLayout in the TargetMachine is used.
|
||||
unsigned getPointerSize(unsigned AS) const {
|
||||
return DL.getPointerSize(AS);
|
||||
}
|
||||
|
||||
unsigned getPointerSizeInBits(unsigned AS) const {
|
||||
return DL.getPointerSizeInBits(AS);
|
||||
}
|
||||
|
||||
unsigned getProgramPointerSize() const {
|
||||
return DL.getPointerSize(DL.getProgramAddressSpace());
|
||||
}
|
||||
|
||||
unsigned getAllocaPointerSize() const {
|
||||
return DL.getPointerSize(DL.getAllocaAddrSpace());
|
||||
}
|
||||
|
||||
/// Reset the target options based on the function's attributes.
|
||||
// FIXME: Remove TargetOptions that affect per-function code generation
|
||||
// from TargetMachine.
|
||||
void resetTargetOptions(const Function &F) const;
|
||||
|
||||
/// Return target specific asm information.
|
||||
const MCAsmInfo *getMCAsmInfo() const { return AsmInfo.get(); }
|
||||
|
||||
const MCRegisterInfo *getMCRegisterInfo() const { return MRI.get(); }
|
||||
const MCInstrInfo *getMCInstrInfo() const { return MII.get(); }
|
||||
const MCSubtargetInfo *getMCSubtargetInfo() const { return STI.get(); }
|
||||
|
||||
/// If intrinsic information is available, return it. If not, return null.
|
||||
virtual const TargetIntrinsicInfo *getIntrinsicInfo() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool requiresStructuredCFG() const { return RequireStructuredCFG; }
|
||||
void setRequiresStructuredCFG(bool Value) { RequireStructuredCFG = Value; }
|
||||
|
||||
/// Returns the code generation relocation model. The choices are static, PIC,
|
||||
/// and dynamic-no-pic, and target default.
|
||||
Reloc::Model getRelocationModel() const;
|
||||
|
||||
/// Returns the code model. The choices are small, kernel, medium, large, and
|
||||
/// target default.
|
||||
CodeModel::Model getCodeModel() const;
|
||||
|
||||
bool isPositionIndependent() const;
|
||||
|
||||
bool shouldAssumeDSOLocal(const Module &M, const GlobalValue *GV) const;
|
||||
|
||||
/// Returns true if this target uses emulated TLS.
|
||||
bool useEmulatedTLS() const;
|
||||
|
||||
/// Returns the TLS model which should be used for the given global variable.
|
||||
TLSModel::Model getTLSModel(const GlobalValue *GV) const;
|
||||
|
||||
/// Returns the optimization level: None, Less, Default, or Aggressive.
|
||||
CodeGenOpt::Level getOptLevel() const;
|
||||
|
||||
/// Overrides the optimization level.
|
||||
void setOptLevel(CodeGenOpt::Level Level);
|
||||
|
||||
void setFastISel(bool Enable) { Options.EnableFastISel = Enable; }
|
||||
bool getO0WantsFastISel() { return O0WantsFastISel; }
|
||||
void setO0WantsFastISel(bool Enable) { O0WantsFastISel = Enable; }
|
||||
void setGlobalISel(bool Enable) { Options.EnableGlobalISel = Enable; }
|
||||
void setGlobalISelAbort(GlobalISelAbortMode Mode) {
|
||||
Options.GlobalISelAbort = Mode;
|
||||
}
|
||||
void setMachineOutliner(bool Enable) {
|
||||
Options.EnableMachineOutliner = Enable;
|
||||
}
|
||||
void setSupportsDefaultOutlining(bool Enable) {
|
||||
Options.SupportsDefaultOutlining = Enable;
|
||||
}
|
||||
void setSupportsDebugEntryValues(bool Enable) {
|
||||
Options.SupportsDebugEntryValues = Enable;
|
||||
}
|
||||
|
||||
bool getAIXExtendedAltivecABI() const {
|
||||
return Options.EnableAIXExtendedAltivecABI;
|
||||
}
|
||||
|
||||
bool getUniqueSectionNames() const { return Options.UniqueSectionNames; }
|
||||
|
||||
/// Return true if unique basic block section names must be generated.
|
||||
bool getUniqueBasicBlockSectionNames() const {
|
||||
return Options.UniqueBasicBlockSectionNames;
|
||||
}
|
||||
|
||||
/// Return true if data objects should be emitted into their own section,
|
||||
/// corresponds to -fdata-sections.
|
||||
bool getDataSections() const {
|
||||
return Options.DataSections;
|
||||
}
|
||||
|
||||
/// Return true if functions should be emitted into their own section,
|
||||
/// corresponding to -ffunction-sections.
|
||||
bool getFunctionSections() const {
|
||||
return Options.FunctionSections;
|
||||
}
|
||||
|
||||
/// Return true if visibility attribute should not be emitted in XCOFF,
|
||||
/// corresponding to -mignore-xcoff-visibility.
|
||||
bool getIgnoreXCOFFVisibility() const {
|
||||
return Options.IgnoreXCOFFVisibility;
|
||||
}
|
||||
|
||||
/// Return true if XCOFF traceback table should be emitted,
|
||||
/// corresponding to -xcoff-traceback-table.
|
||||
bool getXCOFFTracebackTable() const { return Options.XCOFFTracebackTable; }
|
||||
|
||||
/// If basic blocks should be emitted into their own section,
|
||||
/// corresponding to -fbasic-block-sections.
|
||||
llvm::BasicBlockSection getBBSectionsType() const {
|
||||
return Options.BBSections;
|
||||
}
|
||||
|
||||
/// Get the list of functions and basic block ids that need unique sections.
|
||||
const MemoryBuffer *getBBSectionsFuncListBuf() const {
|
||||
return Options.BBSectionsFuncListBuf.get();
|
||||
}
|
||||
|
||||
/// Returns true if a cast between SrcAS and DestAS is a noop.
|
||||
virtual bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void setPGOOption(Optional<PGOOptions> PGOOpt) { PGOOption = PGOOpt; }
|
||||
const Optional<PGOOptions> &getPGOOption() const { return PGOOption; }
|
||||
|
||||
/// If the specified generic pointer could be assumed as a pointer to a
|
||||
/// specific address space, return that address space.
|
||||
///
|
||||
/// Under offloading programming, the offloading target may be passed with
|
||||
/// values only prepared on the host side and could assume certain
|
||||
/// properties.
|
||||
virtual unsigned getAssumedAddrSpace(const Value *V) const { return -1; }
|
||||
|
||||
/// If the specified predicate checks whether a generic pointer falls within
|
||||
/// a specified address space, return that generic pointer and the address
|
||||
/// space being queried.
|
||||
///
|
||||
/// Such predicates could be specified in @llvm.assume intrinsics for the
|
||||
/// optimizer to assume that the given generic pointer always falls within
|
||||
/// the address space based on that predicate.
|
||||
virtual std::pair<const Value *, unsigned>
|
||||
getPredicatedAddrSpace(const Value *V) const {
|
||||
return std::make_pair(nullptr, -1);
|
||||
}
|
||||
|
||||
/// Get a \c TargetIRAnalysis appropriate for the target.
|
||||
///
|
||||
/// This is used to construct the new pass manager's target IR analysis pass,
|
||||
/// set up appropriately for this target machine. Even the old pass manager
|
||||
/// uses this to answer queries about the IR.
|
||||
TargetIRAnalysis getTargetIRAnalysis();
|
||||
|
||||
/// Return a TargetTransformInfo for a given function.
|
||||
///
|
||||
/// The returned TargetTransformInfo is specialized to the subtarget
|
||||
/// corresponding to \p F.
|
||||
virtual TargetTransformInfo getTargetTransformInfo(const Function &F);
|
||||
|
||||
/// Allow the target to modify the pass manager, e.g. by calling
|
||||
/// PassManagerBuilder::addExtension.
|
||||
virtual void adjustPassManager(PassManagerBuilder &) {}
|
||||
|
||||
/// Allow the target to modify the pass pipeline with New Pass Manager
|
||||
/// (similar to adjustPassManager for Legacy Pass manager).
|
||||
virtual void registerPassBuilderCallbacks(PassBuilder &) {}
|
||||
|
||||
/// Allow the target to register alias analyses with the AAManager for use
|
||||
/// with the new pass manager. Only affects the "default" AAManager.
|
||||
virtual void registerDefaultAliasAnalyses(AAManager &) {}
|
||||
|
||||
/// Add passes to the specified pass manager to get the specified file
|
||||
/// emitted. Typically this will involve several steps of code generation.
|
||||
/// This method should return true if emission of this file type is not
|
||||
/// supported, or false on success.
|
||||
/// \p MMIWP is an optional parameter that, if set to non-nullptr,
|
||||
/// will be used to set the MachineModuloInfo for this PM.
|
||||
virtual bool
|
||||
addPassesToEmitFile(PassManagerBase &, raw_pwrite_stream &,
|
||||
raw_pwrite_stream *, CodeGenFileType,
|
||||
bool /*DisableVerify*/ = true,
|
||||
MachineModuleInfoWrapperPass *MMIWP = nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Add passes to the specified pass manager to get machine code emitted with
|
||||
/// the MCJIT. This method returns true if machine code is not supported. It
|
||||
/// fills the MCContext Ctx pointer which can be used to build custom
|
||||
/// MCStreamer.
|
||||
///
|
||||
virtual bool addPassesToEmitMC(PassManagerBase &, MCContext *&,
|
||||
raw_pwrite_stream &,
|
||||
bool /*DisableVerify*/ = true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// True if subtarget inserts the final scheduling pass on its own.
|
||||
///
|
||||
/// Branch relaxation, which must happen after block placement, can
|
||||
/// on some targets (e.g. SystemZ) expose additional post-RA
|
||||
/// scheduling opportunities.
|
||||
virtual bool targetSchedulesPostRAScheduling() const { return false; };
|
||||
|
||||
void getNameWithPrefix(SmallVectorImpl<char> &Name, const GlobalValue *GV,
|
||||
Mangler &Mang, bool MayAlwaysUsePrivate = false) const;
|
||||
MCSymbol *getSymbol(const GlobalValue *GV) const;
|
||||
|
||||
/// The integer bit size to use for SjLj based exception handling.
|
||||
static constexpr unsigned DefaultSjLjDataSize = 32;
|
||||
virtual unsigned getSjLjDataSize() const { return DefaultSjLjDataSize; }
|
||||
|
||||
static std::pair<int, int> parseBinutilsVersion(StringRef Version);
|
||||
};
|
||||
|
||||
/// This class describes a target machine that is implemented with the LLVM
|
||||
/// target-independent code generator.
|
||||
///
|
||||
class LLVMTargetMachine : public TargetMachine {
|
||||
protected: // Can only create subclasses.
|
||||
LLVMTargetMachine(const Target &T, StringRef DataLayoutString,
|
||||
const Triple &TT, StringRef CPU, StringRef FS,
|
||||
const TargetOptions &Options, Reloc::Model RM,
|
||||
CodeModel::Model CM, CodeGenOpt::Level OL);
|
||||
|
||||
void initAsmInfo();
|
||||
|
||||
public:
|
||||
/// Get a TargetTransformInfo implementation for the target.
|
||||
///
|
||||
/// The TTI returned uses the common code generator to answer queries about
|
||||
/// the IR.
|
||||
TargetTransformInfo getTargetTransformInfo(const Function &F) override;
|
||||
|
||||
/// Create a pass configuration object to be used by addPassToEmitX methods
|
||||
/// for generating a pipeline of CodeGen passes.
|
||||
virtual TargetPassConfig *createPassConfig(PassManagerBase &PM);
|
||||
|
||||
/// Add passes to the specified pass manager to get the specified file
|
||||
/// emitted. Typically this will involve several steps of code generation.
|
||||
/// \p MMIWP is an optional parameter that, if set to non-nullptr,
|
||||
/// will be used to set the MachineModuloInfo for this PM.
|
||||
bool
|
||||
addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out,
|
||||
raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
|
||||
bool DisableVerify = true,
|
||||
MachineModuleInfoWrapperPass *MMIWP = nullptr) override;
|
||||
|
||||
virtual Error buildCodeGenPipeline(ModulePassManager &,
|
||||
MachineFunctionPassManager &,
|
||||
MachineFunctionAnalysisManager &,
|
||||
raw_pwrite_stream &, raw_pwrite_stream *,
|
||||
CodeGenFileType, CGPassBuilderOption,
|
||||
PassInstrumentationCallbacks *) {
|
||||
return make_error<StringError>("buildCodeGenPipeline is not overridden",
|
||||
inconvertibleErrorCode());
|
||||
}
|
||||
|
||||
virtual std::pair<StringRef, bool> getPassNameFromLegacyName(StringRef) {
|
||||
llvm_unreachable(
|
||||
"getPassNameFromLegacyName parseMIRPipeline is not overridden");
|
||||
}
|
||||
|
||||
/// Add passes to the specified pass manager to get machine code emitted with
|
||||
/// the MCJIT. This method returns true if machine code is not supported. It
|
||||
/// fills the MCContext Ctx pointer which can be used to build custom
|
||||
/// MCStreamer.
|
||||
bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx,
|
||||
raw_pwrite_stream &Out,
|
||||
bool DisableVerify = true) override;
|
||||
|
||||
/// Returns true if the target is expected to pass all machine verifier
|
||||
/// checks. This is a stopgap measure to fix targets one by one. We will
|
||||
/// remove this at some point and always enable the verifier when
|
||||
/// EXPENSIVE_CHECKS is enabled.
|
||||
virtual bool isMachineVerifierClean() const { return true; }
|
||||
|
||||
/// Adds an AsmPrinter pass to the pipeline that prints assembly or
|
||||
/// machine code from the MI representation.
|
||||
bool addAsmPrinter(PassManagerBase &PM, raw_pwrite_stream &Out,
|
||||
raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
|
||||
MCContext &Context);
|
||||
|
||||
Expected<std::unique_ptr<MCStreamer>>
|
||||
createMCStreamer(raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
|
||||
CodeGenFileType FileType, MCContext &Ctx);
|
||||
|
||||
/// True if the target uses physical regs (as nearly all targets do). False
|
||||
/// for stack machines such as WebAssembly and other virtual-register
|
||||
/// machines. If true, all vregs must be allocated before PEI. If false, then
|
||||
/// callee-save register spilling and scavenging are not needed or used. If
|
||||
/// false, implicitly defined registers will still be assumed to be physical
|
||||
/// registers, except that variadic defs will be allocated vregs.
|
||||
virtual bool usesPhysRegsForValues() const { return true; }
|
||||
|
||||
/// True if the target wants to use interprocedural register allocation by
|
||||
/// default. The -enable-ipra flag can be used to override this.
|
||||
virtual bool useIPRA() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// The default variant to use in unqualified `asm` instructions.
|
||||
/// If this returns 0, `asm "$(foo$|bar$)"` will evaluate to `asm "foo"`.
|
||||
virtual int unqualifiedInlineAsmVariant() const { return 0; }
|
||||
};
|
||||
|
||||
/// Helper method for getting the code model, returning Default if
|
||||
/// CM does not have a value. The tiny and kernel models will produce
|
||||
/// an error, so targets that support them or require more complex codemodel
|
||||
/// selection logic should implement and call their own getEffectiveCodeModel.
|
||||
inline CodeModel::Model getEffectiveCodeModel(Optional<CodeModel::Model> CM,
|
||||
CodeModel::Model Default) {
|
||||
if (CM) {
|
||||
// By default, targets do not support the tiny and kernel models.
|
||||
if (*CM == CodeModel::Tiny)
|
||||
report_fatal_error("Target does not support the tiny CodeModel", false);
|
||||
if (*CM == CodeModel::Kernel)
|
||||
report_fatal_error("Target does not support the kernel CodeModel", false);
|
||||
return *CM;
|
||||
}
|
||||
return Default;
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_TARGET_TARGETMACHINE_H
|
433
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetOptions.h
vendored
Normal file
433
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetOptions.h
vendored
Normal file
@@ -0,0 +1,433 @@
|
||||
//===-- llvm/Target/TargetOptions.h - Target Options ------------*- 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 defines command line option flags that are shared across various
|
||||
// targets.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TARGET_TARGETOPTIONS_H
|
||||
#define LLVM_TARGET_TARGETOPTIONS_H
|
||||
|
||||
#include "llvm/ADT/FloatingPointMode.h"
|
||||
#include "llvm/MC/MCTargetOptions.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
struct fltSemantics;
|
||||
class MachineFunction;
|
||||
class MemoryBuffer;
|
||||
|
||||
namespace FloatABI {
|
||||
enum ABIType {
|
||||
Default, // Target-specific (either soft or hard depending on triple, etc).
|
||||
Soft, // Soft float.
|
||||
Hard // Hard float.
|
||||
};
|
||||
}
|
||||
|
||||
namespace FPOpFusion {
|
||||
enum FPOpFusionMode {
|
||||
Fast, // Enable fusion of FP ops wherever it's profitable.
|
||||
Standard, // Only allow fusion of 'blessed' ops (currently just fmuladd).
|
||||
Strict // Never fuse FP-ops.
|
||||
};
|
||||
}
|
||||
|
||||
namespace JumpTable {
|
||||
enum JumpTableType {
|
||||
Single, // Use a single table for all indirect jumptable calls.
|
||||
Arity, // Use one table per number of function parameters.
|
||||
Simplified, // Use one table per function type, with types projected
|
||||
// into 4 types: pointer to non-function, struct,
|
||||
// primitive, and function pointer.
|
||||
Full // Use one table per unique function type
|
||||
};
|
||||
}
|
||||
|
||||
namespace ThreadModel {
|
||||
enum Model {
|
||||
POSIX, // POSIX Threads
|
||||
Single // Single Threaded Environment
|
||||
};
|
||||
}
|
||||
|
||||
enum class BasicBlockSection {
|
||||
All, // Use Basic Block Sections for all basic blocks. A section
|
||||
// for every basic block can significantly bloat object file sizes.
|
||||
List, // Get list of functions & BBs from a file. Selectively enables
|
||||
// basic block sections for a subset of basic blocks which can be
|
||||
// used to control object size bloats from creating sections.
|
||||
Labels, // Do not use Basic Block Sections but label basic blocks. This
|
||||
// is useful when associating profile counts from virtual addresses
|
||||
// to basic blocks.
|
||||
Preset, // Similar to list but the blocks are identified by passes which
|
||||
// seek to use Basic Block Sections, e.g. MachineFunctionSplitter.
|
||||
// This option cannot be set via the command line.
|
||||
None // Do not use Basic Block Sections.
|
||||
};
|
||||
|
||||
enum class EABI {
|
||||
Unknown,
|
||||
Default, // Default means not specified
|
||||
EABI4, // Target-specific (either 4, 5 or gnu depending on triple).
|
||||
EABI5,
|
||||
GNU
|
||||
};
|
||||
|
||||
/// Identify a debugger for "tuning" the debug info.
|
||||
///
|
||||
/// The "debugger tuning" concept allows us to present a more intuitive
|
||||
/// interface that unpacks into different sets of defaults for the various
|
||||
/// individual feature-flag settings, that suit the preferences of the
|
||||
/// various debuggers. However, it's worth remembering that debuggers are
|
||||
/// not the only consumers of debug info, and some variations in DWARF might
|
||||
/// better be treated as target/platform issues. Fundamentally,
|
||||
/// o if the feature is useful (or not) to a particular debugger, regardless
|
||||
/// of the target, that's a tuning decision;
|
||||
/// o if the feature is useful (or not) on a particular platform, regardless
|
||||
/// of the debugger, that's a target decision.
|
||||
/// It's not impossible to see both factors in some specific case.
|
||||
enum class DebuggerKind {
|
||||
Default, ///< No specific tuning requested.
|
||||
GDB, ///< Tune debug info for gdb.
|
||||
LLDB, ///< Tune debug info for lldb.
|
||||
SCE, ///< Tune debug info for SCE targets (e.g. PS4).
|
||||
DBX ///< Tune debug info for dbx.
|
||||
};
|
||||
|
||||
/// Enable abort calls when global instruction selection fails to lower/select
|
||||
/// an instruction.
|
||||
enum class GlobalISelAbortMode {
|
||||
Disable, // Disable the abort.
|
||||
Enable, // Enable the abort.
|
||||
DisableWithDiag // Disable the abort but emit a diagnostic on failure.
|
||||
};
|
||||
|
||||
/// Indicates when and how the Swift async frame pointer bit should be set.
|
||||
enum class SwiftAsyncFramePointerMode {
|
||||
/// Determine whether to set the bit statically or dynamically based
|
||||
/// on the deployment target.
|
||||
DeploymentBased,
|
||||
/// Always set the bit.
|
||||
Always,
|
||||
/// Never set the bit.
|
||||
Never,
|
||||
};
|
||||
|
||||
class TargetOptions {
|
||||
public:
|
||||
TargetOptions()
|
||||
: UnsafeFPMath(false), NoInfsFPMath(false), NoNaNsFPMath(false),
|
||||
NoTrappingFPMath(true), NoSignedZerosFPMath(false),
|
||||
ApproxFuncFPMath(false), EnableAIXExtendedAltivecABI(false),
|
||||
HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false),
|
||||
GuaranteedTailCallOpt(false), StackSymbolOrdering(true),
|
||||
EnableFastISel(false), EnableGlobalISel(false), UseInitArray(false),
|
||||
DisableIntegratedAS(false), RelaxELFRelocations(false),
|
||||
FunctionSections(false), DataSections(false),
|
||||
IgnoreXCOFFVisibility(false), XCOFFTracebackTable(true),
|
||||
UniqueSectionNames(true), UniqueBasicBlockSectionNames(false),
|
||||
TrapUnreachable(false), NoTrapAfterNoreturn(false), TLSSize(0),
|
||||
EmulatedTLS(false), ExplicitEmulatedTLS(false), EnableIPRA(false),
|
||||
EmitStackSizeSection(false), EnableMachineOutliner(false),
|
||||
EnableMachineFunctionSplitter(false), SupportsDefaultOutlining(false),
|
||||
EmitAddrsig(false), EmitCallSiteInfo(false),
|
||||
SupportsDebugEntryValues(false), EnableDebugEntryValues(false),
|
||||
ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false),
|
||||
XRayOmitFunctionIndex(false), DebugStrictDwarf(false),
|
||||
Hotpatch(false),
|
||||
FPDenormalMode(DenormalMode::IEEE, DenormalMode::IEEE) {}
|
||||
|
||||
/// DisableFramePointerElim - This returns true if frame pointer elimination
|
||||
/// optimization should be disabled for the given machine function.
|
||||
bool DisableFramePointerElim(const MachineFunction &MF) const;
|
||||
|
||||
/// If greater than 0, override the default value of
|
||||
/// MCAsmInfo::BinutilsVersion.
|
||||
std::pair<int, int> BinutilsVersion{0, 0};
|
||||
|
||||
/// UnsafeFPMath - This flag is enabled when the
|
||||
/// -enable-unsafe-fp-math flag is specified on the command line. When
|
||||
/// this flag is off (the default), the code generator is not allowed to
|
||||
/// produce results that are "less precise" than IEEE allows. This includes
|
||||
/// use of X86 instructions like FSIN and FCOS instead of libcalls.
|
||||
unsigned UnsafeFPMath : 1;
|
||||
|
||||
/// NoInfsFPMath - This flag is enabled when the
|
||||
/// -enable-no-infs-fp-math flag is specified on the command line. When
|
||||
/// this flag is off (the default), the code generator is not allowed to
|
||||
/// assume the FP arithmetic arguments and results are never +-Infs.
|
||||
unsigned NoInfsFPMath : 1;
|
||||
|
||||
/// NoNaNsFPMath - This flag is enabled when the
|
||||
/// -enable-no-nans-fp-math flag is specified on the command line. When
|
||||
/// this flag is off (the default), the code generator is not allowed to
|
||||
/// assume the FP arithmetic arguments and results are never NaNs.
|
||||
unsigned NoNaNsFPMath : 1;
|
||||
|
||||
/// NoTrappingFPMath - This flag is enabled when the
|
||||
/// -enable-no-trapping-fp-math is specified on the command line. This
|
||||
/// specifies that there are no trap handlers to handle exceptions.
|
||||
unsigned NoTrappingFPMath : 1;
|
||||
|
||||
/// NoSignedZerosFPMath - This flag is enabled when the
|
||||
/// -enable-no-signed-zeros-fp-math is specified on the command line. This
|
||||
/// specifies that optimizations are allowed to treat the sign of a zero
|
||||
/// argument or result as insignificant.
|
||||
unsigned NoSignedZerosFPMath : 1;
|
||||
|
||||
/// ApproxFuncFPMath - This flag is enabled when the
|
||||
/// -enable-approx-func-fp-math is specified on the command line. This
|
||||
/// specifies that optimizations are allowed to substitute math functions
|
||||
/// with approximate calculations
|
||||
unsigned ApproxFuncFPMath : 1;
|
||||
|
||||
/// EnableAIXExtendedAltivecABI - This flag returns true when -vec-extabi is
|
||||
/// specified. The code generator is then able to use both volatile and
|
||||
/// nonvolatile vector registers. When false, the code generator only uses
|
||||
/// volatile vector registers which is the default setting on AIX.
|
||||
unsigned EnableAIXExtendedAltivecABI : 1;
|
||||
|
||||
/// HonorSignDependentRoundingFPMath - This returns true when the
|
||||
/// -enable-sign-dependent-rounding-fp-math is specified. If this returns
|
||||
/// false (the default), the code generator is allowed to assume that the
|
||||
/// rounding behavior is the default (round-to-zero for all floating point
|
||||
/// to integer conversions, and round-to-nearest for all other arithmetic
|
||||
/// truncations). If this is enabled (set to true), the code generator must
|
||||
/// assume that the rounding mode may dynamically change.
|
||||
unsigned HonorSignDependentRoundingFPMathOption : 1;
|
||||
bool HonorSignDependentRoundingFPMath() const;
|
||||
|
||||
/// NoZerosInBSS - By default some codegens place zero-initialized data to
|
||||
/// .bss section. This flag disables such behaviour (necessary, e.g. for
|
||||
/// crt*.o compiling).
|
||||
unsigned NoZerosInBSS : 1;
|
||||
|
||||
/// GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is
|
||||
/// specified on the commandline. When the flag is on, participating targets
|
||||
/// will perform tail call optimization on all calls which use the fastcc
|
||||
/// calling convention and which satisfy certain target-independent
|
||||
/// criteria (being at the end of a function, having the same return type
|
||||
/// as their parent function, etc.), using an alternate ABI if necessary.
|
||||
unsigned GuaranteedTailCallOpt : 1;
|
||||
|
||||
/// StackSymbolOrdering - When true, this will allow CodeGen to order
|
||||
/// the local stack symbols (for code size, code locality, or any other
|
||||
/// heuristics). When false, the local symbols are left in whatever order
|
||||
/// they were generated. Default is true.
|
||||
unsigned StackSymbolOrdering : 1;
|
||||
|
||||
/// EnableFastISel - This flag enables fast-path instruction selection
|
||||
/// which trades away generated code quality in favor of reducing
|
||||
/// compile time.
|
||||
unsigned EnableFastISel : 1;
|
||||
|
||||
/// EnableGlobalISel - This flag enables global instruction selection.
|
||||
unsigned EnableGlobalISel : 1;
|
||||
|
||||
/// EnableGlobalISelAbort - Control abort behaviour when global instruction
|
||||
/// selection fails to lower/select an instruction.
|
||||
GlobalISelAbortMode GlobalISelAbort = GlobalISelAbortMode::Enable;
|
||||
|
||||
/// Control when and how the Swift async frame pointer bit should
|
||||
/// be set.
|
||||
SwiftAsyncFramePointerMode SwiftAsyncFramePointer =
|
||||
SwiftAsyncFramePointerMode::Always;
|
||||
|
||||
/// UseInitArray - Use .init_array instead of .ctors for static
|
||||
/// constructors.
|
||||
unsigned UseInitArray : 1;
|
||||
|
||||
/// Disable the integrated assembler.
|
||||
unsigned DisableIntegratedAS : 1;
|
||||
|
||||
/// Compress DWARF debug sections.
|
||||
DebugCompressionType CompressDebugSections = DebugCompressionType::None;
|
||||
|
||||
unsigned RelaxELFRelocations : 1;
|
||||
|
||||
/// Emit functions into separate sections.
|
||||
unsigned FunctionSections : 1;
|
||||
|
||||
/// Emit data into separate sections.
|
||||
unsigned DataSections : 1;
|
||||
|
||||
/// Do not emit visibility attribute for xcoff.
|
||||
unsigned IgnoreXCOFFVisibility : 1;
|
||||
|
||||
/// Emit XCOFF traceback table.
|
||||
unsigned XCOFFTracebackTable : 1;
|
||||
|
||||
unsigned UniqueSectionNames : 1;
|
||||
|
||||
/// Use unique names for basic block sections.
|
||||
unsigned UniqueBasicBlockSectionNames : 1;
|
||||
|
||||
/// Emit target-specific trap instruction for 'unreachable' IR instructions.
|
||||
unsigned TrapUnreachable : 1;
|
||||
|
||||
/// Do not emit a trap instruction for 'unreachable' IR instructions behind
|
||||
/// noreturn calls, even if TrapUnreachable is true.
|
||||
unsigned NoTrapAfterNoreturn : 1;
|
||||
|
||||
/// Bit size of immediate TLS offsets (0 == use the default).
|
||||
unsigned TLSSize : 8;
|
||||
|
||||
/// EmulatedTLS - This flag enables emulated TLS model, using emutls
|
||||
/// function in the runtime library..
|
||||
unsigned EmulatedTLS : 1;
|
||||
|
||||
/// Whether -emulated-tls or -no-emulated-tls is set.
|
||||
unsigned ExplicitEmulatedTLS : 1;
|
||||
|
||||
/// This flag enables InterProcedural Register Allocation (IPRA).
|
||||
unsigned EnableIPRA : 1;
|
||||
|
||||
/// Emit section containing metadata on function stack sizes.
|
||||
unsigned EmitStackSizeSection : 1;
|
||||
|
||||
/// Enables the MachineOutliner pass.
|
||||
unsigned EnableMachineOutliner : 1;
|
||||
|
||||
/// Enables the MachineFunctionSplitter pass.
|
||||
unsigned EnableMachineFunctionSplitter : 1;
|
||||
|
||||
/// Set if the target supports default outlining behaviour.
|
||||
unsigned SupportsDefaultOutlining : 1;
|
||||
|
||||
/// Emit address-significance table.
|
||||
unsigned EmitAddrsig : 1;
|
||||
|
||||
/// Emit basic blocks into separate sections.
|
||||
BasicBlockSection BBSections = BasicBlockSection::None;
|
||||
|
||||
/// Memory Buffer that contains information on sampled basic blocks and used
|
||||
/// to selectively generate basic block sections.
|
||||
std::shared_ptr<MemoryBuffer> BBSectionsFuncListBuf;
|
||||
|
||||
/// The flag enables call site info production. It is used only for debug
|
||||
/// info, and it is restricted only to optimized code. This can be used for
|
||||
/// something else, so that should be controlled in the frontend.
|
||||
unsigned EmitCallSiteInfo : 1;
|
||||
/// Set if the target supports the debug entry values by default.
|
||||
unsigned SupportsDebugEntryValues : 1;
|
||||
/// When set to true, the EnableDebugEntryValues option forces production
|
||||
/// of debug entry values even if the target does not officially support
|
||||
/// it. Useful for testing purposes only. This flag should never be checked
|
||||
/// directly, always use \ref ShouldEmitDebugEntryValues instead.
|
||||
unsigned EnableDebugEntryValues : 1;
|
||||
/// NOTE: There are targets that still do not support the debug entry values
|
||||
/// production.
|
||||
bool ShouldEmitDebugEntryValues() const;
|
||||
|
||||
// When set to true, use experimental new debug variable location tracking,
|
||||
// which seeks to follow the values of variables rather than their location,
|
||||
// post isel.
|
||||
unsigned ValueTrackingVariableLocations : 1;
|
||||
|
||||
/// Emit DWARF debug frame section.
|
||||
unsigned ForceDwarfFrameSection : 1;
|
||||
|
||||
/// Emit XRay Function Index section
|
||||
unsigned XRayOmitFunctionIndex : 1;
|
||||
|
||||
/// When set to true, don't use DWARF extensions in later DWARF versions.
|
||||
/// By default, it is set to false.
|
||||
unsigned DebugStrictDwarf : 1;
|
||||
|
||||
/// Emit the hotpatch flag in CodeView debug.
|
||||
unsigned Hotpatch : 1;
|
||||
|
||||
/// Name of the stack usage file (i.e., .su file) if user passes
|
||||
/// -fstack-usage. If empty, it can be implied that -fstack-usage is not
|
||||
/// passed on the command line.
|
||||
std::string StackUsageOutput;
|
||||
|
||||
/// If greater than 0, override TargetLoweringBase::PrefLoopAlignment.
|
||||
unsigned LoopAlignment = 0;
|
||||
|
||||
/// FloatABIType - This setting is set by -float-abi=xxx option is specified
|
||||
/// on the command line. This setting may either be Default, Soft, or Hard.
|
||||
/// Default selects the target's default behavior. Soft selects the ABI for
|
||||
/// software floating point, but does not indicate that FP hardware may not
|
||||
/// be used. Such a combination is unfortunately popular (e.g.
|
||||
/// arm-apple-darwin). Hard presumes that the normal FP ABI is used.
|
||||
FloatABI::ABIType FloatABIType = FloatABI::Default;
|
||||
|
||||
/// AllowFPOpFusion - This flag is set by the -fp-contract=xxx option.
|
||||
/// This controls the creation of fused FP ops that store intermediate
|
||||
/// results in higher precision than IEEE allows (E.g. FMAs).
|
||||
///
|
||||
/// Fast mode - allows formation of fused FP ops whenever they're
|
||||
/// profitable.
|
||||
/// Standard mode - allow fusion only for 'blessed' FP ops. At present the
|
||||
/// only blessed op is the fmuladd intrinsic. In the future more blessed ops
|
||||
/// may be added.
|
||||
/// Strict mode - allow fusion only if/when it can be proven that the excess
|
||||
/// precision won't effect the result.
|
||||
///
|
||||
/// Note: This option only controls formation of fused ops by the
|
||||
/// optimizers. Fused operations that are explicitly specified (e.g. FMA
|
||||
/// via the llvm.fma.* intrinsic) will always be honored, regardless of
|
||||
/// the value of this option.
|
||||
FPOpFusion::FPOpFusionMode AllowFPOpFusion = FPOpFusion::Standard;
|
||||
|
||||
/// ThreadModel - This flag specifies the type of threading model to assume
|
||||
/// for things like atomics
|
||||
ThreadModel::Model ThreadModel = ThreadModel::POSIX;
|
||||
|
||||
/// EABIVersion - This flag specifies the EABI version
|
||||
EABI EABIVersion = EABI::Default;
|
||||
|
||||
/// Which debugger to tune for.
|
||||
DebuggerKind DebuggerTuning = DebuggerKind::Default;
|
||||
|
||||
private:
|
||||
/// Flushing mode to assume in default FP environment.
|
||||
DenormalMode FPDenormalMode;
|
||||
|
||||
/// Flushing mode to assume in default FP environment, for float/vector of
|
||||
/// float.
|
||||
DenormalMode FP32DenormalMode;
|
||||
|
||||
public:
|
||||
void setFPDenormalMode(DenormalMode Mode) {
|
||||
FPDenormalMode = Mode;
|
||||
}
|
||||
|
||||
void setFP32DenormalMode(DenormalMode Mode) {
|
||||
FP32DenormalMode = Mode;
|
||||
}
|
||||
|
||||
DenormalMode getRawFPDenormalMode() const {
|
||||
return FPDenormalMode;
|
||||
}
|
||||
|
||||
DenormalMode getRawFP32DenormalMode() const {
|
||||
return FP32DenormalMode;
|
||||
}
|
||||
|
||||
DenormalMode getDenormalMode(const fltSemantics &FPType) const;
|
||||
|
||||
/// What exception model to use
|
||||
ExceptionHandling ExceptionModel = ExceptionHandling::None;
|
||||
|
||||
/// Machine level options.
|
||||
MCTargetOptions MCOptions;
|
||||
|
||||
/// Stores the filename/path of the final .o/.obj file, to be written in the
|
||||
/// debug information. This is used for emitting the CodeView S_OBJNAME
|
||||
/// record.
|
||||
std::string ObjectFilenameForDebug;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
51
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetPfmCounters.td
vendored
Normal file
51
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetPfmCounters.td
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
//===- TargetPfmCounters.td - Target Pfm Counters -*- tablegen ----------*-===//
|
||||
//
|
||||
// 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 defines the target-independent interfaces for performance counters.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Definition of a hardware counters from libpfm identifiers.
|
||||
class PfmCounter<string counter> {
|
||||
// The name of the counter that measures events.
|
||||
// The name can be "some_counter + some_other_counter", in which case the
|
||||
// measured value is the sum of events on these counters.
|
||||
string Counter = counter;
|
||||
}
|
||||
|
||||
// Issue counters can be tied to a ProcResource
|
||||
class PfmIssueCounter<string resource_name, string counter>
|
||||
: PfmCounter<counter> {
|
||||
// The name of the ProcResource on which uops are issued. This is used by
|
||||
// llvm-exegesis to compare measurements with values in the SchedModels.
|
||||
// If the CPU has a sched model, this should correspond to the name of a
|
||||
// ProcResource.
|
||||
string ResourceName = resource_name;
|
||||
}
|
||||
|
||||
def NoPfmCounter : PfmCounter <""> {}
|
||||
|
||||
// Set of PfmCounters for measuring sched model characteristics.
|
||||
class ProcPfmCounters {
|
||||
// Processors can define how to measure cycles by defining a CycleCounter.
|
||||
PfmCounter CycleCounter = NoPfmCounter;
|
||||
// Processors can define how to measure uops by defining a UopsCounter.
|
||||
PfmCounter UopsCounter = NoPfmCounter;
|
||||
// Processors can define how to measure issued uops by defining IssueCounters.
|
||||
list<PfmIssueCounter> IssueCounters = [];
|
||||
}
|
||||
|
||||
// A binding of a set of counters to a CPU.
|
||||
class PfmCountersBinding<string cpu_name, ProcPfmCounters counters> {
|
||||
string CpuName = cpu_name;
|
||||
ProcPfmCounters Counters = counters;
|
||||
}
|
||||
|
||||
// Declares the default binding for unbound CPUs for the target.
|
||||
class PfmCountersDefaultBinding<ProcPfmCounters counters>
|
||||
: PfmCountersBinding<"", counters> {}
|
574
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetSchedule.td
vendored
Normal file
574
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetSchedule.td
vendored
Normal file
@@ -0,0 +1,574 @@
|
||||
//===- TargetSchedule.td - Target Independent Scheduling ---*- tablegen -*-===//
|
||||
//
|
||||
// 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 defines the target-independent scheduling interfaces which should
|
||||
// be implemented by each target which is using TableGen based scheduling.
|
||||
//
|
||||
// The SchedMachineModel is defined by subtargets for three categories of data:
|
||||
// 1. Basic properties for coarse grained instruction cost model.
|
||||
// 2. Scheduler Read/Write resources for simple per-opcode cost model.
|
||||
// 3. Instruction itineraries for detailed reservation tables.
|
||||
//
|
||||
// (1) Basic properties are defined by the SchedMachineModel
|
||||
// class. Target hooks allow subtargets to associate opcodes with
|
||||
// those properties.
|
||||
//
|
||||
// (2) A per-operand machine model can be implemented in any
|
||||
// combination of the following ways:
|
||||
//
|
||||
// A. Associate per-operand SchedReadWrite types with Instructions by
|
||||
// modifying the Instruction definition to inherit from Sched. For
|
||||
// each subtarget, define WriteRes and ReadAdvance to associate
|
||||
// processor resources and latency with each SchedReadWrite type.
|
||||
//
|
||||
// B. In each instruction definition, name an ItineraryClass. For each
|
||||
// subtarget, define ItinRW entries to map ItineraryClass to
|
||||
// per-operand SchedReadWrite types. Unlike method A, these types may
|
||||
// be subtarget specific and can be directly associated with resources
|
||||
// by defining SchedWriteRes and SchedReadAdvance.
|
||||
//
|
||||
// C. In the subtarget, map SchedReadWrite types to specific
|
||||
// opcodes. This overrides any SchedReadWrite types or
|
||||
// ItineraryClasses defined by the Instruction. As in method B, the
|
||||
// subtarget can directly associate resources with SchedReadWrite
|
||||
// types by defining SchedWriteRes and SchedReadAdvance.
|
||||
//
|
||||
// D. In either the target or subtarget, define SchedWriteVariant or
|
||||
// SchedReadVariant to map one SchedReadWrite type onto another
|
||||
// sequence of SchedReadWrite types. This allows dynamic selection of
|
||||
// an instruction's machine model via custom C++ code. It also allows
|
||||
// a machine-independent SchedReadWrite type to map to a sequence of
|
||||
// machine-dependent types.
|
||||
//
|
||||
// (3) A per-pipeline-stage machine model can be implemented by providing
|
||||
// Itineraries in addition to mapping instructions to ItineraryClasses.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Include legacy support for instruction itineraries.
|
||||
include "llvm/Target/TargetItinerary.td"
|
||||
|
||||
class Predicate; // Forward def
|
||||
|
||||
// DAG operator that interprets the DAG args as Instruction defs.
|
||||
def instrs;
|
||||
|
||||
// DAG operator that interprets each DAG arg as a regex pattern for
|
||||
// matching Instruction opcode names.
|
||||
// The regex must match the beginning of the opcode (as in Python re.match).
|
||||
// To avoid matching prefixes, append '$' to the pattern.
|
||||
def instregex;
|
||||
|
||||
// Define the SchedMachineModel and provide basic properties for
|
||||
// coarse grained instruction cost model. Default values for the
|
||||
// properties are defined in MCSchedModel. A value of "-1" in the
|
||||
// target description's SchedMachineModel indicates that the property
|
||||
// is not overridden by the target.
|
||||
//
|
||||
// Target hooks allow subtargets to associate LoadLatency and
|
||||
// HighLatency with groups of opcodes.
|
||||
//
|
||||
// See MCSchedule.h for detailed comments.
|
||||
class SchedMachineModel {
|
||||
int IssueWidth = -1; // Max micro-ops that may be scheduled per cycle.
|
||||
int MicroOpBufferSize = -1; // Max micro-ops that can be buffered.
|
||||
int LoopMicroOpBufferSize = -1; // Max micro-ops that can be buffered for
|
||||
// optimized loop dispatch/execution.
|
||||
int LoadLatency = -1; // Cycles for loads to access the cache.
|
||||
int HighLatency = -1; // Approximation of cycles for "high latency" ops.
|
||||
int MispredictPenalty = -1; // Extra cycles for a mispredicted branch.
|
||||
|
||||
// Per-cycle resources tables.
|
||||
ProcessorItineraries Itineraries = NoItineraries;
|
||||
|
||||
bit PostRAScheduler = false; // Enable Post RegAlloc Scheduler pass.
|
||||
|
||||
// Subtargets that define a model for only a subset of instructions
|
||||
// that have a scheduling class (itinerary class or SchedRW list)
|
||||
// and may actually be generated for that subtarget must clear this
|
||||
// bit. Otherwise, the scheduler considers an unmodelled opcode to
|
||||
// be an error. This should only be set during initial bringup,
|
||||
// or there will be no way to catch simple errors in the model
|
||||
// resulting from changes to the instruction definitions.
|
||||
bit CompleteModel = true;
|
||||
|
||||
// Indicates that we should do full overlap checking for multiple InstrRWs
|
||||
// defining the same instructions within the same SchedMachineModel.
|
||||
// FIXME: Remove when all in tree targets are clean with the full check
|
||||
// enabled.
|
||||
bit FullInstRWOverlapCheck = true;
|
||||
|
||||
// A processor may only implement part of published ISA, due to either new ISA
|
||||
// extensions, (e.g. Pentium 4 doesn't have AVX) or implementation
|
||||
// (ARM/MIPS/PowerPC/SPARC soft float cores).
|
||||
//
|
||||
// For a processor which doesn't support some feature(s), the schedule model
|
||||
// can use:
|
||||
//
|
||||
// let<Predicate> UnsupportedFeatures = [HaveA,..,HaveY];
|
||||
//
|
||||
// to skip the checks for scheduling information when building LLVM for
|
||||
// instructions which have any of the listed predicates in their Predicates
|
||||
// field.
|
||||
list<Predicate> UnsupportedFeatures = [];
|
||||
|
||||
bit NoModel = false; // Special tag to indicate missing machine model.
|
||||
}
|
||||
|
||||
def NoSchedModel : SchedMachineModel {
|
||||
let NoModel = true;
|
||||
let CompleteModel = false;
|
||||
}
|
||||
|
||||
// Define a kind of processor resource that may be common across
|
||||
// similar subtargets.
|
||||
class ProcResourceKind;
|
||||
|
||||
// Define a number of interchangeable processor resources. NumUnits
|
||||
// determines the throughput of instructions that require the resource.
|
||||
//
|
||||
// An optional Super resource may be given to model these resources as
|
||||
// a subset of the more general super resources. Using one of these
|
||||
// resources implies using one of the super resources.
|
||||
//
|
||||
// ProcResourceUnits normally model a few buffered resources within an
|
||||
// out-of-order engine. Buffered resources may be held for multiple
|
||||
// clock cycles, but the scheduler does not pin them to a particular
|
||||
// clock cycle relative to instruction dispatch. Setting BufferSize=0
|
||||
// changes this to an in-order issue/dispatch resource. In this case,
|
||||
// the scheduler counts down from the cycle that the instruction
|
||||
// issues in-order, forcing a stall whenever a subsequent instruction
|
||||
// requires the same resource until the number of ResourceCycles
|
||||
// specified in WriteRes expire. Setting BufferSize=1 changes this to
|
||||
// an in-order latency resource. In this case, the scheduler models
|
||||
// producer/consumer stalls between instructions that use the
|
||||
// resource.
|
||||
//
|
||||
// Examples (all assume an out-of-order engine):
|
||||
//
|
||||
// Use BufferSize = -1 for "issue ports" fed by a unified reservation
|
||||
// station. Here the size of the reservation station is modeled by
|
||||
// MicroOpBufferSize, which should be the minimum size of either the
|
||||
// register rename pool, unified reservation station, or reorder
|
||||
// buffer.
|
||||
//
|
||||
// Use BufferSize = 0 for resources that force "dispatch/issue
|
||||
// groups". (Different processors define dispath/issue
|
||||
// differently. Here we refer to stage between decoding into micro-ops
|
||||
// and moving them into a reservation station.) Normally NumMicroOps
|
||||
// is sufficient to limit dispatch/issue groups. However, some
|
||||
// processors can form groups of with only certain combinations of
|
||||
// instruction types. e.g. POWER7.
|
||||
//
|
||||
// Use BufferSize = 1 for in-order execution units. This is used for
|
||||
// an in-order pipeline within an out-of-order core where scheduling
|
||||
// dependent operations back-to-back is guaranteed to cause a
|
||||
// bubble. e.g. Cortex-a9 floating-point.
|
||||
//
|
||||
// Use BufferSize > 1 for out-of-order executions units with a
|
||||
// separate reservation station. This simply models the size of the
|
||||
// reservation station.
|
||||
//
|
||||
// To model both dispatch/issue groups and in-order execution units,
|
||||
// create two types of units, one with BufferSize=0 and one with
|
||||
// BufferSize=1.
|
||||
//
|
||||
// SchedModel ties these units to a processor for any stand-alone defs
|
||||
// of this class.
|
||||
class ProcResourceUnits<ProcResourceKind kind, int num> {
|
||||
ProcResourceKind Kind = kind;
|
||||
int NumUnits = num;
|
||||
ProcResourceKind Super = ?;
|
||||
int BufferSize = -1;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
// EponymousProcResourceKind helps implement ProcResourceUnits by
|
||||
// allowing a ProcResourceUnits definition to reference itself. It
|
||||
// should not be referenced anywhere else.
|
||||
def EponymousProcResourceKind : ProcResourceKind;
|
||||
|
||||
// Subtargets typically define processor resource kind and number of
|
||||
// units in one place.
|
||||
class ProcResource<int num> : ProcResourceKind,
|
||||
ProcResourceUnits<EponymousProcResourceKind, num>;
|
||||
|
||||
class ProcResGroup<list<ProcResource> resources> : ProcResourceKind {
|
||||
list<ProcResource> Resources = resources;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
int BufferSize = -1;
|
||||
}
|
||||
|
||||
// A target architecture may define SchedReadWrite types and associate
|
||||
// them with instruction operands.
|
||||
class SchedReadWrite;
|
||||
|
||||
// List the per-operand types that map to the machine model of an
|
||||
// instruction. One SchedWrite type must be listed for each explicit
|
||||
// def operand in order. Additional SchedWrite types may optionally be
|
||||
// listed for implicit def operands. SchedRead types may optionally
|
||||
// be listed for use operands in order. The order of defs relative to
|
||||
// uses is insignificant. This way, the same SchedReadWrite list may
|
||||
// be used for multiple forms of an operation. For example, a
|
||||
// two-address instruction could have two tied operands or single
|
||||
// operand that both reads and writes a reg. In both cases we have a
|
||||
// single SchedWrite and single SchedRead in any order.
|
||||
class Sched<list<SchedReadWrite> schedrw> {
|
||||
list<SchedReadWrite> SchedRW = schedrw;
|
||||
}
|
||||
|
||||
// Define a scheduler resource associated with a def operand.
|
||||
class SchedWrite : SchedReadWrite;
|
||||
def NoWrite : SchedWrite;
|
||||
|
||||
// Define a scheduler resource associated with a use operand.
|
||||
class SchedRead : SchedReadWrite;
|
||||
|
||||
// Define a SchedWrite that is modeled as a sequence of other
|
||||
// SchedWrites with additive latency. This allows a single operand to
|
||||
// be mapped the resources composed from a set of previously defined
|
||||
// SchedWrites.
|
||||
//
|
||||
// If the final write in this sequence is a SchedWriteVariant marked
|
||||
// Variadic, then the list of prior writes are distributed across all
|
||||
// operands after resolving the predicate for the final write.
|
||||
//
|
||||
// SchedModel silences warnings but is ignored.
|
||||
class WriteSequence<list<SchedWrite> writes, int rep = 1> : SchedWrite {
|
||||
list<SchedWrite> Writes = writes;
|
||||
int Repeat = rep;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
// Define values common to WriteRes and SchedWriteRes.
|
||||
//
|
||||
// SchedModel ties these resources to a processor.
|
||||
class ProcWriteResources<list<ProcResourceKind> resources> {
|
||||
list<ProcResourceKind> ProcResources = resources;
|
||||
list<int> ResourceCycles = [];
|
||||
int Latency = 1;
|
||||
int NumMicroOps = 1;
|
||||
bit BeginGroup = false;
|
||||
bit EndGroup = false;
|
||||
// Allow a processor to mark some scheduling classes as unsupported
|
||||
// for stronger verification.
|
||||
bit Unsupported = false;
|
||||
// Allow a processor to mark some scheduling classes as single-issue.
|
||||
// SingleIssue is an alias for Begin/End Group.
|
||||
bit SingleIssue = false;
|
||||
// An instruction is allowed to retire out-of-order if RetireOOO is
|
||||
// true for at least one of its writes. This field is only used by
|
||||
// MCA for in-order subtargets, and is ignored for other targets.
|
||||
bit RetireOOO = false;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
// Define the resources and latency of a SchedWrite. This will be used
|
||||
// directly by targets that have no itinerary classes. In this case,
|
||||
// SchedWrite is defined by the target, while WriteResources is
|
||||
// defined by the subtarget, and maps the SchedWrite to processor
|
||||
// resources.
|
||||
//
|
||||
// If a target already has itinerary classes, SchedWriteResources can
|
||||
// be used instead to define subtarget specific SchedWrites and map
|
||||
// them to processor resources in one place. Then ItinRW can map
|
||||
// itinerary classes to the subtarget's SchedWrites.
|
||||
//
|
||||
// ProcResources indicates the set of resources consumed by the write.
|
||||
// Optionally, ResourceCycles indicates the number of cycles the
|
||||
// resource is consumed. Each ResourceCycles item is paired with the
|
||||
// ProcResource item at the same position in its list. ResourceCycles
|
||||
// can be `[]`: in that case, all resources are consumed for a single
|
||||
// cycle, regardless of latency, which models a fully pipelined processing
|
||||
// unit. A value of 0 for ResourceCycles means that the resource must
|
||||
// be available but is not consumed, which is only relevant for
|
||||
// unbuffered resources.
|
||||
//
|
||||
// By default, each SchedWrite takes one micro-op, which is counted
|
||||
// against the processor's IssueWidth limit. If an instruction can
|
||||
// write multiple registers with a single micro-op, the subtarget
|
||||
// should define one of the writes to be zero micro-ops. If a
|
||||
// subtarget requires multiple micro-ops to write a single result, it
|
||||
// should either override the write's NumMicroOps to be greater than 1
|
||||
// or require additional writes. Extra writes can be required either
|
||||
// by defining a WriteSequence, or simply listing extra writes in the
|
||||
// instruction's list of writers beyond the number of "def"
|
||||
// operands. The scheduler assumes that all micro-ops must be
|
||||
// dispatched in the same cycle. These micro-ops may be required to
|
||||
// begin or end the current dispatch group.
|
||||
class WriteRes<SchedWrite write, list<ProcResourceKind> resources>
|
||||
: ProcWriteResources<resources> {
|
||||
SchedWrite WriteType = write;
|
||||
}
|
||||
|
||||
// Directly name a set of WriteResources defining a new SchedWrite
|
||||
// type at the same time. This class is unaware of its SchedModel so
|
||||
// must be referenced by InstRW or ItinRW.
|
||||
class SchedWriteRes<list<ProcResourceKind> resources> : SchedWrite,
|
||||
ProcWriteResources<resources>;
|
||||
|
||||
// Define values common to ReadAdvance and SchedReadAdvance.
|
||||
//
|
||||
// SchedModel ties these resources to a processor.
|
||||
class ProcReadAdvance<int cycles, list<SchedWrite> writes = []> {
|
||||
int Cycles = cycles;
|
||||
list<SchedWrite> ValidWrites = writes;
|
||||
// Allow a processor to mark some scheduling classes as unsupported
|
||||
// for stronger verification.
|
||||
bit Unsupported = false;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
// A processor may define a ReadAdvance associated with a SchedRead
|
||||
// to reduce latency of a prior write by N cycles. A negative advance
|
||||
// effectively increases latency, which may be used for cross-domain
|
||||
// stalls.
|
||||
//
|
||||
// A ReadAdvance may be associated with a list of SchedWrites
|
||||
// to implement pipeline bypass. The Writes list may be empty to
|
||||
// indicate operands that are always read this number of Cycles later
|
||||
// than a normal register read, allowing the read's parent instruction
|
||||
// to issue earlier relative to the writer.
|
||||
class ReadAdvance<SchedRead read, int cycles, list<SchedWrite> writes = []>
|
||||
: ProcReadAdvance<cycles, writes> {
|
||||
SchedRead ReadType = read;
|
||||
}
|
||||
|
||||
// Directly associate a new SchedRead type with a delay and optional
|
||||
// pipeline bypass. For use with InstRW or ItinRW.
|
||||
class SchedReadAdvance<int cycles, list<SchedWrite> writes = []> : SchedRead,
|
||||
ProcReadAdvance<cycles, writes>;
|
||||
|
||||
// Define SchedRead defaults. Reads seldom need special treatment.
|
||||
def ReadDefault : SchedRead;
|
||||
def NoReadAdvance : SchedReadAdvance<0>;
|
||||
|
||||
// Define shared code that will be in the same scope as all
|
||||
// SchedPredicates. Available variables are:
|
||||
// (const MachineInstr *MI, const TargetSchedModel *SchedModel)
|
||||
class PredicateProlog<code c> {
|
||||
code Code = c;
|
||||
}
|
||||
|
||||
// Base class for scheduling predicates.
|
||||
class SchedPredicateBase;
|
||||
|
||||
// A scheduling predicate whose logic is defined by a MCInstPredicate.
|
||||
// This can directly be used by SchedWriteVariant definitions.
|
||||
class MCSchedPredicate<MCInstPredicate P> : SchedPredicateBase {
|
||||
MCInstPredicate Pred = P;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
// Define a predicate to determine which SchedVariant applies to a
|
||||
// particular MachineInstr. The code snippet is used as an
|
||||
// if-statement's expression. Available variables are MI, SchedModel,
|
||||
// and anything defined in a PredicateProlog.
|
||||
//
|
||||
// SchedModel silences warnings but is ignored.
|
||||
class SchedPredicate<code pred> : SchedPredicateBase {
|
||||
SchedMachineModel SchedModel = ?;
|
||||
code Predicate = pred;
|
||||
}
|
||||
|
||||
// Define a predicate to be typically used as the default case in a
|
||||
// SchedVariant. It the SchedVariant does not use any other predicate based on
|
||||
// MCSchedPredicate, this is the default scheduling case used by llvm-mca.
|
||||
def NoSchedPred : MCSchedPredicate<TruePred>;
|
||||
|
||||
// Associate a predicate with a list of SchedReadWrites. By default,
|
||||
// the selected SchedReadWrites are still associated with a single
|
||||
// operand and assumed to execute sequentially with additive
|
||||
// latency. However, if the parent SchedWriteVariant or
|
||||
// SchedReadVariant is marked "Variadic", then each Selected
|
||||
// SchedReadWrite is mapped in place to the instruction's variadic
|
||||
// operands. In this case, latency is not additive. If the current Variant
|
||||
// is already part of a Sequence, then that entire chain leading up to
|
||||
// the Variant is distributed over the variadic operands.
|
||||
class SchedVar<SchedPredicateBase pred, list<SchedReadWrite> selected> {
|
||||
SchedPredicateBase Predicate = pred;
|
||||
list<SchedReadWrite> Selected = selected;
|
||||
}
|
||||
|
||||
// SchedModel silences warnings but is ignored.
|
||||
class SchedVariant<list<SchedVar> variants> {
|
||||
list<SchedVar> Variants = variants;
|
||||
bit Variadic = false;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
// A SchedWriteVariant is a single SchedWrite type that maps to a list
|
||||
// of SchedWrite types under the conditions defined by its predicates.
|
||||
//
|
||||
// A Variadic write is expanded to cover multiple "def" operands. The
|
||||
// SchedVariant's Expansion list is then interpreted as one write
|
||||
// per-operand instead of the usual sequential writes feeding a single
|
||||
// operand.
|
||||
class SchedWriteVariant<list<SchedVar> variants> : SchedWrite,
|
||||
SchedVariant<variants> {
|
||||
}
|
||||
|
||||
// A SchedReadVariant is a single SchedRead type that maps to a list
|
||||
// of SchedRead types under the conditions defined by its predicates.
|
||||
//
|
||||
// A Variadic write is expanded to cover multiple "readsReg" operands as
|
||||
// explained above.
|
||||
class SchedReadVariant<list<SchedVar> variants> : SchedRead,
|
||||
SchedVariant<variants> {
|
||||
}
|
||||
|
||||
// Map a set of opcodes to a list of SchedReadWrite types. This allows
|
||||
// the subtarget to easily override specific operations.
|
||||
//
|
||||
// SchedModel ties this opcode mapping to a processor.
|
||||
class InstRW<list<SchedReadWrite> rw, dag instrlist> {
|
||||
list<SchedReadWrite> OperandReadWrites = rw;
|
||||
dag Instrs = instrlist;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
// Allow a subtarget to mark some instructions as unsupported.
|
||||
bit Unsupported = false;
|
||||
}
|
||||
|
||||
// Map a set of itinerary classes to SchedReadWrite resources. This is
|
||||
// used to bootstrap a target (e.g. ARM) when itineraries already
|
||||
// exist and changing InstrInfo is undesirable.
|
||||
//
|
||||
// SchedModel ties this ItineraryClass mapping to a processor.
|
||||
class ItinRW<list<SchedReadWrite> rw, list<InstrItinClass> iic> {
|
||||
list<InstrItinClass> MatchedItinClasses = iic;
|
||||
list<SchedReadWrite> OperandReadWrites = rw;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
// Alias a target-defined SchedReadWrite to a processor specific
|
||||
// SchedReadWrite. This allows a subtarget to easily map a
|
||||
// SchedReadWrite type onto a WriteSequence, SchedWriteVariant, or
|
||||
// SchedReadVariant.
|
||||
//
|
||||
// SchedModel will usually be provided by surrounding let statement
|
||||
// and ties this SchedAlias mapping to a processor.
|
||||
class SchedAlias<SchedReadWrite match, SchedReadWrite alias> {
|
||||
SchedReadWrite MatchRW = match;
|
||||
SchedReadWrite AliasRW = alias;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
// Allow the definition of processor register files for register renaming
|
||||
// purposes.
|
||||
//
|
||||
// Each processor register file declares:
|
||||
// - The set of registers that can be renamed.
|
||||
// - The number of physical registers which can be used for register renaming
|
||||
// purpose.
|
||||
// - The cost of a register rename.
|
||||
// - The set of registers that allow move elimination.
|
||||
// - The maximum number of moves that can be eliminated every cycle.
|
||||
// - Whether move elimination is limited to register moves whose input
|
||||
// is known to be zero.
|
||||
//
|
||||
// The cost of a rename is the number of physical registers allocated by the
|
||||
// register alias table to map the new definition. By default, register can be
|
||||
// renamed at the cost of a single physical register. Note that register costs
|
||||
// are defined at register class granularity (see field `Costs`).
|
||||
//
|
||||
// The set of registers that are subject to register renaming is declared using
|
||||
// a list of register classes (see field `RegClasses`). An empty list of
|
||||
// register classes means: all the logical registers defined by the target can
|
||||
// be fully renamed.
|
||||
//
|
||||
// A register R can be renamed if its register class appears in the `RegClasses`
|
||||
// set. When R is written, a new alias is allocated at the cost of one or more
|
||||
// physical registers; as a result, false dependencies on R are removed.
|
||||
//
|
||||
// A sub-register V of register R is implicitly part of the same register file.
|
||||
// However, V is only renamed if its register class is part of `RegClasses`.
|
||||
// Otherwise, the processor keeps it (as well as any other different part
|
||||
// of R) together with R, and a write of V always causes a compulsory read of R.
|
||||
//
|
||||
// This is what happens for example on AMD processors (at least from Bulldozer
|
||||
// onwards), where AL and AH are not treated as independent from AX, and AX is
|
||||
// not treated as independent from EAX. A write to AL has an implicitly false
|
||||
// dependency on the last write to EAX (or a portion of EAX). As a consequence,
|
||||
// a write to AL cannot go in parallel with a write to AH.
|
||||
//
|
||||
// There is no false dependency if the partial register write belongs to a
|
||||
// register class that is in `RegClasses`.
|
||||
// There is also no penalty for writes that "clear the content a super-register"
|
||||
// (see MC/MCInstrAnalysis.h - method MCInstrAnalysis::clearsSuperRegisters()).
|
||||
// On x86-64, 32-bit GPR writes implicitly zero the upper half of the underlying
|
||||
// physical register, effectively removing any false dependencies with the
|
||||
// previous register definition.
|
||||
//
|
||||
// TODO: This implementation assumes that there is no limit in the number of
|
||||
// renames per cycle, which might not be true for all hardware or register
|
||||
// classes. Also, there is no limit to how many times the same logical register
|
||||
// can be renamed during the same cycle.
|
||||
//
|
||||
// TODO: we don't currently model merge penalties for the case where a write to
|
||||
// a part of a register is followed by a read from a larger part of the same
|
||||
// register. On some Intel chips, different parts of a GPR can be stored in
|
||||
// different physical registers. However, there is a cost to pay for when the
|
||||
// partial write is combined with the previous super-register definition. We
|
||||
// should add support for these cases, and correctly model merge problems with
|
||||
// partial register accesses.
|
||||
//
|
||||
// Field MaxMovesEliminatedPerCycle specifies how many moves can be eliminated
|
||||
// every cycle. A default value of zero for that field means: there is no limit
|
||||
// to the number of moves that can be eliminated by this register file.
|
||||
//
|
||||
// An instruction MI is a candidate for move elimination if a call to
|
||||
// method TargetSubtargetInfo::isOptimizableRegisterMove(MI) returns true (see
|
||||
// llvm/CodeGen/TargetSubtargetInfo.h, and llvm/MC/MCInstrAnalysis.h).
|
||||
//
|
||||
// Subtargets can instantiate tablegen class IsOptimizableRegisterMove (see
|
||||
// llvm/Target/TargetInstrPredicate.td) to customize the set of move elimination
|
||||
// candidates. By default, no instruction is a valid move elimination candidate.
|
||||
//
|
||||
// A register move MI is eliminated only if:
|
||||
// - MI is a move elimination candidate.
|
||||
// - The destination register is from a register class that allows move
|
||||
// elimination (see field `AllowMoveElimination` below).
|
||||
// - Constraints on the move kind, and the maximum number of moves that can be
|
||||
// eliminated per cycle are all met.
|
||||
|
||||
class RegisterFile<int numPhysRegs, list<RegisterClass> Classes = [],
|
||||
list<int> Costs = [], list<bit> AllowMoveElim = [],
|
||||
int MaxMoveElimPerCy = 0, bit AllowZeroMoveElimOnly = false> {
|
||||
list<RegisterClass> RegClasses = Classes;
|
||||
list<int> RegCosts = Costs;
|
||||
list<bit> AllowMoveElimination = AllowMoveElim;
|
||||
int NumPhysRegs = numPhysRegs;
|
||||
int MaxMovesEliminatedPerCycle = MaxMoveElimPerCy;
|
||||
bit AllowZeroMoveEliminationOnly = AllowZeroMoveElimOnly;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
// Describe the retire control unit.
|
||||
// A retire control unit specifies the size of the reorder buffer, as well as
|
||||
// the maximum number of opcodes that can be retired every cycle.
|
||||
// A value less-than-or-equal-to zero for field 'ReorderBufferSize' means: "the
|
||||
// size is unknown". The idea is that external tools can fall-back to using
|
||||
// field MicroOpBufferSize in SchedModel if the reorder buffer size is unknown.
|
||||
// A zero or negative value for field 'MaxRetirePerCycle' means "no
|
||||
// restrictions on the number of instructions retired per cycle".
|
||||
// Models can optionally specify up to one instance of RetireControlUnit per
|
||||
// scheduling model.
|
||||
class RetireControlUnit<int bufferSize, int retirePerCycle> {
|
||||
int ReorderBufferSize = bufferSize;
|
||||
int MaxRetirePerCycle = retirePerCycle;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
// Base class for Load/StoreQueue. It is used to identify processor resources
|
||||
// which describe load/store queues in the LS unit.
|
||||
class MemoryQueue<ProcResourceKind PR> {
|
||||
ProcResourceKind QueueDescriptor = PR;
|
||||
SchedMachineModel SchedModel = ?;
|
||||
}
|
||||
|
||||
class LoadQueue<ProcResourceKind LDQueue> : MemoryQueue<LDQueue>;
|
||||
class StoreQueue<ProcResourceKind STQueue> : MemoryQueue<STQueue>;
|
1668
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetSelectionDAG.td
vendored
Normal file
1668
thirdparty/capstone/suite/synctools/tablegen/include/llvm/Target/TargetSelectionDAG.td
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user