forked from OSchip/llvm-project
[Hexagon] Update MCTargetDesc
Changes include: - Updates to the instruction descriptor flags. - Improvements to the packet shuffler and checker. - Updates to the handling of certain relocations. - Better handling of duplex instructions. llvm-svn: 294226
This commit is contained in:
parent
11d0b8df5f
commit
8cdfe8ecf3
|
@ -27,9 +27,9 @@ def ArchV5: SubtargetFeature<"v5", "HexagonArchVersion", "V5", "Hexagon V5">;
|
|||
def ArchV55: SubtargetFeature<"v55", "HexagonArchVersion", "V55", "Hexagon V55">;
|
||||
def ArchV60: SubtargetFeature<"v60", "HexagonArchVersion", "V60", "Hexagon V60">;
|
||||
|
||||
def FeatureHVX: SubtargetFeature<"hvx", "UseHVXOps", "true",
|
||||
def ExtensionHVX: SubtargetFeature<"hvx", "UseHVXOps", "true",
|
||||
"Hexagon HVX instructions">;
|
||||
def FeatureHVXDbl: SubtargetFeature<"hvx-double", "UseHVXDblOps", "true",
|
||||
def ExtensionHVXDbl: SubtargetFeature<"hvx-double", "UseHVXDblOps", "true",
|
||||
"Hexagon HVX Double instructions">;
|
||||
def FeatureLongCalls: SubtargetFeature<"long-calls", "UseLongCalls", "true",
|
||||
"Use constant-extended calls">;
|
||||
|
@ -46,10 +46,10 @@ def HasV60T : Predicate<"HST->hasV60TOps()">,
|
|||
def UseMEMOP : Predicate<"HST->useMemOps()">;
|
||||
def IEEERndNearV5T : Predicate<"HST->modeIEEERndNear()">;
|
||||
def UseHVXDbl : Predicate<"HST->useHVXDblOps()">,
|
||||
AssemblerPredicate<"FeatureHVXDbl">;
|
||||
AssemblerPredicate<"ExtensionHVXDbl">;
|
||||
def UseHVXSgl : Predicate<"HST->useHVXSglOps()">;
|
||||
def UseHVX : Predicate<"HST->useHVXSglOps() ||HST->useHVXDblOps()">,
|
||||
AssemblerPredicate<"FeatureHVX">;
|
||||
AssemblerPredicate<"ExtensionHVX">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Classes used for relation maps.
|
||||
|
@ -271,7 +271,7 @@ def : Proc<"hexagonv5", HexagonModelV4,
|
|||
def : Proc<"hexagonv55", HexagonModelV55,
|
||||
[ArchV4, ArchV5, ArchV55]>;
|
||||
def : Proc<"hexagonv60", HexagonModelV60,
|
||||
[ArchV4, ArchV5, ArchV55, ArchV60, FeatureHVX]>;
|
||||
[ArchV4, ArchV5, ArchV55, ArchV60, ExtensionHVX]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Declare the target which we are implementing
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
// *** Must match HexagonBaseInfo.h ***
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class IType<bits<5> t> {
|
||||
bits<5> Value = t;
|
||||
class IType<bits<6> t> {
|
||||
bits<6> Value = t;
|
||||
}
|
||||
def TypePSEUDO : IType<0>;
|
||||
def TypeALU32 : IType<1>;
|
||||
|
@ -99,85 +99,85 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern,
|
|||
|
||||
// Instruction type according to the ISA.
|
||||
IType Type = type;
|
||||
let TSFlags{4-0} = Type.Value;
|
||||
let TSFlags{5-0} = Type.Value;
|
||||
|
||||
// Solo instructions, i.e., those that cannot be in a packet with others.
|
||||
bits<1> isSolo = 0;
|
||||
let TSFlags{5} = isSolo;
|
||||
let TSFlags{6} = isSolo;
|
||||
// Packed only with A or X-type instructions.
|
||||
bits<1> isSoloAX = 0;
|
||||
let TSFlags{6} = isSoloAX;
|
||||
let TSFlags{7} = isSoloAX;
|
||||
// Only A-type instruction in first slot or nothing.
|
||||
bits<1> isSoloAin1 = 0;
|
||||
let TSFlags{7} = isSoloAin1;
|
||||
let TSFlags{8} = isSoloAin1;
|
||||
|
||||
// Predicated instructions.
|
||||
bits<1> isPredicated = 0;
|
||||
let TSFlags{8} = isPredicated;
|
||||
let TSFlags{9} = isPredicated;
|
||||
bits<1> isPredicatedFalse = 0;
|
||||
let TSFlags{9} = isPredicatedFalse;
|
||||
let TSFlags{10} = isPredicatedFalse;
|
||||
bits<1> isPredicatedNew = 0;
|
||||
let TSFlags{10} = isPredicatedNew;
|
||||
let TSFlags{11} = isPredicatedNew;
|
||||
bits<1> isPredicateLate = 0;
|
||||
let TSFlags{11} = isPredicateLate; // Late predicate producer insn.
|
||||
let TSFlags{12} = isPredicateLate; // Late predicate producer insn.
|
||||
|
||||
// New-value insn helper fields.
|
||||
bits<1> isNewValue = 0;
|
||||
let TSFlags{12} = isNewValue; // New-value consumer insn.
|
||||
let TSFlags{13} = isNewValue; // New-value consumer insn.
|
||||
bits<1> hasNewValue = 0;
|
||||
let TSFlags{13} = hasNewValue; // New-value producer insn.
|
||||
let TSFlags{14} = hasNewValue; // New-value producer insn.
|
||||
bits<3> opNewValue = 0;
|
||||
let TSFlags{16-14} = opNewValue; // New-value produced operand.
|
||||
let TSFlags{17-15} = opNewValue; // New-value produced operand.
|
||||
bits<1> isNVStorable = 0;
|
||||
let TSFlags{17} = isNVStorable; // Store that can become new-value store.
|
||||
let TSFlags{18} = isNVStorable; // Store that can become new-value store.
|
||||
bits<1> isNVStore = 0;
|
||||
let TSFlags{18} = isNVStore; // New-value store insn.
|
||||
let TSFlags{19} = isNVStore; // New-value store insn.
|
||||
bits<1> isCVLoadable = 0;
|
||||
let TSFlags{19} = isCVLoadable; // Load that can become cur-value load.
|
||||
let TSFlags{20} = isCVLoadable; // Load that can become cur-value load.
|
||||
bits<1> isCVLoad = 0;
|
||||
let TSFlags{20} = isCVLoad; // Cur-value load insn.
|
||||
let TSFlags{21} = isCVLoad; // Cur-value load insn.
|
||||
|
||||
// Immediate extender helper fields.
|
||||
bits<1> isExtendable = 0;
|
||||
let TSFlags{21} = isExtendable; // Insn may be extended.
|
||||
let TSFlags{22} = isExtendable; // Insn may be extended.
|
||||
bits<1> isExtended = 0;
|
||||
let TSFlags{22} = isExtended; // Insn must be extended.
|
||||
let TSFlags{23} = isExtended; // Insn must be extended.
|
||||
bits<3> opExtendable = 0;
|
||||
let TSFlags{25-23} = opExtendable; // Which operand may be extended.
|
||||
let TSFlags{26-24} = opExtendable; // Which operand may be extended.
|
||||
bits<1> isExtentSigned = 0;
|
||||
let TSFlags{26} = isExtentSigned; // Signed or unsigned range.
|
||||
let TSFlags{27} = isExtentSigned; // Signed or unsigned range.
|
||||
bits<5> opExtentBits = 0;
|
||||
let TSFlags{31-27} = opExtentBits; //Number of bits of range before extending.
|
||||
let TSFlags{32-28} = opExtentBits; //Number of bits of range before extending.
|
||||
bits<2> opExtentAlign = 0;
|
||||
let TSFlags{33-32} = opExtentAlign; // Alignment exponent before extending.
|
||||
let TSFlags{34-33} = opExtentAlign; // Alignment exponent before extending.
|
||||
|
||||
// If an instruction is valid on a subtarget, set the corresponding
|
||||
// bit from validSubTargets.
|
||||
// By default, instruction is valid on all subtargets.
|
||||
SubTarget validSubTargets = HasAnySubT;
|
||||
let TSFlags{39-34} = validSubTargets.Value;
|
||||
let TSFlags{40-35} = validSubTargets.Value;
|
||||
|
||||
// Addressing mode for load/store instructions.
|
||||
AddrModeType addrMode = NoAddrMode;
|
||||
let TSFlags{42-40} = addrMode.Value;
|
||||
let TSFlags{43-41} = addrMode.Value;
|
||||
|
||||
// Memory access size for mem access instructions (load/store)
|
||||
MemAccessSize accessSize = NoMemAccess;
|
||||
let TSFlags{46-43} = accessSize.Value;
|
||||
let TSFlags{47-44} = accessSize.Value;
|
||||
|
||||
bits<1> isTaken = 0;
|
||||
let TSFlags {47} = isTaken; // Branch prediction.
|
||||
let TSFlags {48} = isTaken; // Branch prediction.
|
||||
|
||||
bits<1> isFP = 0;
|
||||
let TSFlags {48} = isFP; // Floating-point.
|
||||
let TSFlags {49} = isFP; // Floating-point.
|
||||
|
||||
bits<1> hasNewValue2 = 0;
|
||||
let TSFlags{50} = hasNewValue2; // Second New-value producer insn.
|
||||
let TSFlags{51} = hasNewValue2; // Second New-value producer insn.
|
||||
bits<3> opNewValue2 = 0;
|
||||
let TSFlags{53-51} = opNewValue2; // Second New-value produced operand.
|
||||
let TSFlags{54-52} = opNewValue2; // Second New-value produced operand.
|
||||
|
||||
bits<1> isAccumulator = 0;
|
||||
let TSFlags{54} = isAccumulator;
|
||||
let TSFlags{55} = isAccumulator;
|
||||
|
||||
bit cofMax1 = 0;
|
||||
let TSFlags{60} = cofMax1;
|
||||
|
@ -200,6 +200,7 @@ class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern,
|
|||
let NValueST = !if(isNVStore, "true", "false");
|
||||
let isNT = !if(isNonTemporal, "true", "false");
|
||||
|
||||
let hasSideEffects = 0;
|
||||
// *** Must match MCTargetDesc/HexagonBaseInfo.h ***
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
//----------------------------------------------------------------------------//
|
||||
|
||||
def TypeV4LDST : IType<9>;
|
||||
def TypeNV : IType<10>;
|
||||
def TypeNCJ : IType<10>;
|
||||
def TypeDUPLEX : IType<11>;
|
||||
def TypeCJ : IType<12>;
|
||||
def TypeEXTENDER : IType<30>;
|
||||
|
@ -61,7 +61,7 @@ class InstDuplex<bits<4> iClass, list<dag> pattern = [],
|
|||
|
||||
// *** Must match MCTargetDesc/HexagonBaseInfo.h ***
|
||||
|
||||
let TSFlags{4-0} = Type.Value;
|
||||
let TSFlags{5-0} = Type.Value;
|
||||
|
||||
// Predicated instructions.
|
||||
bits<1> isPredicated = 0;
|
||||
|
@ -107,7 +107,7 @@ class InstDuplex<bits<4> iClass, list<dag> pattern = [],
|
|||
//
|
||||
class NVInst<dag outs, dag ins, string asmstr, list<dag> pattern = [],
|
||||
string cstr = "", InstrItinClass itin = NCJ_tc_3or4stall_SLOT0>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, itin, TypeNV>, OpcodeHexagon;
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, itin, TypeNCJ>, OpcodeHexagon;
|
||||
|
||||
class NVInst_V4<dag outs, dag ins, string asmstr, list<dag> pattern = [],
|
||||
string cstr = "", InstrItinClass itin = NCJ_tc_3or4stall_SLOT0>
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonFixupKinds.h"
|
||||
#include "HexagonMCTargetDesc.h"
|
||||
#include "MCTargetDesc/HexagonBaseInfo.h"
|
||||
#include "MCTargetDesc/HexagonMCChecker.h"
|
||||
#include "MCTargetDesc/HexagonMCCodeEmitter.h"
|
||||
#include "MCTargetDesc/HexagonMCTargetDesc.h"
|
||||
#include "MCTargetDesc/HexagonMCInstrInfo.h"
|
||||
#include "MCTargetDesc/HexagonMCShuffler.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
|
@ -59,9 +59,10 @@ class HexagonAsmBackend : public MCAsmBackend {
|
|||
RF.getFixups() = Fixups;
|
||||
}
|
||||
public:
|
||||
HexagonAsmBackend(const Target &T, uint8_t OSABI, StringRef CPU) :
|
||||
OSABI(OSABI), MCII (T.createMCInstrInfo()), RelaxTarget(new MCInst *),
|
||||
Extender(nullptr) {}
|
||||
HexagonAsmBackend(const Target &T, const Triple &TT, uint8_t OSABI,
|
||||
StringRef CPU) :
|
||||
OSABI(OSABI), CPU(CPU), MCII(T.createMCInstrInfo()),
|
||||
RelaxTarget(new MCInst *), Extender(nullptr) {}
|
||||
|
||||
MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
|
||||
return createHexagonELFObjectWriter(OS, OSABI, CPU);
|
||||
|
@ -88,101 +89,101 @@ public:
|
|||
// This table *must* be in same the order of fixup_* kinds in
|
||||
// HexagonFixupKinds.h.
|
||||
//
|
||||
// namei offset bits flags
|
||||
{ "fixup_Hexagon_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B15_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B7_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_8", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GPREL16_0", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GPREL16_1", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GPREL16_2", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GPREL16_3", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_HL16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_B13_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B9_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B32_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_B22_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B15_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B13_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B9_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B7_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_12_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_10_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_9_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_8_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_7_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_32_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_COPY", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GLOB_DAT", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_JMP_SLOT", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_RELATIVE", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_GOTREL_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOTREL_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOTREL_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPMOD_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_LD_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_GD_GOT_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_GOT_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_GOT_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_GOT_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_6_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_GOTREL_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOTREL_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOTREL_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_GOT_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_GOT_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_GOT_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_11_X", 0, 32, 0 }
|
||||
// namei offset bits flags
|
||||
{ "fixup_Hexagon_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B15_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B7_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_8", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GPREL16_0", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GPREL16_1", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GPREL16_2", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GPREL16_3", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_HL16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_B13_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B9_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B32_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_B22_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B15_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B13_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B9_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_B7_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_12_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_10_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_9_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_8_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_7_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_32_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_COPY", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GLOB_DAT", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_JMP_SLOT", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_RELATIVE", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_PLT_B22_PCREL", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_GOTREL_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOTREL_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOTREL_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPMOD_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_PLT_B22_PCREL",0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_LD_PLT_B22_PCREL",0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_GD_GOT_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_GOT_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_GOT_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_GOT_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_LO16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_HI16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_32", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_16", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_6_PCREL_X", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_Hexagon_GOTREL_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOTREL_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOTREL_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GOT_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_DTPREL_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_GOT_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_GOT_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_GD_GOT_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_LD_GOT_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_IE_GOT_11_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_32_6_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_16_X", 0, 32, 0 },
|
||||
{ "fixup_Hexagon_TPREL_11_X", 0, 32, 0 }
|
||||
};
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
|
@ -526,7 +527,7 @@ public:
|
|||
if (llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeJ ||
|
||||
(llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeCJ &&
|
||||
MCID.isBranch()) ||
|
||||
(llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeNV &&
|
||||
(llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeNCJ &&
|
||||
MCID.isBranch()) ||
|
||||
(llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeCR &&
|
||||
HMI.getOpcode() != Hexagon::C4_addipc))
|
||||
|
@ -723,7 +724,8 @@ public:
|
|||
Size = 0;
|
||||
}
|
||||
}
|
||||
bool Error = HexagonMCShuffle(*MCII, RF.getSubtargetInfo(), Inst);
|
||||
bool Error = HexagonMCShuffle(true, *MCII, RF.getSubtargetInfo(),
|
||||
Inst);
|
||||
//assert(!Error);
|
||||
(void)Error;
|
||||
ReplaceInstruction(Asm.getEmitter(), RF, Inst);
|
||||
|
@ -738,15 +740,17 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
}; // class HexagonAsmBackend
|
||||
|
||||
namespace llvm {
|
||||
MCAsmBackend *createHexagonAsmBackend(Target const &T,
|
||||
} // namespace
|
||||
|
||||
// MCAsmBackend
|
||||
MCAsmBackend *llvm::createHexagonAsmBackend(Target const &T,
|
||||
MCRegisterInfo const & /*MRI*/,
|
||||
const Triple &TT, StringRef CPU,
|
||||
const MCTargetOptions &Options) {
|
||||
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
|
||||
return new HexagonAsmBackend(T, OSABI, CPU);
|
||||
}
|
||||
|
||||
StringRef CPUString = Hexagon_MC::selectHexagonCPU(TT, CPU);
|
||||
return new HexagonAsmBackend(T, TT, OSABI, CPUString);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace HexagonII {
|
|||
TypeSYSTEM = 7,
|
||||
TypeXTYPE = 8,
|
||||
TypeV4LDST = 9,
|
||||
TypeNV = 10,
|
||||
TypeNCJ = 10,
|
||||
TypeDUPLEX = 11,
|
||||
TypeCJ = 12,
|
||||
TypeCVI_FIRST = 13,
|
||||
|
@ -68,16 +68,10 @@ namespace HexagonII {
|
|||
};
|
||||
|
||||
enum SubTarget {
|
||||
HasV2SubT = 0xf,
|
||||
HasV2SubTOnly = 0x1,
|
||||
NoV2SubT = 0x0,
|
||||
HasV3SubT = 0xe,
|
||||
HasV3SubTOnly = 0x2,
|
||||
NoV3SubT = 0x1,
|
||||
HasV4SubT = 0xc,
|
||||
NoV4SubT = 0x3,
|
||||
HasV5SubT = 0x8,
|
||||
NoV5SubT = 0x7
|
||||
HasV4SubT = 0x3f,
|
||||
HasV5SubT = 0x3e,
|
||||
HasV55SubT = 0x3c,
|
||||
HasV60SubT = 0x38,
|
||||
};
|
||||
|
||||
enum AddrMode {
|
||||
|
@ -107,102 +101,101 @@ namespace HexagonII {
|
|||
enum {
|
||||
// This 5-bit field describes the insn type.
|
||||
TypePos = 0,
|
||||
TypeMask = 0x1f,
|
||||
TypeMask = 0x3f,
|
||||
|
||||
// Solo instructions.
|
||||
SoloPos = 5,
|
||||
SoloPos = 6,
|
||||
SoloMask = 0x1,
|
||||
// Packed only with A or X-type instructions.
|
||||
SoloAXPos = 6,
|
||||
SoloAXPos = 7,
|
||||
SoloAXMask = 0x1,
|
||||
// Only A-type instruction in first slot or nothing.
|
||||
SoloAin1Pos = 7,
|
||||
SoloAin1Pos = 8,
|
||||
SoloAin1Mask = 0x1,
|
||||
|
||||
// Predicated instructions.
|
||||
PredicatedPos = 8,
|
||||
PredicatedPos = 9,
|
||||
PredicatedMask = 0x1,
|
||||
PredicatedFalsePos = 9,
|
||||
PredicatedFalsePos = 10,
|
||||
PredicatedFalseMask = 0x1,
|
||||
PredicatedNewPos = 10,
|
||||
PredicatedNewPos = 11,
|
||||
PredicatedNewMask = 0x1,
|
||||
PredicateLatePos = 11,
|
||||
PredicateLatePos = 12,
|
||||
PredicateLateMask = 0x1,
|
||||
|
||||
// New-Value consumer instructions.
|
||||
NewValuePos = 12,
|
||||
NewValuePos = 13,
|
||||
NewValueMask = 0x1,
|
||||
// New-Value producer instructions.
|
||||
hasNewValuePos = 13,
|
||||
hasNewValuePos = 14,
|
||||
hasNewValueMask = 0x1,
|
||||
// Which operand consumes or produces a new value.
|
||||
NewValueOpPos = 14,
|
||||
NewValueOpPos = 15,
|
||||
NewValueOpMask = 0x7,
|
||||
// Stores that can become new-value stores.
|
||||
mayNVStorePos = 17,
|
||||
mayNVStorePos = 18,
|
||||
mayNVStoreMask = 0x1,
|
||||
// New-value store instructions.
|
||||
NVStorePos = 18,
|
||||
NVStorePos = 19,
|
||||
NVStoreMask = 0x1,
|
||||
// Loads that can become current-value loads.
|
||||
mayCVLoadPos = 19,
|
||||
mayCVLoadPos = 20,
|
||||
mayCVLoadMask = 0x1,
|
||||
// Current-value load instructions.
|
||||
CVLoadPos = 20,
|
||||
CVLoadPos = 21,
|
||||
CVLoadMask = 0x1,
|
||||
|
||||
// Extendable insns.
|
||||
ExtendablePos = 21,
|
||||
ExtendablePos = 22,
|
||||
ExtendableMask = 0x1,
|
||||
// Insns must be extended.
|
||||
ExtendedPos = 22,
|
||||
ExtendedPos = 23,
|
||||
ExtendedMask = 0x1,
|
||||
// Which operand may be extended.
|
||||
ExtendableOpPos = 23,
|
||||
ExtendableOpPos = 24,
|
||||
ExtendableOpMask = 0x7,
|
||||
// Signed or unsigned range.
|
||||
ExtentSignedPos = 26,
|
||||
ExtentSignedPos = 27,
|
||||
ExtentSignedMask = 0x1,
|
||||
// Number of bits of range before extending operand.
|
||||
ExtentBitsPos = 27,
|
||||
ExtentBitsPos = 28,
|
||||
ExtentBitsMask = 0x1f,
|
||||
// Alignment power-of-two before extending operand.
|
||||
ExtentAlignPos = 32,
|
||||
ExtentAlignPos = 33,
|
||||
ExtentAlignMask = 0x3,
|
||||
|
||||
// Valid subtargets
|
||||
validSubTargetPos = 34,
|
||||
validSubTargetMask = 0xf,
|
||||
validSubTargetPos = 35,
|
||||
validSubTargetMask = 0x3f,
|
||||
|
||||
// Addressing mode for load/store instructions.
|
||||
AddrModePos = 40,
|
||||
AddrModePos = 41,
|
||||
AddrModeMask = 0x7,
|
||||
// Access size for load/store instructions.
|
||||
MemAccessSizePos = 43,
|
||||
MemAccessSizePos = 44,
|
||||
MemAccesSizeMask = 0xf,
|
||||
|
||||
// Branch predicted taken.
|
||||
TakenPos = 47,
|
||||
TakenPos = 48,
|
||||
TakenMask = 0x1,
|
||||
|
||||
// Floating-point instructions.
|
||||
FPPos = 48,
|
||||
FPPos = 49,
|
||||
FPMask = 0x1,
|
||||
|
||||
// New-Value producer-2 instructions.
|
||||
hasNewValuePos2 = 50,
|
||||
hasNewValuePos2 = 51,
|
||||
hasNewValueMask2 = 0x1,
|
||||
|
||||
// Which operand consumes or produces a new value.
|
||||
NewValueOpPos2 = 51,
|
||||
NewValueOpPos2 = 52,
|
||||
NewValueOpMask2 = 0x7,
|
||||
|
||||
// Accumulator instructions.
|
||||
AccumulatorPos = 54,
|
||||
AccumulatorPos = 55,
|
||||
AccumulatorMask = 0x1,
|
||||
|
||||
// Complex XU, prevent xu competition by preferring slot3
|
||||
PrefersSlot3Pos = 55,
|
||||
PrefersSlot3Pos = 56,
|
||||
PrefersSlot3Mask = 0x1,
|
||||
|
||||
CofMax1Pos = 60,
|
||||
|
@ -217,8 +210,6 @@ namespace HexagonII {
|
|||
// Hexagon Specific MachineOperand flags.
|
||||
MO_NO_FLAG,
|
||||
|
||||
HMOTF_ConstExtended = 1,
|
||||
|
||||
/// MO_PCREL - On a symbol operand, indicates a PC-relative relocation
|
||||
/// Used for computing a global address for PIC compilations
|
||||
MO_PCREL,
|
||||
|
@ -250,7 +241,13 @@ namespace HexagonII {
|
|||
|
||||
// MO_TPREL - indicates relocation for TLS
|
||||
// local Executable method
|
||||
MO_TPREL
|
||||
MO_TPREL,
|
||||
|
||||
// HMOTF_ConstExtended
|
||||
// Addendum to abovem, indicates a const extended op
|
||||
// Can be used as a mask.
|
||||
HMOTF_ConstExtended = 0x80
|
||||
|
||||
};
|
||||
|
||||
// Hexagon Sub-instruction classes.
|
||||
|
|
|
@ -23,6 +23,7 @@ HexagonMCAsmInfo::HexagonMCAsmInfo(const Triple &TT) {
|
|||
Data32bitsDirective = "\t.word\t";
|
||||
Data64bitsDirective = nullptr; // .xword is only supported by V9.
|
||||
CommentString = "//";
|
||||
SupportsDebugInformation = true;
|
||||
|
||||
LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment;
|
||||
InlineAsmStart = "# InlineAsm Start";
|
||||
|
@ -30,8 +31,8 @@ HexagonMCAsmInfo::HexagonMCAsmInfo(const Triple &TT) {
|
|||
ZeroDirective = "\t.space\t";
|
||||
AscizDirective = "\t.string\t";
|
||||
|
||||
SupportsDebugInformation = true;
|
||||
MinInstAlignment = 4;
|
||||
UsesELFSectionDirectiveForBSS = true;
|
||||
ExceptionsType = ExceptionHandling::DwarfCFI;
|
||||
UseLogicalShr = false;
|
||||
}
|
||||
|
|
|
@ -47,12 +47,40 @@ void HexagonMCChecker::init() {
|
|||
if (HexagonMCInstrInfo::isBundle(MCB))
|
||||
// Unfurl a bundle.
|
||||
for (auto const&I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
init(*I.getInst());
|
||||
MCInst const &Inst = *I.getInst();
|
||||
if (HexagonMCInstrInfo::isDuplex(MCII, Inst)) {
|
||||
init(*Inst.getOperand(0).getInst());
|
||||
init(*Inst.getOperand(1).getInst());
|
||||
}
|
||||
else
|
||||
init(Inst);
|
||||
}
|
||||
else
|
||||
init(MCB);
|
||||
}
|
||||
|
||||
void HexagonMCChecker::initReg(MCInst const &MCI, unsigned R, unsigned &PredReg,
|
||||
bool &isTrue) {
|
||||
if (HexagonMCInstrInfo::isPredicated(MCII, MCI) && isPredicateRegister(R)) {
|
||||
// Note an used predicate register.
|
||||
PredReg = R;
|
||||
isTrue = HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI);
|
||||
|
||||
// Note use of new predicate register.
|
||||
if (HexagonMCInstrInfo::isPredicatedNew(MCII, MCI))
|
||||
NewPreds.insert(PredReg);
|
||||
}
|
||||
else
|
||||
// Note register use. Super-registers are not tracked directly,
|
||||
// but their components.
|
||||
for(MCRegAliasIterator SRI(R, &RI, !MCSubRegIterator(R, &RI).isValid());
|
||||
SRI.isValid();
|
||||
++SRI)
|
||||
if (!MCSubRegIterator(*SRI, &RI).isValid())
|
||||
// Skip super-registers used indirectly.
|
||||
Uses.insert(*SRI);
|
||||
}
|
||||
|
||||
void HexagonMCChecker::init(MCInst const& MCI) {
|
||||
const MCInstrDesc& MCID = HexagonMCInstrInfo::getDesc(MCII, MCI);
|
||||
unsigned PredReg = Hexagon::NoRegister;
|
||||
|
@ -60,28 +88,10 @@ void HexagonMCChecker::init(MCInst const& MCI) {
|
|||
|
||||
// Get used registers.
|
||||
for (unsigned i = MCID.getNumDefs(); i < MCID.getNumOperands(); ++i)
|
||||
if (MCI.getOperand(i).isReg()) {
|
||||
unsigned R = MCI.getOperand(i).getReg();
|
||||
|
||||
if (HexagonMCInstrInfo::isPredicated(MCII, MCI) && isPredicateRegister(R)) {
|
||||
// Note an used predicate register.
|
||||
PredReg = R;
|
||||
isTrue = HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI);
|
||||
|
||||
// Note use of new predicate register.
|
||||
if (HexagonMCInstrInfo::isPredicatedNew(MCII, MCI))
|
||||
NewPreds.insert(PredReg);
|
||||
}
|
||||
else
|
||||
// Note register use. Super-registers are not tracked directly,
|
||||
// but their components.
|
||||
for(MCRegAliasIterator SRI(R, &RI, !MCSubRegIterator(R, &RI).isValid());
|
||||
SRI.isValid();
|
||||
++SRI)
|
||||
if (!MCSubRegIterator(*SRI, &RI).isValid())
|
||||
// Skip super-registers used indirectly.
|
||||
Uses.insert(*SRI);
|
||||
}
|
||||
if (MCI.getOperand(i).isReg())
|
||||
initReg(MCI, MCI.getOperand(i).getReg(), PredReg, isTrue);
|
||||
for (unsigned i = 0; i < MCID.getNumImplicitUses(); ++i)
|
||||
initReg(MCI, MCID.getImplicitUses()[i], PredReg, isTrue);
|
||||
|
||||
// Get implicit register definitions.
|
||||
if (const MCPhysReg *ImpDef = MCID.getImplicitDefs())
|
||||
|
@ -216,9 +226,11 @@ void HexagonMCChecker::init(MCInst const& MCI) {
|
|||
if (!MCSubRegIterator(N, &RI).isValid()) {
|
||||
// Super-registers cannot use new values.
|
||||
if (MCID.isBranch())
|
||||
NewUses[N] = NewSense::Jmp(llvm::HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNV);
|
||||
NewUses[N] = NewSense::Jmp(
|
||||
llvm::HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNCJ);
|
||||
else
|
||||
NewUses[N] = NewSense::Use(PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI));
|
||||
NewUses[N] = NewSense::Use(
|
||||
PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -230,14 +242,18 @@ HexagonMCChecker::HexagonMCChecker(MCInstrInfo const &MCII, MCSubtargetInfo cons
|
|||
init();
|
||||
}
|
||||
|
||||
bool HexagonMCChecker::check() {
|
||||
bool HexagonMCChecker::check(bool FullCheck) {
|
||||
bool chkB = checkBranches();
|
||||
bool chkP = checkPredicates();
|
||||
bool chkNV = checkNewValues();
|
||||
bool chkR = checkRegisters();
|
||||
bool chkS = checkSolo();
|
||||
bool chkSh = checkShuffle();
|
||||
bool chkSl = checkSlots();
|
||||
bool chkSh = true;
|
||||
if (FullCheck)
|
||||
chkSh = checkShuffle();
|
||||
bool chkSl = true;
|
||||
if (FullCheck)
|
||||
chkSl = checkSlots();
|
||||
bool chk = chkB && chkP && chkNV && chkR && chkS && chkSh && chkSl;
|
||||
|
||||
return chk;
|
||||
|
@ -504,7 +520,7 @@ bool HexagonMCChecker::checkShuffle() {
|
|||
HexagonMCErrInfo errInfo;
|
||||
// Branch info is lost when duplexing. The unduplexed insns must be
|
||||
// checked and only branch errors matter for this case.
|
||||
HexagonMCShuffler MCS(MCII, STI, MCB);
|
||||
HexagonMCShuffler MCS(true, MCII, STI, MCB);
|
||||
if (!MCS.check()) {
|
||||
if (MCS.getError() == HexagonShuffler::SHUFFLE_ERROR_BRANCHES) {
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_SHUFFLE);
|
||||
|
@ -513,7 +529,7 @@ bool HexagonMCChecker::checkShuffle() {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
HexagonMCShuffler MCSDX(MCII, STI, MCBDX);
|
||||
HexagonMCShuffler MCSDX(true, MCII, STI, MCBDX);
|
||||
if (!MCSDX.check()) {
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_SHUFFLE);
|
||||
errInfo.setShuffleError(MCSDX.getError());
|
||||
|
|
|
@ -168,6 +168,7 @@ class HexagonMCChecker {
|
|||
|
||||
void init();
|
||||
void init(MCInst const&);
|
||||
void initReg(MCInst const &, unsigned, unsigned &PredReg, bool &isTrue);
|
||||
|
||||
// Checks performed.
|
||||
bool checkBranches();
|
||||
|
@ -177,6 +178,7 @@ class HexagonMCChecker {
|
|||
bool checkSolo();
|
||||
bool checkShuffle();
|
||||
bool checkSlots();
|
||||
bool checkSize();
|
||||
|
||||
static void compoundRegisterMap(unsigned&);
|
||||
|
||||
|
@ -196,7 +198,7 @@ class HexagonMCChecker {
|
|||
explicit HexagonMCChecker(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst& mcb, MCInst &mcbdx,
|
||||
const MCRegisterInfo& ri);
|
||||
|
||||
bool check();
|
||||
bool check(bool FullCheck = true);
|
||||
|
||||
/// add a new error/warning
|
||||
void addErrInfo(HexagonMCErrInfo &err) { ErrInfoQ.push(err.s); };
|
||||
|
|
|
@ -65,9 +65,10 @@ uint32_t HexagonMCCodeEmitter::parseBits(size_t Last,
|
|||
return HexagonII::INST_PARSE_NOT_END;
|
||||
}
|
||||
|
||||
void HexagonMCCodeEmitter::encodeInstruction(MCInst const &MI, raw_ostream &OS,
|
||||
/// EncodeInstruction - Emit the bundle
|
||||
void HexagonMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
MCSubtargetInfo const &STI) const {
|
||||
const MCSubtargetInfo &STI) const {
|
||||
MCInst &HMB = const_cast<MCInst &>(MI);
|
||||
|
||||
assert(HexagonMCInstrInfo::isBundle(HMB));
|
||||
|
@ -137,60 +138,7 @@ void HexagonMCCodeEmitter::EncodeSingleInstruction(
|
|||
MI.getOpcode() <= Hexagon::DuplexIClassF) {
|
||||
assert(Parse == HexagonII::INST_PARSE_DUPLEX &&
|
||||
"Emitting duplex without duplex parse bits");
|
||||
unsigned dupIClass;
|
||||
switch (MI.getOpcode()) {
|
||||
case Hexagon::DuplexIClass0:
|
||||
dupIClass = 0;
|
||||
break;
|
||||
case Hexagon::DuplexIClass1:
|
||||
dupIClass = 1;
|
||||
break;
|
||||
case Hexagon::DuplexIClass2:
|
||||
dupIClass = 2;
|
||||
break;
|
||||
case Hexagon::DuplexIClass3:
|
||||
dupIClass = 3;
|
||||
break;
|
||||
case Hexagon::DuplexIClass4:
|
||||
dupIClass = 4;
|
||||
break;
|
||||
case Hexagon::DuplexIClass5:
|
||||
dupIClass = 5;
|
||||
break;
|
||||
case Hexagon::DuplexIClass6:
|
||||
dupIClass = 6;
|
||||
break;
|
||||
case Hexagon::DuplexIClass7:
|
||||
dupIClass = 7;
|
||||
break;
|
||||
case Hexagon::DuplexIClass8:
|
||||
dupIClass = 8;
|
||||
break;
|
||||
case Hexagon::DuplexIClass9:
|
||||
dupIClass = 9;
|
||||
break;
|
||||
case Hexagon::DuplexIClassA:
|
||||
dupIClass = 10;
|
||||
break;
|
||||
case Hexagon::DuplexIClassB:
|
||||
dupIClass = 11;
|
||||
break;
|
||||
case Hexagon::DuplexIClassC:
|
||||
dupIClass = 12;
|
||||
break;
|
||||
case Hexagon::DuplexIClassD:
|
||||
dupIClass = 13;
|
||||
break;
|
||||
case Hexagon::DuplexIClassE:
|
||||
dupIClass = 14;
|
||||
break;
|
||||
case Hexagon::DuplexIClassF:
|
||||
dupIClass = 15;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unimplemented DuplexIClass");
|
||||
break;
|
||||
}
|
||||
unsigned dupIClass = MI.getOpcode() - Hexagon::DuplexIClass0;
|
||||
// 29 is the bit position.
|
||||
// 0b1110 =0xE bits are masked off and down shifted by 1 bit.
|
||||
// Last bit is moved to bit position 13
|
||||
|
@ -390,7 +338,8 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
|
|||
int64_t Value;
|
||||
if (ME->evaluateAsAbsolute(Value))
|
||||
return Value;
|
||||
assert(ME->getKind() == MCExpr::SymbolRef || ME->getKind() == MCExpr::Binary);
|
||||
assert(ME->getKind() == MCExpr::SymbolRef ||
|
||||
ME->getKind() == MCExpr::Binary);
|
||||
if (ME->getKind() == MCExpr::Binary) {
|
||||
MCBinaryExpr const *Binary = cast<MCBinaryExpr>(ME);
|
||||
getExprOpValue(MI, MO, Binary->getLHS(), Fixups, STI);
|
||||
|
@ -523,7 +472,7 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
|
|||
else
|
||||
if (MCID.mayStore() || MCID.mayLoad()) {
|
||||
for (const MCPhysReg *ImpUses = MCID.getImplicitUses(); *ImpUses;
|
||||
++ImpUses) {
|
||||
++ImpUses) {
|
||||
if (*ImpUses != Hexagon::GP)
|
||||
continue;
|
||||
switch (HexagonMCInstrInfo::getAccessSize(MCII, MI)) {
|
||||
|
@ -543,8 +492,7 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
|
|||
raise_relocation_error(bits, kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
} else
|
||||
raise_relocation_error(bits, kind);
|
||||
break;
|
||||
}
|
||||
|
@ -759,6 +707,13 @@ unsigned
|
|||
HexagonMCCodeEmitter::getMachineOpValue(MCInst const &MI, MCOperand const &MO,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
MCSubtargetInfo const &STI) const {
|
||||
size_t OperandNumber = ~0U;
|
||||
for (unsigned i = 0, n = MI.getNumOperands(); i < n; ++i)
|
||||
if (&MI.getOperand(i) == &MO) {
|
||||
OperandNumber = i;
|
||||
break;
|
||||
}
|
||||
assert((OperandNumber != ~0U) && "Operand not found");
|
||||
|
||||
if (HexagonMCInstrInfo::isNewValue(MCII, MI) &&
|
||||
&MO == &MI.getOperand(HexagonMCInstrInfo::getNewValueOp(MCII, MI))) {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "Hexagon.h"
|
||||
#include "MCTargetDesc/HexagonBaseInfo.h"
|
||||
#include "MCTargetDesc/HexagonMCInstrInfo.h"
|
||||
#include "MCTargetDesc/HexagonMCShuffler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
|
@ -396,7 +397,7 @@ static bool lookForCompound(MCInstrInfo const &MCII, MCContext &Context,
|
|||
/// is found update the contents fo the bundle with the compound insn.
|
||||
/// If a compound instruction is found then the bundle will have one
|
||||
/// additional slot.
|
||||
void HexagonMCInstrInfo::tryCompound(MCInstrInfo const &MCII,
|
||||
void HexagonMCInstrInfo::tryCompound(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCContext &Context, MCInst &MCI) {
|
||||
assert(HexagonMCInstrInfo::isBundle(MCI) &&
|
||||
"Non-Bundle where Bundle expected");
|
||||
|
@ -405,8 +406,23 @@ void HexagonMCInstrInfo::tryCompound(MCInstrInfo const &MCII,
|
|||
if (MCI.size() < 2)
|
||||
return;
|
||||
|
||||
bool StartedValid = llvm::HexagonMCShuffle(false, MCII, STI, MCI);
|
||||
|
||||
// Create a vector, needed to keep the order of jump instructions.
|
||||
MCInst CheckList(MCI);
|
||||
|
||||
// Look for compounds until none are found, only update the bundle when
|
||||
// a compound is found.
|
||||
while (lookForCompound(MCII, Context, MCI))
|
||||
;
|
||||
while (lookForCompound(MCII, Context, CheckList)) {
|
||||
// Keep the original bundle around in case the shuffle fails.
|
||||
MCInst OriginalBundle(MCI);
|
||||
|
||||
// Need to update the bundle.
|
||||
MCI = CheckList;
|
||||
|
||||
if (StartedValid && !llvm::HexagonMCShuffle(false, MCII, STI, MCI)) {
|
||||
DEBUG(dbgs() << "Found ERROR\n");
|
||||
MCI = OriginalBundle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "MCTargetDesc/HexagonMCInstrInfo.h"
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
|
@ -262,6 +263,7 @@ unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
|
|||
case Hexagon::EH_RETURN_JMPR:
|
||||
|
||||
case Hexagon::J2_jumpr:
|
||||
case Hexagon::PS_jmpret:
|
||||
// jumpr r31
|
||||
// Actual form JMPR %PC<imp-def>, %R31<imp-use>, %R0<imp-use,internal>.
|
||||
DstReg = MCI.getOperand(0).getReg();
|
||||
|
@ -275,6 +277,12 @@ unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
|
|||
case Hexagon::J2_jumprfnew:
|
||||
case Hexagon::J2_jumprtnewpt:
|
||||
case Hexagon::J2_jumprfnewpt:
|
||||
case Hexagon::PS_jmprett:
|
||||
case Hexagon::PS_jmpretf:
|
||||
case Hexagon::PS_jmprettnew:
|
||||
case Hexagon::PS_jmpretfnew:
|
||||
case Hexagon::PS_jmprettnewpt:
|
||||
case Hexagon::PS_jmpretfnewpt:
|
||||
DstReg = MCI.getOperand(1).getReg();
|
||||
SrcReg = MCI.getOperand(0).getReg();
|
||||
// [if ([!]p0[.new])] jumpr r31
|
||||
|
@ -284,15 +292,10 @@ unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
|
|||
}
|
||||
break;
|
||||
case Hexagon::L4_return_t:
|
||||
|
||||
case Hexagon::L4_return_f:
|
||||
|
||||
case Hexagon::L4_return_tnew_pnt:
|
||||
|
||||
case Hexagon::L4_return_fnew_pnt:
|
||||
|
||||
case Hexagon::L4_return_tnew_pt:
|
||||
|
||||
case Hexagon::L4_return_fnew_pt:
|
||||
// [if ([!]p0[.new])] dealloc_return
|
||||
SrcReg = MCI.getOperand(0).getReg();
|
||||
|
@ -565,7 +568,8 @@ bool HexagonMCInstrInfo::subInstWouldBeExtended(MCInst const &potentialDuplex) {
|
|||
bool HexagonMCInstrInfo::isOrderedDuplexPair(MCInstrInfo const &MCII,
|
||||
MCInst const &MIa, bool ExtendedA,
|
||||
MCInst const &MIb, bool ExtendedB,
|
||||
bool bisReversable) {
|
||||
bool bisReversable,
|
||||
MCSubtargetInfo const &STI) {
|
||||
// Slot 1 cannot be extended in duplexes PRM 10.5
|
||||
if (ExtendedA)
|
||||
return false;
|
||||
|
@ -625,11 +629,16 @@ bool HexagonMCInstrInfo::isOrderedDuplexPair(MCInstrInfo const &MCII,
|
|||
return false;
|
||||
}
|
||||
|
||||
// If a store appears, it must be in slot 0 (MIa) 1st, and then slot 1 (MIb);
|
||||
// therefore, not duplexable if slot 1 is a store, and slot 0 is not.
|
||||
if ((MIbG == HexagonII::HSIG_S1) || (MIbG == HexagonII::HSIG_S2)) {
|
||||
if ((MIaG != HexagonII::HSIG_S1) && (MIaG != HexagonII::HSIG_S2))
|
||||
return false;
|
||||
if (STI.getCPU().equals_lower("hexagonv4") ||
|
||||
STI.getCPU().equals_lower("hexagonv5") ||
|
||||
STI.getCPU().equals_lower("hexagonv55") ||
|
||||
STI.getCPU().equals_lower("hexagonv60")) {
|
||||
// If a store appears, it must be in slot 0 (MIa) 1st, and then slot 1 (MIb);
|
||||
// therefore, not duplexable if slot 1 is a store, and slot 0 is not.
|
||||
if ((MIbG == HexagonII::HSIG_S1) || (MIbG == HexagonII::HSIG_S2)) {
|
||||
if ((MIaG != HexagonII::HSIG_S1) && (MIaG != HexagonII::HSIG_S2))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (isDuplexPairMatch(MIaG, MIbG));
|
||||
|
@ -703,6 +712,7 @@ MCInst HexagonMCInstrInfo::deriveSubInst(MCInst const &Inst) {
|
|||
Result.setOpcode(Hexagon::SA1_dec);
|
||||
addOps(Result, Inst, 0);
|
||||
addOps(Result, Inst, 1);
|
||||
addOps(Result, Inst, 2);
|
||||
break;
|
||||
} // 1,2 SUBInst $Rd = add($Rs,#-1)
|
||||
else if (Inst.getOperand(1).getReg() == Hexagon::R29) {
|
||||
|
@ -806,20 +816,27 @@ MCInst HexagonMCInstrInfo::deriveSubInst(MCInst const &Inst) {
|
|||
break; // none SUBInst deallocframe
|
||||
case Hexagon::EH_RETURN_JMPR:
|
||||
case Hexagon::J2_jumpr:
|
||||
case Hexagon::PS_jmpret:
|
||||
Result.setOpcode(Hexagon::SL2_jumpr31);
|
||||
break; // none SUBInst jumpr r31
|
||||
case Hexagon::J2_jumprf:
|
||||
case Hexagon::PS_jmpretf:
|
||||
Result.setOpcode(Hexagon::SL2_jumpr31_f);
|
||||
break; // none SUBInst if (!p0) jumpr r31
|
||||
case Hexagon::J2_jumprfnew:
|
||||
case Hexagon::J2_jumprfnewpt:
|
||||
case Hexagon::PS_jmpretfnewpt:
|
||||
case Hexagon::PS_jmpretfnew:
|
||||
Result.setOpcode(Hexagon::SL2_jumpr31_fnew);
|
||||
break; // none SUBInst if (!p0.new) jumpr:nt r31
|
||||
case Hexagon::J2_jumprt:
|
||||
case Hexagon::PS_jmprett:
|
||||
Result.setOpcode(Hexagon::SL2_jumpr31_t);
|
||||
break; // none SUBInst if (p0) jumpr r31
|
||||
case Hexagon::J2_jumprtnew:
|
||||
case Hexagon::J2_jumprtnewpt:
|
||||
case Hexagon::PS_jmprettnewpt:
|
||||
case Hexagon::PS_jmprettnew:
|
||||
Result.setOpcode(Hexagon::SL2_jumpr31_tnew);
|
||||
break; // none SUBInst if (p0.new) jumpr:nt r31
|
||||
case Hexagon::L2_loadrb_io:
|
||||
|
@ -966,6 +983,7 @@ MCInst HexagonMCInstrInfo::deriveSubInst(MCInst const &Inst) {
|
|||
if (Absolute && Value == -1) {
|
||||
Result.setOpcode(Hexagon::SA1_setin1);
|
||||
addOps(Result, Inst, 0);
|
||||
addOps(Result, Inst, 1);
|
||||
break; // 2 1 SUBInst $Rd = #-1
|
||||
} else {
|
||||
Result.setOpcode(Hexagon::SA1_seti);
|
||||
|
@ -1005,6 +1023,7 @@ static bool isStoreInst(unsigned opCode) {
|
|||
|
||||
SmallVector<DuplexCandidate, 8>
|
||||
HexagonMCInstrInfo::getDuplexPossibilties(MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI,
|
||||
MCInst const &MCB) {
|
||||
assert(isBundle(MCB));
|
||||
SmallVector<DuplexCandidate, 8> duplexToTry;
|
||||
|
@ -1033,7 +1052,7 @@ HexagonMCInstrInfo::getDuplexPossibilties(MCInstrInfo const &MCII,
|
|||
HexagonMCInstrInfo::hasExtenderForIndex(MCB, k - 1),
|
||||
*MCB.getOperand(j).getInst(),
|
||||
HexagonMCInstrInfo::hasExtenderForIndex(MCB, j - 1),
|
||||
bisReversable)) {
|
||||
bisReversable, STI)) {
|
||||
// Get iClass.
|
||||
unsigned iClass = iClassOfDuplexPair(
|
||||
getDuplexCandidateGroup(*MCB.getOperand(k).getInst()),
|
||||
|
@ -1058,7 +1077,7 @@ HexagonMCInstrInfo::getDuplexPossibilties(MCInstrInfo const &MCII,
|
|||
HexagonMCInstrInfo::hasExtenderForIndex(MCB, j - 1),
|
||||
*MCB.getOperand(k).getInst(),
|
||||
HexagonMCInstrInfo::hasExtenderForIndex(MCB, k - 1),
|
||||
bisReversable)) {
|
||||
bisReversable, STI)) {
|
||||
// Get iClass.
|
||||
unsigned iClass = iClassOfDuplexPair(
|
||||
getDuplexCandidateGroup(*MCB.getOperand(j).getInst()),
|
||||
|
|
|
@ -37,30 +37,19 @@
|
|||
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<unsigned>
|
||||
GPSize("gpsize", cl::NotHidden,
|
||||
cl::desc("Global Pointer Addressing Size. The default size is 8."),
|
||||
cl::Prefix, cl::init(8));
|
||||
static cl::opt<unsigned> GPSize
|
||||
("gpsize", cl::NotHidden,
|
||||
cl::desc("Global Pointer Addressing Size. The default size is 8."),
|
||||
cl::Prefix,
|
||||
cl::init(8));
|
||||
|
||||
void HexagonMCELFStreamer::EmitInstruction(const MCInst &MCK,
|
||||
void HexagonMCELFStreamer::EmitInstruction(const MCInst &MCB,
|
||||
const MCSubtargetInfo &STI) {
|
||||
MCInst HMI = HexagonMCInstrInfo::createBundle();
|
||||
MCInst *MCB;
|
||||
|
||||
if (MCK.getOpcode() != Hexagon::BUNDLE) {
|
||||
HMI.addOperand(MCOperand::createInst(&MCK));
|
||||
MCB = &HMI;
|
||||
} else
|
||||
MCB = const_cast<MCInst *>(&MCK);
|
||||
|
||||
// Examines packet and pad the packet, if needed, when an
|
||||
// end-loop is in the bundle.
|
||||
HexagonMCInstrInfo::padEndloop(getContext(), *MCB);
|
||||
HexagonMCShuffle(*MCII, STI, *MCB);
|
||||
|
||||
assert(HexagonMCInstrInfo::bundleSize(*MCB) <= HEXAGON_PACKET_SIZE);
|
||||
assert(MCB.getOpcode() == Hexagon::BUNDLE);
|
||||
assert(HexagonMCInstrInfo::bundleSize(MCB) <= HEXAGON_PACKET_SIZE);
|
||||
assert(HexagonMCInstrInfo::bundleSize(MCB) > 0);
|
||||
bool Extended = false;
|
||||
for (auto &I : HexagonMCInstrInfo::bundleInstructions(*MCB)) {
|
||||
for (auto &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
MCInst *MCI = const_cast<MCInst *>(I.getInst());
|
||||
if (Extended) {
|
||||
if (HexagonMCInstrInfo::isDuplex(*MCII, *MCI)) {
|
||||
|
@ -77,11 +66,12 @@ void HexagonMCELFStreamer::EmitInstruction(const MCInst &MCK,
|
|||
|
||||
// At this point, MCB is a bundle
|
||||
// Iterate through the bundle and assign addends for the instructions
|
||||
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(*MCB)) {
|
||||
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
MCInst *MCI = const_cast<MCInst *>(I.getInst());
|
||||
EmitSymbol(*MCI);
|
||||
}
|
||||
MCObjectStreamer::EmitInstruction(*MCB, STI);
|
||||
|
||||
MCObjectStreamer::EmitInstruction(MCB, STI);
|
||||
}
|
||||
|
||||
void HexagonMCELFStreamer::EmitSymbol(const MCInst &Inst) {
|
||||
|
@ -119,9 +109,11 @@ void HexagonMCELFStreamer::HexagonMCEmitCommonSymbol(MCSymbol *Symbol,
|
|||
MCSectionSubPair P = getCurrentSection();
|
||||
SwitchSection(&Section);
|
||||
|
||||
EmitValueToAlignment(ByteAlignment, 0, 1, 0);
|
||||
EmitLabel(Symbol);
|
||||
EmitZeros(Size);
|
||||
if (ELFSymbol->isUndefined(false)) {
|
||||
EmitValueToAlignment(ByteAlignment, 0, 1, 0);
|
||||
EmitLabel(Symbol);
|
||||
EmitZeros(Size);
|
||||
}
|
||||
|
||||
// Update the maximum alignment of the section if necessary.
|
||||
if (ByteAlignment > Section.getAlignment())
|
||||
|
@ -144,9 +136,10 @@ void HexagonMCELFStreamer::HexagonMCEmitCommonSymbol(MCSymbol *Symbol,
|
|||
ELFSymbol->setSize(MCConstantExpr::create(Size, getContext()));
|
||||
}
|
||||
|
||||
void HexagonMCELFStreamer::HexagonMCEmitLocalCommonSymbol(
|
||||
MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment,
|
||||
unsigned AccessSize) {
|
||||
void HexagonMCELFStreamer::HexagonMCEmitLocalCommonSymbol(MCSymbol *Symbol,
|
||||
uint64_t Size,
|
||||
unsigned ByteAlignment,
|
||||
unsigned AccessSize) {
|
||||
getAssembler().registerSymbol(*Symbol);
|
||||
auto ELFSymbol = cast<MCSymbolELF>(Symbol);
|
||||
ELFSymbol->setBinding(ELF::STB_LOCAL);
|
||||
|
@ -154,11 +147,12 @@ void HexagonMCELFStreamer::HexagonMCEmitLocalCommonSymbol(
|
|||
HexagonMCEmitCommonSymbol(Symbol, Size, ByteAlignment, AccessSize);
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
MCStreamer *createHexagonELFStreamer(MCContext &Context, MCAsmBackend &MAB,
|
||||
raw_pwrite_stream &OS, MCCodeEmitter *CE) {
|
||||
return new HexagonMCELFStreamer(Context, MAB, OS, CE);
|
||||
}
|
||||
namespace llvm {
|
||||
MCStreamer *createHexagonELFStreamer(Triple const &TT, MCContext &Context,
|
||||
MCAsmBackend &MAB,
|
||||
raw_pwrite_stream &OS, MCCodeEmitter *CE) {
|
||||
return new HexagonMCELFStreamer(Context, MAB, OS, CE);
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
|
|
@ -27,6 +27,13 @@ public:
|
|||
: MCELFStreamer(Context, TAB, OS, Emitter),
|
||||
MCII(createHexagonMCInstrInfo()) {}
|
||||
|
||||
HexagonMCELFStreamer(MCContext &Context,
|
||||
MCAsmBackend &TAB,
|
||||
raw_pwrite_stream &OS, MCCodeEmitter *Emitter,
|
||||
MCAssembler *Assembler) :
|
||||
MCELFStreamer(Context, TAB, OS, Emitter),
|
||||
MCII (createHexagonMCInstrInfo()) {}
|
||||
|
||||
void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
|
||||
void EmitSymbol(const MCInst &Inst);
|
||||
void HexagonMCEmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||
|
@ -36,8 +43,9 @@ public:
|
|||
unsigned ByteAlignment, unsigned AccessSize);
|
||||
};
|
||||
|
||||
MCStreamer *createHexagonELFStreamer(MCContext &Context, MCAsmBackend &MAB,
|
||||
raw_pwrite_stream &OS, MCCodeEmitter *CE);
|
||||
MCStreamer *createHexagonELFStreamer(Triple const &TT, MCContext &Context,
|
||||
MCAsmBackend &MAB, raw_pwrite_stream &OS,
|
||||
MCCodeEmitter *CE);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
#include "HexagonMCExpr.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSymbolELF.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
@ -36,7 +38,47 @@ MCFragment *llvm::HexagonMCExpr::findAssociatedFragment() const {
|
|||
return Expr->findAssociatedFragment();
|
||||
}
|
||||
|
||||
void HexagonMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {}
|
||||
static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
|
||||
switch (Expr->getKind()) {
|
||||
case MCExpr::Target:
|
||||
llvm_unreachable("Cannot handle nested target MCExpr");
|
||||
break;
|
||||
case MCExpr::Constant:
|
||||
break;
|
||||
|
||||
case MCExpr::Binary: {
|
||||
const MCBinaryExpr *be = cast<MCBinaryExpr>(Expr);
|
||||
fixELFSymbolsInTLSFixupsImpl(be->getLHS(), Asm);
|
||||
fixELFSymbolsInTLSFixupsImpl(be->getRHS(), Asm);
|
||||
break;
|
||||
}
|
||||
case MCExpr::SymbolRef: {
|
||||
const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(Expr);
|
||||
switch (symRef.getKind()) {
|
||||
default:
|
||||
return;
|
||||
case MCSymbolRefExpr::VK_Hexagon_GD_GOT:
|
||||
case MCSymbolRefExpr::VK_Hexagon_LD_GOT:
|
||||
case MCSymbolRefExpr::VK_Hexagon_GD_PLT:
|
||||
case MCSymbolRefExpr::VK_Hexagon_LD_PLT:
|
||||
case MCSymbolRefExpr::VK_Hexagon_IE:
|
||||
case MCSymbolRefExpr::VK_Hexagon_IE_GOT:
|
||||
case MCSymbolRefExpr::VK_TPREL:
|
||||
break;
|
||||
}
|
||||
cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);
|
||||
break;
|
||||
}
|
||||
case MCExpr::Unary:
|
||||
fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HexagonMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
|
||||
auto expr = getExpr();
|
||||
fixELFSymbolsInTLSFixupsImpl(expr, Asm);
|
||||
}
|
||||
|
||||
MCExpr const *HexagonMCExpr::getExpr() const { return Expr; }
|
||||
|
||||
|
@ -75,4 +117,4 @@ void HexagonMCExpr::setSignMismatch(bool Val) {
|
|||
|
||||
bool HexagonMCExpr::signMismatch() const {
|
||||
return SignMismatch;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,9 @@
|
|||
#include "Hexagon.h"
|
||||
#include "HexagonBaseInfo.h"
|
||||
#include "HexagonMCChecker.h"
|
||||
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCInstrItineraries.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
@ -59,31 +58,36 @@ bool HexagonMCInstrInfo::canonicalizePacket(MCInstrInfo const &MCII,
|
|||
MCSubtargetInfo const &STI,
|
||||
MCContext &Context, MCInst &MCB,
|
||||
HexagonMCChecker *Check) {
|
||||
// Check the bundle for errors.
|
||||
bool CheckOk = Check ? Check->check(false) : true;
|
||||
if (!CheckOk)
|
||||
return false;
|
||||
// Examine the packet and convert pairs of instructions to compound
|
||||
// instructions when possible.
|
||||
if (!HexagonDisableCompound)
|
||||
HexagonMCInstrInfo::tryCompound(MCII, Context, MCB);
|
||||
// Check the bundle for errors.
|
||||
bool CheckOk = Check ? Check->check() : true;
|
||||
if (!CheckOk)
|
||||
return false;
|
||||
HexagonMCShuffle(MCII, STI, MCB);
|
||||
HexagonMCInstrInfo::tryCompound(MCII, STI, Context, MCB);
|
||||
HexagonMCShuffle(false, MCII, STI, MCB);
|
||||
// Examine the packet and convert pairs of instructions to duplex
|
||||
// instructions when possible.
|
||||
MCInst InstBundlePreDuplex = MCInst(MCB);
|
||||
if (!HexagonDisableDuplex) {
|
||||
SmallVector<DuplexCandidate, 8> possibleDuplexes;
|
||||
possibleDuplexes = HexagonMCInstrInfo::getDuplexPossibilties(MCII, MCB);
|
||||
possibleDuplexes =
|
||||
HexagonMCInstrInfo::getDuplexPossibilties(MCII, STI, MCB);
|
||||
HexagonMCShuffle(MCII, STI, Context, MCB, possibleDuplexes);
|
||||
}
|
||||
// Examines packet and pad the packet, if needed, when an
|
||||
// end-loop is in the bundle.
|
||||
HexagonMCInstrInfo::padEndloop(Context, MCB);
|
||||
HexagonMCInstrInfo::padEndloop(MCB);
|
||||
// If compounding and duplexing didn't reduce the size below
|
||||
// 4 or less we have a packet that is too big.
|
||||
if (HexagonMCInstrInfo::bundleSize(MCB) > HEXAGON_PACKET_SIZE)
|
||||
return false;
|
||||
HexagonMCShuffle(MCII, STI, MCB);
|
||||
// Check the bundle for errors.
|
||||
CheckOk = Check ? Check->check(true) : true;
|
||||
if (!CheckOk)
|
||||
return false;
|
||||
HexagonMCShuffle(true, MCII, STI, MCB);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -111,20 +115,6 @@ MCInst HexagonMCInstrInfo::createBundle() {
|
|||
return Result;
|
||||
}
|
||||
|
||||
MCInst *HexagonMCInstrInfo::deriveDuplex(MCContext &Context, unsigned iClass,
|
||||
MCInst const &inst0,
|
||||
MCInst const &inst1) {
|
||||
assert((iClass <= 0xf) && "iClass must have range of 0 to 0xf");
|
||||
MCInst *duplexInst = new (Context) MCInst;
|
||||
duplexInst->setOpcode(Hexagon::DuplexIClass0 + iClass);
|
||||
|
||||
MCInst *SubInst0 = new (Context) MCInst(deriveSubInst(inst0));
|
||||
MCInst *SubInst1 = new (Context) MCInst(deriveSubInst(inst1));
|
||||
duplexInst->addOperand(MCOperand::createInst(SubInst0));
|
||||
duplexInst->addOperand(MCOperand::createInst(SubInst1));
|
||||
return duplexInst;
|
||||
}
|
||||
|
||||
MCInst HexagonMCInstrInfo::deriveExtender(MCInstrInfo const &MCII,
|
||||
MCInst const &Inst,
|
||||
MCOperand const &MO) {
|
||||
|
@ -142,6 +132,20 @@ MCInst HexagonMCInstrInfo::deriveExtender(MCInstrInfo const &MCII,
|
|||
return XMI;
|
||||
}
|
||||
|
||||
MCInst *HexagonMCInstrInfo::deriveDuplex(MCContext &Context, unsigned iClass,
|
||||
MCInst const &inst0,
|
||||
MCInst const &inst1) {
|
||||
assert((iClass <= 0xf) && "iClass must have range of 0 to 0xf");
|
||||
MCInst *duplexInst = new (Context) MCInst;
|
||||
duplexInst->setOpcode(Hexagon::DuplexIClass0 + iClass);
|
||||
|
||||
MCInst *SubInst0 = new (Context) MCInst(deriveSubInst(inst0));
|
||||
MCInst *SubInst1 = new (Context) MCInst(deriveSubInst(inst1));
|
||||
duplexInst->addOperand(MCOperand::createInst(SubInst0));
|
||||
duplexInst->addOperand(MCOperand::createInst(SubInst1));
|
||||
return duplexInst;
|
||||
}
|
||||
|
||||
MCInst const *HexagonMCInstrInfo::extenderForIndex(MCInst const &MCB,
|
||||
size_t Index) {
|
||||
assert(Index <= bundleSize(MCB));
|
||||
|
@ -169,22 +173,9 @@ HexagonMCInstrInfo::getAccessSize(MCInstrInfo const &MCII, MCInst const &MCI) {
|
|||
HexagonII::MemAccesSizeMask));
|
||||
}
|
||||
|
||||
unsigned HexagonMCInstrInfo::getBitCount(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask);
|
||||
}
|
||||
|
||||
// Return constant extended operand number.
|
||||
unsigned short HexagonMCInstrInfo::getCExtOpNum(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask);
|
||||
}
|
||||
|
||||
MCInstrDesc const &HexagonMCInstrInfo::getDesc(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
return (MCII.get(MCI.getOpcode()));
|
||||
return MCII.get(MCI.getOpcode());
|
||||
}
|
||||
|
||||
unsigned HexagonMCInstrInfo::getDuplexRegisterNumbering(unsigned Reg) {
|
||||
|
@ -272,32 +263,32 @@ unsigned HexagonMCInstrInfo::getExtentBits(MCInstrInfo const &MCII,
|
|||
return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask);
|
||||
}
|
||||
|
||||
// Return the max value that a constant extendable operand can have
|
||||
// without being extended.
|
||||
/// Return the maximum value of an extendable operand.
|
||||
int HexagonMCInstrInfo::getMaxValue(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
unsigned isSigned =
|
||||
(F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
|
||||
unsigned bits = (F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask;
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
bool S = (F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
|
||||
|
||||
if (isSigned) // if value is signed
|
||||
return ~(-1U << (bits - 1));
|
||||
assert(HexagonMCInstrInfo::isExtendable(MCII, MCI) ||
|
||||
HexagonMCInstrInfo::isExtended(MCII, MCI));
|
||||
|
||||
if (S) // if value is signed
|
||||
return ~(-1 << (HexagonMCInstrInfo::getExtentBits(MCII, MCI) - 1));
|
||||
else
|
||||
return ~(-1U << bits);
|
||||
return ~(-1 << HexagonMCInstrInfo::getExtentBits(MCII, MCI));
|
||||
}
|
||||
|
||||
// Return the min value that a constant extendable operand can have
|
||||
// without being extended.
|
||||
/// Return the minimum value of an extendable operand.
|
||||
int HexagonMCInstrInfo::getMinValue(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
unsigned isSigned =
|
||||
(F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
|
||||
unsigned bits = (F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask;
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
bool S = (F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask;
|
||||
|
||||
if (isSigned) // if value is signed
|
||||
return -1U << (bits - 1);
|
||||
assert(HexagonMCInstrInfo::isExtendable(MCII, MCI) ||
|
||||
HexagonMCInstrInfo::isExtended(MCII, MCI));
|
||||
|
||||
if (S) // if value is signed
|
||||
return -1 << (HexagonMCInstrInfo::getExtentBits(MCII, MCI) - 1);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -315,9 +306,7 @@ unsigned short HexagonMCInstrInfo::getNewValueOp(MCInstrInfo const &MCII,
|
|||
|
||||
MCOperand const &HexagonMCInstrInfo::getNewValueOperand(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
unsigned const O =
|
||||
(F >> HexagonII::NewValueOpPos) & HexagonII::NewValueOpMask;
|
||||
unsigned O = HexagonMCInstrInfo::getNewValueOp(MCII, MCI);
|
||||
MCOperand const &MCO = MCI.getOperand(O);
|
||||
|
||||
assert((HexagonMCInstrInfo::isNewValue(MCII, MCI) ||
|
||||
|
@ -345,6 +334,13 @@ HexagonMCInstrInfo::getNewValueOperand2(MCInstrInfo const &MCII,
|
|||
return (MCO);
|
||||
}
|
||||
|
||||
/// Return the Hexagon ISA class for the insn.
|
||||
unsigned HexagonMCInstrInfo::getType(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
const uint64_t F = MCII.get(MCI.getOpcode()).TSFlags;
|
||||
return ((F >> HexagonII::TypePos) & HexagonII::TypeMask);
|
||||
}
|
||||
|
||||
int HexagonMCInstrInfo::getSubTarget(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
|
@ -357,17 +353,14 @@ int HexagonMCInstrInfo::getSubTarget(MCInstrInfo const &MCII,
|
|||
return Hexagon::ArchV4;
|
||||
case HexagonII::HasV5SubT:
|
||||
return Hexagon::ArchV5;
|
||||
case HexagonII::HasV55SubT:
|
||||
return Hexagon::ArchV55;
|
||||
case HexagonII::HasV60SubT:
|
||||
return Hexagon::ArchV60;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the Hexagon ISA class for the insn.
|
||||
unsigned HexagonMCInstrInfo::getType(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
|
||||
return ((F >> HexagonII::TypePos) & HexagonII::TypeMask);
|
||||
}
|
||||
|
||||
/// Return the slots this instruction can execute out of
|
||||
unsigned HexagonMCInstrInfo::getUnits(MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI,
|
||||
MCInst const &MCI) {
|
||||
|
@ -377,6 +370,49 @@ unsigned HexagonMCInstrInfo::getUnits(MCInstrInfo const &MCII,
|
|||
return ((II[SchedClass].FirstStage + HexagonStages)->getUnits());
|
||||
}
|
||||
|
||||
/// Return the slots this instruction consumes in addition to
|
||||
/// the slot(s) it can execute out of
|
||||
|
||||
unsigned HexagonMCInstrInfo::getOtherReservedSlots(MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI,
|
||||
MCInst const &MCI) {
|
||||
const InstrItinerary *II = STI.getSchedModel().InstrItineraries;
|
||||
int SchedClass = HexagonMCInstrInfo::getDesc(MCII, MCI).getSchedClass();
|
||||
unsigned Slots = 0;
|
||||
|
||||
// FirstStage are slots that this instruction can execute in.
|
||||
// FirstStage+1 are slots that are also consumed by this instruction.
|
||||
// For example: vmemu can only execute in slot 0 but also consumes slot 1.
|
||||
for (unsigned Stage = II[SchedClass].FirstStage + 1;
|
||||
Stage < II[SchedClass].LastStage; ++Stage) {
|
||||
unsigned Units = (Stage + HexagonStages)->getUnits();
|
||||
if (Units > HexagonGetLastSlot())
|
||||
break;
|
||||
// fyi: getUnits() will return 0x1, 0x2, 0x4 or 0x8
|
||||
Slots |= Units;
|
||||
}
|
||||
|
||||
// if 0 is returned, then no additional slots are consumed by this inst.
|
||||
return Slots;
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::hasDuplex(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
if (!HexagonMCInstrInfo::isBundle(MCI))
|
||||
return false;
|
||||
|
||||
for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCI)) {
|
||||
auto MI = I.getInst();
|
||||
if (HexagonMCInstrInfo::isDuplex(MCII, *MI))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::hasExtenderForIndex(MCInst const &MCB, size_t Index) {
|
||||
return extenderForIndex(MCB, Index) != nullptr;
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::hasImmExt(MCInst const &MCI) {
|
||||
if (!HexagonMCInstrInfo::isBundle(MCI))
|
||||
return false;
|
||||
|
@ -390,11 +426,7 @@ bool HexagonMCInstrInfo::hasImmExt(MCInst const &MCI) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::hasExtenderForIndex(MCInst const &MCB, size_t Index) {
|
||||
return extenderForIndex(MCB, Index) != nullptr;
|
||||
}
|
||||
|
||||
// Return whether the instruction is a legal new-value producer.
|
||||
/// Return whether the insn produces a value.
|
||||
bool HexagonMCInstrInfo::hasNewValue(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
|
@ -414,46 +446,19 @@ MCInst const &HexagonMCInstrInfo::instruction(MCInst const &MCB, size_t Index) {
|
|||
return *MCB.getOperand(bundleInstructionsOffset + Index).getInst();
|
||||
}
|
||||
|
||||
/// Return where the instruction is an accumulator.
|
||||
bool HexagonMCInstrInfo::isAccumulator(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
return ((F >> HexagonII::AccumulatorPos) & HexagonII::AccumulatorMask);
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isBundle(MCInst const &MCI) {
|
||||
auto Result = Hexagon::BUNDLE == MCI.getOpcode();
|
||||
assert(!Result || (MCI.size() > 0 && MCI.getOperand(0).isImm()));
|
||||
return Result;
|
||||
}
|
||||
|
||||
// Return whether the insn is an actual insn.
|
||||
bool HexagonMCInstrInfo::isCanon(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
return (!HexagonMCInstrInfo::getDesc(MCII, MCI).isPseudo() &&
|
||||
!HexagonMCInstrInfo::isPrefix(MCII, MCI) &&
|
||||
HexagonMCInstrInfo::getType(MCII, MCI) != HexagonII::TypeENDLOOP);
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
return ((F >> HexagonII::CofMax1Pos) & HexagonII::CofMax1Mask);
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isCompound(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
return getType(MCII, MCI) == HexagonII::TypeCJ;
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isDblRegForSubInst(unsigned Reg) {
|
||||
return ((Reg >= Hexagon::D0 && Reg <= Hexagon::D3) ||
|
||||
(Reg >= Hexagon::D8 && Reg <= Hexagon::D11));
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isDuplex(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
return HexagonII::TypeDUPLEX == HexagonMCInstrInfo::getType(MCII, MCI);
|
||||
}
|
||||
|
||||
// Return whether the instruction needs to be constant extended.
|
||||
// 1) Always return true if the instruction has 'isExtended' flag set.
|
||||
//
|
||||
// isExtendable:
|
||||
// 2) For immediate extended operands, return true only if the value is
|
||||
// out-of-range.
|
||||
// 3) For global address, always return true.
|
||||
|
||||
bool HexagonMCInstrInfo::isConstExtended(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
if (HexagonMCInstrInfo::isExtended(MCII, MCI))
|
||||
|
@ -468,7 +473,7 @@ bool HexagonMCInstrInfo::isConstExtended(MCInstrInfo const &MCII,
|
|||
if ((HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeJ) ||
|
||||
(HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCJ &&
|
||||
HexagonMCInstrInfo::getDesc(MCII, MCI).isBranch()) ||
|
||||
(HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNV &&
|
||||
(HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNCJ &&
|
||||
HexagonMCInstrInfo::getDesc(MCII, MCI).isBranch()))
|
||||
return false;
|
||||
// Otherwise loop instructions and other CR insts are handled by relaxation
|
||||
|
@ -488,6 +493,30 @@ bool HexagonMCInstrInfo::isConstExtended(MCInstrInfo const &MCII,
|
|||
return (MinValue > Value || Value > MaxValue);
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isCanon(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
return !HexagonMCInstrInfo::getDesc(MCII, MCI).isPseudo() &&
|
||||
!HexagonMCInstrInfo::isPrefix(MCII, MCI);
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
return ((F >> HexagonII::CofMax1Pos) & HexagonII::CofMax1Mask);
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isCompound(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
return (getType(MCII, MCI) == HexagonII::TypeCJ);
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isDblRegForSubInst(unsigned Reg) {
|
||||
return ((Reg >= Hexagon::D0 && Reg <= Hexagon::D3) ||
|
||||
(Reg >= Hexagon::D8 && Reg <= Hexagon::D11));
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isDuplex(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
return HexagonII::TypeDUPLEX == HexagonMCInstrInfo::getType(MCII, MCI);
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isExtendable(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
|
@ -524,20 +553,17 @@ bool HexagonMCInstrInfo::isIntRegForSubInst(unsigned Reg) {
|
|||
(Reg >= Hexagon::R16 && Reg <= Hexagon::R23));
|
||||
}
|
||||
|
||||
// Return whether the insn is a new-value consumer.
|
||||
/// Return whether the insn expects newly produced value.
|
||||
bool HexagonMCInstrInfo::isNewValue(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask);
|
||||
}
|
||||
|
||||
// Return whether the operand can be constant extended.
|
||||
bool HexagonMCInstrInfo::isOperandExtended(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI,
|
||||
unsigned short OperandNum) {
|
||||
uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask) ==
|
||||
OperandNum;
|
||||
/// Return whether the operand is extendable.
|
||||
bool HexagonMCInstrInfo::isOpExtendable(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI, unsigned short O) {
|
||||
return (O == HexagonMCInstrInfo::getExtendableOp(MCII, MCI));
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isOuterLoop(MCInst const &MCI) {
|
||||
|
@ -580,8 +606,22 @@ bool HexagonMCInstrInfo::isPredReg(unsigned Reg) {
|
|||
return (Reg >= Hexagon::P0 && Reg <= Hexagon::P3_0);
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isSolo(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
/// Return whether the insn can be packaged only with A and X-type insns.
|
||||
bool HexagonMCInstrInfo::isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
return ((F >> HexagonII::SoloAXPos) & HexagonII::SoloAXMask);
|
||||
}
|
||||
|
||||
/// Return whether the insn can be packaged only with an A-type insn in slot #1.
|
||||
bool HexagonMCInstrInfo::isSoloAin1(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
return ((F >> HexagonII::SoloAin1Pos) & HexagonII::SoloAin1Mask);
|
||||
}
|
||||
|
||||
/// Return whether the insn is solo, i.e., cannot be in a packet.
|
||||
bool HexagonMCInstrInfo::isSolo(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
const uint64_t F = MCII.get(MCI.getOpcode()).TSFlags;
|
||||
return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask);
|
||||
}
|
||||
|
||||
|
@ -657,17 +697,6 @@ bool HexagonMCInstrInfo::isSubInstruction(MCInst const &MCI) {
|
|||
}
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
return ((F >> HexagonII::SoloAXPos) & HexagonII::SoloAXMask);
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isSoloAin1(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI) {
|
||||
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
|
||||
return ((F >> HexagonII::SoloAin1Pos) & HexagonII::SoloAin1Mask);
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::isVector(MCInstrInfo const &MCII, MCInst const &MCI) {
|
||||
if ((getType(MCII, MCI) <= HexagonII::TypeCVI_LAST) &&
|
||||
(getType(MCII, MCI) >= HexagonII::TypeCVI_FIRST))
|
||||
|
@ -699,8 +728,7 @@ bool HexagonMCInstrInfo::mustExtend(MCExpr const &Expr) {
|
|||
return HExpr.mustExtend();
|
||||
}
|
||||
void HexagonMCInstrInfo::setMustNotExtend(MCExpr const &Expr, bool Val) {
|
||||
HexagonMCExpr &HExpr =
|
||||
const_cast<HexagonMCExpr &>(cast<HexagonMCExpr>(Expr));
|
||||
HexagonMCExpr &HExpr = const_cast<HexagonMCExpr &>(cast<HexagonMCExpr>(Expr));
|
||||
HExpr.setMustNotExtend(Val);
|
||||
}
|
||||
bool HexagonMCInstrInfo::mustNotExtend(MCExpr const &Expr) {
|
||||
|
@ -719,7 +747,7 @@ bool HexagonMCInstrInfo::s23_2_reloc(MCExpr const &Expr) {
|
|||
return HExpr->s23_2_reloc();
|
||||
}
|
||||
|
||||
void HexagonMCInstrInfo::padEndloop(MCContext &Context, MCInst &MCB) {
|
||||
void HexagonMCInstrInfo::padEndloop(MCInst &MCB) {
|
||||
MCInst Nop;
|
||||
Nop.setOpcode(Hexagon::A2_nop);
|
||||
assert(isBundle(MCB));
|
||||
|
@ -727,7 +755,7 @@ void HexagonMCInstrInfo::padEndloop(MCContext &Context, MCInst &MCB) {
|
|||
(HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_INNER_SIZE)) ||
|
||||
((HexagonMCInstrInfo::isOuterLoop(MCB) &&
|
||||
(HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_OUTER_SIZE))))
|
||||
MCB.addOperand(MCOperand::createInst(new (Context) MCInst(Nop)));
|
||||
MCB.addOperand(MCOperand::createInst(new MCInst(Nop)));
|
||||
}
|
||||
|
||||
bool HexagonMCInstrInfo::prefersSlot3(MCInstrInfo const &MCII,
|
||||
|
|
|
@ -19,11 +19,8 @@
|
|||
|
||||
namespace llvm {
|
||||
class HexagonMCChecker;
|
||||
class MCContext;
|
||||
class MCInstrDesc;
|
||||
class MCInstrInfo;
|
||||
class MCInst;
|
||||
class MCOperand;
|
||||
class MCSubtargetInfo;
|
||||
namespace HexagonII {
|
||||
enum class MemAccessSize;
|
||||
|
@ -67,6 +64,15 @@ bool canonicalizePacket(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
|||
MCContext &Context, MCInst &MCB,
|
||||
HexagonMCChecker *Checker);
|
||||
|
||||
// Create a duplex instruction given the two subinsts
|
||||
MCInst *deriveDuplex(MCContext &Context, unsigned iClass, MCInst const &inst0,
|
||||
MCInst const &inst1);
|
||||
MCInst deriveExtender(MCInstrInfo const &MCII, MCInst const &Inst,
|
||||
MCOperand const &MO);
|
||||
|
||||
// Convert this instruction in to a duplex subinst
|
||||
MCInst deriveSubInst(MCInst const &Inst);
|
||||
|
||||
// Clamp off upper 26 bits of extendable operand for emission
|
||||
void clampExtended(MCInstrInfo const &MCII, MCContext &Context, MCInst &MCI);
|
||||
|
||||
|
@ -77,36 +83,18 @@ MCInst const *extenderForIndex(MCInst const &MCB, size_t Index);
|
|||
void extendIfNeeded(MCContext &Context, MCInstrInfo const &MCII, MCInst &MCB,
|
||||
MCInst const &MCI);
|
||||
|
||||
// Create a duplex instruction given the two subinsts
|
||||
MCInst *deriveDuplex(MCContext &Context, unsigned iClass, MCInst const &inst0,
|
||||
MCInst const &inst1);
|
||||
MCInst deriveExtender(MCInstrInfo const &MCII, MCInst const &Inst,
|
||||
MCOperand const &MO);
|
||||
|
||||
// Convert this instruction in to a duplex subinst
|
||||
MCInst deriveSubInst(MCInst const &Inst);
|
||||
|
||||
// Return the extender for instruction at Index or nullptr if none
|
||||
MCInst const *extenderForIndex(MCInst const &MCB, size_t Index);
|
||||
|
||||
// Return memory access size
|
||||
HexagonII::MemAccessSize getAccessSize(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI);
|
||||
|
||||
// Return number of bits in the constant extended operand.
|
||||
unsigned getBitCount(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
|
||||
// Return constant extended operand number.
|
||||
unsigned short getCExtOpNum(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
|
||||
MCInstrDesc const &getDesc(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
|
||||
// Return which duplex group this instruction belongs to
|
||||
unsigned getDuplexCandidateGroup(MCInst const &MI);
|
||||
|
||||
// Return a list of all possible instruction duplex combinations
|
||||
SmallVector<DuplexCandidate, 8> getDuplexPossibilties(MCInstrInfo const &MCII,
|
||||
MCInst const &MCB);
|
||||
SmallVector<DuplexCandidate, 8>
|
||||
getDuplexPossibilties(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCInst const &MCB);
|
||||
unsigned getDuplexRegisterNumbering(unsigned Reg);
|
||||
|
||||
MCExpr const &getExpr(MCExpr const &Expr);
|
||||
|
@ -143,7 +131,6 @@ MCOperand const &getNewValueOperand(MCInstrInfo const &MCII, MCInst const &MCI);
|
|||
unsigned short getNewValueOp2(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
MCOperand const &getNewValueOperand2(MCInstrInfo const &MCII,
|
||||
MCInst const &MCI);
|
||||
|
||||
int getSubTarget(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
|
||||
// Return the Hexagon ISA class for the insn.
|
||||
|
@ -152,6 +139,9 @@ unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI);
|
|||
/// Return the slots used by the insn.
|
||||
unsigned getUnits(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCInst const &MCI);
|
||||
unsigned getOtherReservedSlots(MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst const &MCI);
|
||||
bool hasDuplex(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
|
||||
// Does the packet have an extender for the instruction at Index
|
||||
bool hasExtenderForIndex(MCInst const &MCB, size_t Index);
|
||||
|
@ -161,19 +151,6 @@ bool hasImmExt(MCInst const &MCI);
|
|||
// Return whether the instruction is a legal new-value producer.
|
||||
bool hasNewValue(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
bool hasNewValue2(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
|
||||
// Return the instruction at Index
|
||||
MCInst const &instruction(MCInst const &MCB, size_t Index);
|
||||
|
||||
// Returns whether this MCInst is a wellformed bundle
|
||||
bool isBundle(MCInst const &MCI);
|
||||
|
||||
// Return whether the insn is an actual insn.
|
||||
bool isCanon(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
bool isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
bool isCompound(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
|
||||
// Return the duplex iclass given the two duplex classes
|
||||
unsigned iClassOfDuplexPair(unsigned Ga, unsigned Gb);
|
||||
|
||||
int64_t minConstant(MCInst const &MCI, size_t Index);
|
||||
|
@ -189,6 +166,18 @@ template <unsigned N> bool inRange(MCInst const &MCI, size_t Index) {
|
|||
return isUInt<N>(minConstant(MCI, Index));
|
||||
}
|
||||
|
||||
// Return the instruction at Index
|
||||
MCInst const &instruction(MCInst const &MCB, size_t Index);
|
||||
bool isAccumulator(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
|
||||
// Returns whether this MCInst is a wellformed bundle
|
||||
bool isBundle(MCInst const &MCI);
|
||||
|
||||
// Return whether the insn is an actual insn.
|
||||
bool isCanon(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
bool isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
bool isCompound(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
|
||||
// Return whether the instruction needs to be constant extended.
|
||||
bool isConstExtended(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
|
||||
|
@ -229,15 +218,12 @@ bool isMemStoreReorderEnabled(MCInst const &MCI);
|
|||
|
||||
// Return whether the insn is a new-value consumer.
|
||||
bool isNewValue(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
|
||||
// Return true if the operand can be constant extended.
|
||||
bool isOperandExtended(MCInstrInfo const &MCII, MCInst const &MCI,
|
||||
unsigned short OperandNum);
|
||||
bool isOpExtendable(MCInstrInfo const &MCII, MCInst const &MCI, unsigned short);
|
||||
|
||||
// Can these two instructions be duplexed
|
||||
bool isOrderedDuplexPair(MCInstrInfo const &MCII, MCInst const &MIa,
|
||||
bool ExtendedA, MCInst const &MIb, bool ExtendedB,
|
||||
bool bisReversable);
|
||||
bool bisReversable, MCSubtargetInfo const &STI);
|
||||
|
||||
// Returns whether this bundle is an endloop1
|
||||
bool isOuterLoop(MCInst const &MCI);
|
||||
|
@ -270,12 +256,11 @@ bool mustExtend(MCExpr const &Expr);
|
|||
bool mustNotExtend(MCExpr const &Expr);
|
||||
|
||||
// Pad the bundle with nops to satisfy endloop requirements
|
||||
void padEndloop(MCContext &Context, MCInst &MCI);
|
||||
|
||||
void padEndloop(MCInst &MCI);
|
||||
bool prefersSlot3(MCInstrInfo const &MCII, MCInst const &MCI);
|
||||
|
||||
// Replace the instructions inside MCB, represented by Candidate
|
||||
void replaceDuplex(MCContext &Context, MCInst &MCB, DuplexCandidate Candidate);
|
||||
void replaceDuplex(MCContext &Context, MCInst &MCI, DuplexCandidate Candidate);
|
||||
|
||||
bool s23_2_reloc(MCExpr const &Expr);
|
||||
// Marks a bundle as endloop0
|
||||
|
@ -295,7 +280,8 @@ unsigned SubregisterBit(unsigned Consumer, unsigned Producer,
|
|||
unsigned Producer2);
|
||||
|
||||
// Attempt to find and replace compound pairs
|
||||
void tryCompound(MCInstrInfo const &MCII, MCContext &Context, MCInst &MCI);
|
||||
void tryCompound(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCContext &Context, MCInst &MCI);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,42 +33,39 @@ void HexagonMCShuffler::init(MCInst &MCB) {
|
|||
MCInst const *Extender = nullptr;
|
||||
// Copy the bundle for the shuffling.
|
||||
for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo());
|
||||
MCInst *MI = const_cast<MCInst *>(I.getInst());
|
||||
MCInst &MI = *const_cast<MCInst *>(I.getInst());
|
||||
DEBUG(dbgs() << "Shuffling: " << MCII.getName(MI.getOpcode()));
|
||||
assert(!HexagonMCInstrInfo::getDesc(MCII, MI).isPseudo());
|
||||
|
||||
if (!HexagonMCInstrInfo::isImmext(*MI)) {
|
||||
append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, *MI),
|
||||
false);
|
||||
if (!HexagonMCInstrInfo::isImmext(MI)) {
|
||||
append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, MI));
|
||||
Extender = nullptr;
|
||||
} else
|
||||
Extender = MI;
|
||||
Extender = &MI;
|
||||
}
|
||||
}
|
||||
|
||||
BundleFlags = MCB.getOperand(0).getImm();
|
||||
}
|
||||
|
||||
void HexagonMCShuffler::init(MCInst &MCB, MCInst const *AddMI,
|
||||
void HexagonMCShuffler::init(MCInst &MCB, MCInst const &AddMI,
|
||||
bool bInsertAtFront) {
|
||||
if (HexagonMCInstrInfo::isBundle(MCB)) {
|
||||
if (bInsertAtFront && AddMI)
|
||||
append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, *AddMI),
|
||||
false);
|
||||
if (bInsertAtFront)
|
||||
append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, AddMI));
|
||||
MCInst const *Extender = nullptr;
|
||||
// Copy the bundle for the shuffling.
|
||||
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo());
|
||||
MCInst *MI = const_cast<MCInst *>(I.getInst());
|
||||
if (!HexagonMCInstrInfo::isImmext(*MI)) {
|
||||
append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, *MI),
|
||||
false);
|
||||
MCInst &MI = *const_cast<MCInst *>(I.getInst());
|
||||
if (!HexagonMCInstrInfo::isImmext(MI)) {
|
||||
append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, MI));
|
||||
Extender = nullptr;
|
||||
} else
|
||||
Extender = MI;
|
||||
Extender = &MI;
|
||||
}
|
||||
if (!bInsertAtFront && AddMI)
|
||||
append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, *AddMI),
|
||||
false);
|
||||
if (!bInsertAtFront)
|
||||
append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, AddMI));
|
||||
}
|
||||
|
||||
BundleFlags = MCB.getOperand(0).getImm();
|
||||
|
@ -80,11 +77,11 @@ void HexagonMCShuffler::copyTo(MCInst &MCB) {
|
|||
// Copy the results into the bundle.
|
||||
for (HexagonShuffler::iterator I = begin(); I != end(); ++I) {
|
||||
|
||||
MCInst const *MI = I->getDesc();
|
||||
MCInst const &MI = I->getDesc();
|
||||
MCInst const *Extender = I->getExtender();
|
||||
if (Extender)
|
||||
MCB.addOperand(MCOperand::createInst(Extender));
|
||||
MCB.addOperand(MCOperand::createInst(MI));
|
||||
MCB.addOperand(MCOperand::createInst(&MI));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,9 +95,9 @@ bool HexagonMCShuffler::reshuffleTo(MCInst &MCB) {
|
|||
return (!getError());
|
||||
}
|
||||
|
||||
bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCInst &MCB) {
|
||||
HexagonMCShuffler MCS(MCII, STI, MCB);
|
||||
bool llvm::HexagonMCShuffle(bool Fatal, MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst &MCB) {
|
||||
HexagonMCShuffler MCS(true, MCII, STI, MCB);
|
||||
|
||||
if (DisableShuffle)
|
||||
// Ignore if user chose so.
|
||||
|
@ -124,6 +121,18 @@ bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
|||
if (!MCS.reshuffleTo(MCB)) {
|
||||
// Unless there is any error, which should not happen at this point.
|
||||
unsigned shuffleError = MCS.getError();
|
||||
|
||||
if (!Fatal && (shuffleError != HexagonShuffler::SHUFFLE_SUCCESS))
|
||||
return false;
|
||||
if (shuffleError != HexagonShuffler::SHUFFLE_SUCCESS) {
|
||||
errs() << "\nFailing packet:\n";
|
||||
for (const auto& I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
MCInst *MI = const_cast<MCInst *>(I.getInst());
|
||||
errs() << HexagonMCInstrInfo::getName(MCII, *MI) << ' ' << HexagonMCInstrInfo::getDesc(MCII, *MI).getOpcode() << '\n';
|
||||
}
|
||||
errs() << '\n';
|
||||
}
|
||||
|
||||
switch (shuffleError) {
|
||||
default:
|
||||
llvm_unreachable("unknown error");
|
||||
|
@ -176,7 +185,7 @@ llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
|||
DuplexCandidate duplexToTry = possibleDuplexes.pop_back_val();
|
||||
MCInst Attempt(MCB);
|
||||
HexagonMCInstrInfo::replaceDuplex(Context, Attempt, duplexToTry);
|
||||
HexagonMCShuffler MCS(MCII, STI, Attempt); // copy packet to the shuffler
|
||||
HexagonMCShuffler MCS(true, MCII, STI, Attempt); // copy packet to the shuffler
|
||||
if (MCS.size() == 1) { // case of one duplex
|
||||
// copy the created duplex in the shuffler to the bundle
|
||||
MCS.copyTo(MCB);
|
||||
|
@ -191,7 +200,7 @@ llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
|||
}
|
||||
|
||||
if (doneShuffling == false) {
|
||||
HexagonMCShuffler MCS(MCII, STI, MCB);
|
||||
HexagonMCShuffler MCS(true, MCII, STI, MCB);
|
||||
doneShuffling = MCS.reshuffleTo(MCB); // shuffle
|
||||
shuffleError = MCS.getError();
|
||||
}
|
||||
|
@ -202,8 +211,8 @@ llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
|||
}
|
||||
|
||||
bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCInst &MCB, MCInst const *AddMI, int fixupCount) {
|
||||
if (!HexagonMCInstrInfo::isBundle(MCB) || !AddMI)
|
||||
MCInst &MCB, MCInst const &AddMI, int fixupCount) {
|
||||
if (!HexagonMCInstrInfo::isBundle(MCB))
|
||||
return false;
|
||||
|
||||
// if fixups present, make sure we don't insert too many nops that would
|
||||
|
@ -211,8 +220,15 @@ bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
|||
unsigned int bundleSize = HexagonMCInstrInfo::bundleSize(MCB);
|
||||
if (bundleSize >= HEXAGON_PACKET_SIZE)
|
||||
return false;
|
||||
bool bhasDuplex = HexagonMCInstrInfo::hasDuplex(MCII, MCB);
|
||||
if (fixupCount >= 2) {
|
||||
return false;
|
||||
if (bhasDuplex) {
|
||||
if (bundleSize >= HEXAGON_PACKET_SIZE - 1) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (bundleSize == HEXAGON_PACKET_SIZE - 1 && fixupCount)
|
||||
return false;
|
||||
|
@ -221,7 +237,16 @@ bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
|||
if (DisableShuffle)
|
||||
return false;
|
||||
|
||||
HexagonMCShuffler MCS(MCII, STI, MCB, AddMI);
|
||||
// mgl: temporary code (shuffler doesn't take into account the fact that
|
||||
// a duplex takes up two slots. for example, 3 nops can be put into a packet
|
||||
// containing a duplex oversubscribing slots by 1).
|
||||
unsigned maxBundleSize = (HexagonMCInstrInfo::hasImmExt(MCB))
|
||||
? HEXAGON_PACKET_SIZE
|
||||
: HEXAGON_PACKET_SIZE - 1;
|
||||
if (bhasDuplex && bundleSize >= maxBundleSize)
|
||||
return false;
|
||||
|
||||
HexagonMCShuffler MCS(MCII, STI, MCB, AddMI, false);
|
||||
if (!MCS.reshuffleTo(MCB)) {
|
||||
unsigned shuffleError = MCS.getError();
|
||||
switch (shuffleError) {
|
||||
|
|
|
@ -27,16 +27,16 @@ class HexagonMCShuffler : public HexagonShuffler {
|
|||
bool duplex_present;
|
||||
|
||||
public:
|
||||
HexagonMCShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCInst &MCB)
|
||||
HexagonMCShuffler(bool Fatal, MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst &MCB)
|
||||
: HexagonShuffler(MCII, STI) {
|
||||
init(MCB);
|
||||
};
|
||||
HexagonMCShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCInst &MCB, const MCInst *AddMI,
|
||||
bool bInsertAtFront = false)
|
||||
MCInst &MCB, MCInst const &AddMI,
|
||||
bool InsertAtFront)
|
||||
: HexagonShuffler(MCII, STI) {
|
||||
init(MCB, AddMI, bInsertAtFront);
|
||||
init(MCB, AddMI, InsertAtFront);
|
||||
};
|
||||
|
||||
// Copy reordered bundle to another.
|
||||
|
@ -49,14 +49,14 @@ public:
|
|||
|
||||
private:
|
||||
void init(MCInst &MCB);
|
||||
void init(MCInst &MCB, const MCInst *AddMI, bool bInsertAtFront = false);
|
||||
void init(MCInst &MCB, MCInst const &AddMI, bool InsertAtFront);
|
||||
};
|
||||
|
||||
// Invocation of the shuffler.
|
||||
bool HexagonMCShuffle(bool Fatal, MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst &);
|
||||
bool HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCInst &);
|
||||
bool HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCInst &, const MCInst *, int);
|
||||
MCInst &, MCInst const &, int);
|
||||
unsigned HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCContext &Context, MCInst &,
|
||||
SmallVector<DuplexCandidate, 8>);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCDwarf.h"
|
||||
#include "llvm/MC/MCELFStreamer.h"
|
||||
#include "llvm/MC/MCInstrAnalysis.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
|
@ -95,31 +96,19 @@ StringRef Hexagon_MC::selectHexagonCPU(const Triple &TT, StringRef CPU) {
|
|||
return ArchV;
|
||||
}
|
||||
|
||||
MCInstrInfo *llvm::createHexagonMCInstrInfo() {
|
||||
MCInstrInfo *X = new MCInstrInfo();
|
||||
InitHexagonMCInstrInfo(X);
|
||||
return X;
|
||||
unsigned HexagonGetLastSlot() {
|
||||
return HexagonItinerariesV4FU::SLOT3;
|
||||
}
|
||||
|
||||
static MCRegisterInfo *createHexagonMCRegisterInfo(const Triple &TT) {
|
||||
MCRegisterInfo *X = new MCRegisterInfo();
|
||||
InitHexagonMCRegisterInfo(X, Hexagon::R31);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCSubtargetInfo *
|
||||
createHexagonMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
|
||||
CPU = Hexagon_MC::selectHexagonCPU(TT, CPU);
|
||||
return createHexagonMCSubtargetInfoImpl(TT, CPU, FS);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class HexagonTargetAsmStreamer : public HexagonTargetStreamer {
|
||||
public:
|
||||
HexagonTargetAsmStreamer(MCStreamer &S,
|
||||
formatted_raw_ostream &, bool,
|
||||
MCInstPrinter &)
|
||||
formatted_raw_ostream &OS,
|
||||
bool isVerboseAsm,
|
||||
MCInstPrinter &IP)
|
||||
: HexagonTargetStreamer(S) {}
|
||||
|
||||
void prettyPrintAsm(MCInstPrinter &InstPrinter, raw_ostream &OS,
|
||||
|
@ -156,24 +145,15 @@ public:
|
|||
|
||||
class HexagonTargetELFStreamer : public HexagonTargetStreamer {
|
||||
public:
|
||||
HexagonTargetELFStreamer(MCStreamer &S, MCSubtargetInfo const &STI)
|
||||
: HexagonTargetStreamer(S) {
|
||||
auto Bits = STI.getFeatureBits();
|
||||
unsigned Flags = 0;
|
||||
if (Bits[Hexagon::ArchV60])
|
||||
Flags = ELF::EF_HEXAGON_MACH_V60;
|
||||
else if (Bits[Hexagon::ArchV55])
|
||||
Flags = ELF::EF_HEXAGON_MACH_V55;
|
||||
else if (Bits[Hexagon::ArchV5])
|
||||
Flags = ELF::EF_HEXAGON_MACH_V5;
|
||||
else if (Bits[Hexagon::ArchV4])
|
||||
Flags = ELF::EF_HEXAGON_MACH_V4;
|
||||
getStreamer().getAssembler().setELFHeaderEFlags(Flags);
|
||||
}
|
||||
|
||||
MCELFStreamer &getStreamer() {
|
||||
return static_cast<MCELFStreamer &>(Streamer);
|
||||
}
|
||||
HexagonTargetELFStreamer(MCStreamer &S, MCSubtargetInfo const &STI)
|
||||
: HexagonTargetStreamer(S) {
|
||||
MCAssembler &MCA = getStreamer().getAssembler();
|
||||
MCA.setELFHeaderEFlags(Hexagon_MC::GetELFFlags(STI));
|
||||
}
|
||||
|
||||
|
||||
void EmitCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size,
|
||||
unsigned ByteAlignment,
|
||||
|
@ -196,13 +176,26 @@ public:
|
|||
|
||||
} // end anonymous namespace
|
||||
|
||||
llvm::MCInstrInfo *llvm::createHexagonMCInstrInfo() {
|
||||
MCInstrInfo *X = new MCInstrInfo();
|
||||
InitHexagonMCInstrInfo(X);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCRegisterInfo *createHexagonMCRegisterInfo(const Triple &TT) {
|
||||
MCRegisterInfo *X = new MCRegisterInfo();
|
||||
InitHexagonMCRegisterInfo(X, Hexagon::R31);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCAsmInfo *createHexagonMCAsmInfo(const MCRegisterInfo &MRI,
|
||||
const Triple &TT) {
|
||||
MCAsmInfo *MAI = new HexagonMCAsmInfo(TT);
|
||||
|
||||
// VirtualFP = (R30 + #0).
|
||||
MCCFIInstruction Inst =
|
||||
MCCFIInstruction::createDefCfa(nullptr, Hexagon::R30, 0);
|
||||
MCCFIInstruction::createDefCfa(nullptr,
|
||||
MRI.getDwarfRegNum(Hexagon::R30, true), 0);
|
||||
MAI->addInitialFrameState(Inst);
|
||||
|
||||
return MAI;
|
||||
|
@ -212,31 +205,133 @@ static MCInstPrinter *createHexagonMCInstPrinter(const Triple &T,
|
|||
unsigned SyntaxVariant,
|
||||
const MCAsmInfo &MAI,
|
||||
const MCInstrInfo &MII,
|
||||
const MCRegisterInfo &MRI) {
|
||||
const MCRegisterInfo &MRI)
|
||||
{
|
||||
if (SyntaxVariant == 0)
|
||||
return (new HexagonInstPrinter(MAI, MII, MRI));
|
||||
return new HexagonInstPrinter(MAI, MII, MRI);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static MCTargetStreamer *createMCAsmTargetStreamer(MCStreamer &S,
|
||||
formatted_raw_ostream &OS,
|
||||
MCInstPrinter *InstPrint,
|
||||
bool IsVerboseAsm) {
|
||||
return new HexagonTargetAsmStreamer(S, OS, IsVerboseAsm, *InstPrint);
|
||||
static MCTargetStreamer *
|
||||
createMCAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,
|
||||
MCInstPrinter *IP, bool IsVerboseAsm) {
|
||||
return new HexagonTargetAsmStreamer(S, OS, IsVerboseAsm, *IP);
|
||||
}
|
||||
|
||||
static MCStreamer *createMCStreamer(Triple const &T, MCContext &Context,
|
||||
MCAsmBackend &MAB, raw_pwrite_stream &OS,
|
||||
MCCodeEmitter *Emitter, bool RelaxAll) {
|
||||
return createHexagonELFStreamer(Context, MAB, OS, Emitter);
|
||||
static MCStreamer *createMCStreamer(Triple const &T,
|
||||
MCContext &Context,
|
||||
MCAsmBackend &MAB,
|
||||
raw_pwrite_stream &OS,
|
||||
MCCodeEmitter *Emitter,
|
||||
bool RelaxAll) {
|
||||
return createHexagonELFStreamer(T, Context, MAB, OS, Emitter);
|
||||
}
|
||||
|
||||
static MCTargetStreamer *
|
||||
createHexagonObjectTargetStreamer(MCStreamer &S, MCSubtargetInfo const &STI) {
|
||||
createHexagonObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
|
||||
return new HexagonTargetELFStreamer(S, STI);
|
||||
}
|
||||
|
||||
static void LLVM_ATTRIBUTE_UNUSED clearFeature(MCSubtargetInfo* STI, uint64_t F) {
|
||||
uint64_t FB = STI->getFeatureBits().to_ullong();
|
||||
if (FB & (1ULL << F))
|
||||
STI->ToggleFeature(F);
|
||||
}
|
||||
|
||||
static bool LLVM_ATTRIBUTE_UNUSED checkFeature(MCSubtargetInfo* STI, uint64_t F) {
|
||||
uint64_t FB = STI->getFeatureBits().to_ullong();
|
||||
return (FB & (1ULL << F)) != 0;
|
||||
}
|
||||
|
||||
StringRef Hexagon_MC::ParseHexagonTriple(const Triple &TT, StringRef CPU) {
|
||||
StringRef CPUName = Hexagon_MC::selectHexagonCPU(TT, CPU);
|
||||
StringRef FS = "";
|
||||
if (CPUName.equals_lower("hexagonv60"))
|
||||
FS = "+hvx";
|
||||
return FS;
|
||||
}
|
||||
|
||||
static bool isCPUValid(std::string CPU)
|
||||
{
|
||||
std::vector<std::string> table
|
||||
{
|
||||
"hexagonv4",
|
||||
"hexagonv5",
|
||||
"hexagonv55",
|
||||
"hexagonv60",
|
||||
};
|
||||
|
||||
return std::find(table.begin(), table.end(), CPU) != table.end();
|
||||
}
|
||||
|
||||
MCSubtargetInfo *Hexagon_MC::createHexagonMCSubtargetInfo(const Triple &TT,
|
||||
StringRef CPU,
|
||||
StringRef FS) {
|
||||
StringRef ArchFS = (FS.size()) ? FS : Hexagon_MC::ParseHexagonTriple(TT, CPU);
|
||||
StringRef CPUName = Hexagon_MC::selectHexagonCPU(TT, CPU);
|
||||
if (!isCPUValid(CPUName.str()))
|
||||
{
|
||||
errs() << "error: invalid CPU \"" << CPUName.str().c_str() << "\" specified\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MCSubtargetInfo *X = createHexagonMCSubtargetInfoImpl(TT, CPUName, ArchFS);
|
||||
if (X->getFeatureBits()[Hexagon::ExtensionHVXDbl]) {
|
||||
llvm::FeatureBitset Features = X->getFeatureBits();
|
||||
X->setFeatureBits(Features.set(Hexagon::ExtensionHVX));
|
||||
}
|
||||
return X;
|
||||
}
|
||||
|
||||
unsigned Hexagon_MC::GetELFFlags(const MCSubtargetInfo &STI) {
|
||||
static std::map<StringRef,unsigned> ElfFlags = {
|
||||
{"hexagonv4", ELF::EF_HEXAGON_MACH_V4},
|
||||
{"hexagonv5", ELF::EF_HEXAGON_MACH_V5},
|
||||
{"hexagonv55", ELF::EF_HEXAGON_MACH_V55},
|
||||
{"hexagonv60", ELF::EF_HEXAGON_MACH_V60},
|
||||
};
|
||||
|
||||
auto F = ElfFlags.find(STI.getCPU());
|
||||
assert(F != ElfFlags.end() && "Unrecognized Architecture");
|
||||
return F->second;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class HexagonMCInstrAnalysis : public MCInstrAnalysis {
|
||||
public:
|
||||
HexagonMCInstrAnalysis(MCInstrInfo const *Info) : MCInstrAnalysis(Info) {}
|
||||
|
||||
bool isUnconditionalBranch(MCInst const &Inst) const override {
|
||||
//assert(!HexagonMCInstrInfo::isBundle(Inst));
|
||||
return MCInstrAnalysis::isUnconditionalBranch(Inst);
|
||||
}
|
||||
|
||||
bool isConditionalBranch(MCInst const &Inst) const override {
|
||||
//assert(!HexagonMCInstrInfo::isBundle(Inst));
|
||||
return MCInstrAnalysis::isConditionalBranch(Inst);
|
||||
}
|
||||
|
||||
bool evaluateBranch(MCInst const &Inst, uint64_t Addr,
|
||||
uint64_t Size, uint64_t &Target) const override {
|
||||
//assert(!HexagonMCInstrInfo::isBundle(Inst));
|
||||
if(!HexagonMCInstrInfo::isExtendable(*Info, Inst))
|
||||
return false;
|
||||
auto const &Extended(HexagonMCInstrInfo::getExtendableOperand(*Info, Inst));
|
||||
assert(Extended.isExpr());
|
||||
int64_t Value;
|
||||
if(!Extended.getExpr()->evaluateAsAbsolute(Value))
|
||||
return false;
|
||||
Target = Value;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static MCInstrAnalysis *createHexagonMCInstrAnalysis(const MCInstrInfo *Info) {
|
||||
return new HexagonMCInstrAnalysis(Info);
|
||||
}
|
||||
|
||||
// Force static initialization.
|
||||
extern "C" void LLVMInitializeHexagonTargetMC() {
|
||||
// Register the MC asm info.
|
||||
|
@ -252,7 +347,7 @@ extern "C" void LLVMInitializeHexagonTargetMC() {
|
|||
|
||||
// Register the MC subtarget info.
|
||||
TargetRegistry::RegisterMCSubtargetInfo(getTheHexagonTarget(),
|
||||
createHexagonMCSubtargetInfo);
|
||||
Hexagon_MC::createHexagonMCSubtargetInfo);
|
||||
|
||||
// Register the MC Code Emitter
|
||||
TargetRegistry::RegisterMCCodeEmitter(getTheHexagonTarget(),
|
||||
|
@ -262,8 +357,18 @@ extern "C" void LLVMInitializeHexagonTargetMC() {
|
|||
TargetRegistry::RegisterMCAsmBackend(getTheHexagonTarget(),
|
||||
createHexagonAsmBackend);
|
||||
|
||||
|
||||
// Register the MC instruction analyzer.
|
||||
TargetRegistry::RegisterMCInstrAnalysis(getTheHexagonTarget(),
|
||||
createHexagonMCInstrAnalysis);
|
||||
|
||||
// Register the obj streamer
|
||||
TargetRegistry::RegisterELFStreamer(getTheHexagonTarget(), createMCStreamer);
|
||||
TargetRegistry::RegisterELFStreamer(getTheHexagonTarget(),
|
||||
createMCStreamer);
|
||||
|
||||
// Register the obj target streamer
|
||||
TargetRegistry::RegisterObjectTargetStreamer(getTheHexagonTarget(),
|
||||
createHexagonObjectTargetStreamer);
|
||||
|
||||
// Register the asm streamer
|
||||
TargetRegistry::RegisterAsmTargetStreamer(getTheHexagonTarget(),
|
||||
|
@ -272,7 +377,4 @@ extern "C" void LLVMInitializeHexagonTargetMC() {
|
|||
// Register the MC Inst Printer
|
||||
TargetRegistry::RegisterMCInstPrinter(getTheHexagonTarget(),
|
||||
createHexagonMCInstPrinter);
|
||||
|
||||
TargetRegistry::RegisterObjectTargetStreamer(
|
||||
getTheHexagonTarget(), createHexagonObjectTargetStreamer);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,18 @@ extern cl::opt<bool> HexagonDisableDuplex;
|
|||
extern const InstrStage HexagonStages[];
|
||||
|
||||
MCInstrInfo *createHexagonMCInstrInfo();
|
||||
MCRegisterInfo *createHexagonMCRegisterInfo(StringRef TT);
|
||||
|
||||
namespace Hexagon_MC {
|
||||
StringRef ParseHexagonTriple(const Triple &TT, StringRef CPU);
|
||||
StringRef selectHexagonCPU(const Triple &TT, StringRef CPU);
|
||||
|
||||
/// Create a Hexagon MCSubtargetInfo instance. This is exposed so Asm parser,
|
||||
/// etc. do not need to go through TargetRegistry.
|
||||
MCSubtargetInfo *createHexagonMCSubtargetInfo(const Triple &TT, StringRef CPU,
|
||||
StringRef FS);
|
||||
unsigned GetELFFlags(const MCSubtargetInfo &STI);
|
||||
}
|
||||
|
||||
MCCodeEmitter *createHexagonMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
|
@ -53,14 +65,9 @@ MCAsmBackend *createHexagonAsmBackend(const Target &T,
|
|||
|
||||
MCObjectWriter *createHexagonELFObjectWriter(raw_pwrite_stream &OS,
|
||||
uint8_t OSABI, StringRef CPU);
|
||||
} // End llvm namespace
|
||||
|
||||
namespace Hexagon_MC {
|
||||
|
||||
StringRef selectHexagonCPU(const Triple &TT, StringRef CPU);
|
||||
|
||||
} // end namespace Hexagon_MC
|
||||
|
||||
} // end namespace llvm
|
||||
unsigned HexagonGetLastSlot();
|
||||
|
||||
// Define symbolic names for Hexagon registers. This defines a mapping from
|
||||
// register name to register number.
|
||||
|
|
|
@ -37,16 +37,16 @@ class HexagonBid {
|
|||
unsigned Bid;
|
||||
|
||||
public:
|
||||
HexagonBid() : Bid(0){};
|
||||
HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; };
|
||||
HexagonBid() : Bid(0){}
|
||||
HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; }
|
||||
|
||||
// Check if the insn priority is overflowed.
|
||||
bool isSold() const { return (Bid >= MAX); };
|
||||
bool isSold() const { return (Bid >= MAX); }
|
||||
|
||||
HexagonBid &operator+=(const HexagonBid &B) {
|
||||
Bid += B.Bid;
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Slot shuffling allocation.
|
||||
|
@ -56,7 +56,7 @@ class HexagonUnitAuction {
|
|||
unsigned isSold : HEXAGON_PACKET_SIZE;
|
||||
|
||||
public:
|
||||
HexagonUnitAuction() : isSold(0){};
|
||||
HexagonUnitAuction(unsigned cs = 0) : isSold(cs){};
|
||||
|
||||
// Allocate slots.
|
||||
bool bid(unsigned B) {
|
||||
|
@ -70,11 +70,10 @@ public:
|
|||
isSold |= Scores[i].isSold() << i;
|
||||
}
|
||||
return true;
|
||||
;
|
||||
} else
|
||||
// Error if the desired slots are already full.
|
||||
return false;
|
||||
};
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
@ -83,9 +82,6 @@ unsigned HexagonResource::setWeight(unsigned s) {
|
|||
const unsigned MaskWeight = SlotWeight - 1;
|
||||
bool Key = (1 << s) & getUnits();
|
||||
|
||||
// TODO: Improve this API so that we can prevent misuse statically.
|
||||
assert(SlotWeight * s < 32 && "Argument to setWeight too large.");
|
||||
|
||||
// Calculate relative weight of the insn for the given slot, weighing it the
|
||||
// heavier the more restrictive the insn is and the lowest the slots that the
|
||||
// insn may be executed in.
|
||||
|
@ -141,6 +137,40 @@ HexagonCVIResource::HexagonCVIResource(TypeUnitsAndLanes *TUL,
|
|||
}
|
||||
}
|
||||
|
||||
struct CVIUnits {
|
||||
unsigned Units;
|
||||
unsigned Lanes;
|
||||
};
|
||||
typedef SmallVector<struct CVIUnits, 8> HVXInstsT;
|
||||
|
||||
static unsigned makeAllBits(unsigned startBit, unsigned Lanes)
|
||||
|
||||
{
|
||||
for (unsigned i = 1 ; i < Lanes ; ++i)
|
||||
startBit = (startBit << 1) | startBit;
|
||||
return startBit;
|
||||
}
|
||||
|
||||
static bool checkHVXPipes(const HVXInstsT& hvxInsts, unsigned startIdx, unsigned usedUnits)
|
||||
|
||||
{
|
||||
if (startIdx < hvxInsts.size()) {
|
||||
if (!hvxInsts[startIdx].Units)
|
||||
return checkHVXPipes(hvxInsts, startIdx + 1, usedUnits);
|
||||
for (unsigned b = 0x1 ; b <= 0x8 ; b <<= 1) {
|
||||
if ((hvxInsts[startIdx].Units & b) == 0)
|
||||
continue;
|
||||
unsigned allBits = makeAllBits(b, hvxInsts[startIdx].Lanes);
|
||||
if ((allBits & usedUnits) == 0) {
|
||||
if (checkHVXPipes(hvxInsts, startIdx + 1, usedUnits | allBits))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
HexagonShuffler::HexagonShuffler(MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI)
|
||||
: MCII(MCII), STI(STI) {
|
||||
|
@ -154,21 +184,76 @@ void HexagonShuffler::reset() {
|
|||
Error = SHUFFLE_SUCCESS;
|
||||
}
|
||||
|
||||
void HexagonShuffler::append(MCInst const *ID, MCInst const *Extender,
|
||||
unsigned S, bool X) {
|
||||
HexagonInstr PI(&TUL, MCII, ID, Extender, S, X);
|
||||
void HexagonShuffler::append(MCInst const &ID, MCInst const *Extender,
|
||||
unsigned S) {
|
||||
HexagonInstr PI(&TUL, MCII, &ID, Extender, S);
|
||||
|
||||
Packet.push_back(PI);
|
||||
}
|
||||
|
||||
static struct {
|
||||
unsigned first;
|
||||
unsigned second;
|
||||
} jumpSlots[] = { {8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1} };
|
||||
#define MAX_JUMP_SLOTS (sizeof(jumpSlots)/sizeof(jumpSlots[0]))
|
||||
|
||||
namespace {
|
||||
bool isDuplexAGroup(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
case Hexagon::SA1_addi:
|
||||
case Hexagon::SA1_addrx:
|
||||
case Hexagon::SA1_addsp:
|
||||
case Hexagon::SA1_and1:
|
||||
case Hexagon::SA1_clrf:
|
||||
case Hexagon::SA1_clrfnew:
|
||||
case Hexagon::SA1_clrt:
|
||||
case Hexagon::SA1_clrtnew:
|
||||
case Hexagon::SA1_cmpeqi:
|
||||
case Hexagon::SA1_combine0i:
|
||||
case Hexagon::SA1_combine1i:
|
||||
case Hexagon::SA1_combine2i:
|
||||
case Hexagon::SA1_combine3i:
|
||||
case Hexagon::SA1_combinerz:
|
||||
case Hexagon::SA1_combinezr:
|
||||
case Hexagon::SA1_dec:
|
||||
case Hexagon::SA1_inc:
|
||||
case Hexagon::SA1_seti:
|
||||
case Hexagon::SA1_setin1:
|
||||
case Hexagon::SA1_sxtb:
|
||||
case Hexagon::SA1_sxth:
|
||||
case Hexagon::SA1_tfr:
|
||||
case Hexagon::SA1_zxtb:
|
||||
case Hexagon::SA1_zxth:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned countNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) {
|
||||
unsigned Result = 0;
|
||||
unsigned Type = HexagonMCInstrInfo::getType(MCII, ID);
|
||||
if (Type == HexagonII::TypeDUPLEX) {
|
||||
unsigned subInst0Opcode = ID.getOperand(0).getInst()->getOpcode();
|
||||
unsigned subInst1Opcode = ID.getOperand(1).getInst()->getOpcode();
|
||||
Result += !isDuplexAGroup(subInst0Opcode);
|
||||
Result += !isDuplexAGroup(subInst1Opcode);
|
||||
} else
|
||||
Result += Type != HexagonII::TypeALU32 &&
|
||||
Type != HexagonII::TypeXTYPE;
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that the packet is legal and enforce relative insn order.
|
||||
bool HexagonShuffler::check() {
|
||||
// Descriptive slot masks.
|
||||
const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotOne = 0x2,
|
||||
slotThree = 0x8, slotFirstJump = 0x8, slotLastJump = 0x4,
|
||||
slotThree = 0x8, //slotFirstJump = 0x8,
|
||||
slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1;
|
||||
// Highest slots for branches and stores used to keep their original order.
|
||||
unsigned slotJump = slotFirstJump;
|
||||
//unsigned slotJump = slotFirstJump;
|
||||
unsigned slotLoadStore = slotFirstLoadStore;
|
||||
// Number of branches, solo branches, indirect branches.
|
||||
unsigned jumps = 0, jump1 = 0;
|
||||
|
@ -188,36 +273,39 @@ bool HexagonShuffler::check() {
|
|||
unsigned onlyNo1 = 0;
|
||||
unsigned xtypeFloat = 0;
|
||||
unsigned pSlot3Cnt = 0;
|
||||
unsigned memops = 0;
|
||||
unsigned deallocs = 0;
|
||||
iterator slot3ISJ = end();
|
||||
std::vector<iterator> foundBranches;
|
||||
unsigned reservedSlots = 0;
|
||||
|
||||
// Collect information from the insns in the packet.
|
||||
for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
|
||||
MCInst const *ID = ISJ->getDesc();
|
||||
MCInst const &ID = ISJ->getDesc();
|
||||
|
||||
if (HexagonMCInstrInfo::isSolo(MCII, *ID))
|
||||
solo += !ISJ->isSoloException();
|
||||
else if (HexagonMCInstrInfo::isSoloAX(MCII, *ID))
|
||||
onlyAX += !ISJ->isSoloException();
|
||||
else if (HexagonMCInstrInfo::isSoloAin1(MCII, *ID))
|
||||
onlyAin1 += !ISJ->isSoloException();
|
||||
if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32 &&
|
||||
HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeXTYPE)
|
||||
++neitherAnorX;
|
||||
if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID)) {
|
||||
if (HexagonMCInstrInfo::isSolo(MCII, ID))
|
||||
solo++;
|
||||
else if (HexagonMCInstrInfo::isSoloAX(MCII, ID))
|
||||
onlyAX++;
|
||||
else if (HexagonMCInstrInfo::isSoloAin1(MCII, ID))
|
||||
onlyAin1++;
|
||||
neitherAnorX += countNeitherAnorX(MCII, ID);
|
||||
if (HexagonMCInstrInfo::prefersSlot3(MCII, ID)) {
|
||||
++pSlot3Cnt;
|
||||
slot3ISJ = ISJ;
|
||||
}
|
||||
if (HexagonMCInstrInfo::isCofMax1(MCII, *ID))
|
||||
reservedSlots |= HexagonMCInstrInfo::getOtherReservedSlots(MCII, STI, ID);
|
||||
if (HexagonMCInstrInfo::isCofMax1(MCII, ID))
|
||||
++jump1;
|
||||
|
||||
switch (HexagonMCInstrInfo::getType(MCII, *ID)) {
|
||||
switch (HexagonMCInstrInfo::getType(MCII, ID)) {
|
||||
case HexagonII::TypeXTYPE:
|
||||
if (HexagonMCInstrInfo::isFloat(MCII, *ID))
|
||||
if (HexagonMCInstrInfo::isFloat(MCII, ID))
|
||||
++xtypeFloat;
|
||||
break;
|
||||
case HexagonII::TypeJR:
|
||||
case HexagonII::TypeJ:
|
||||
++jumps;
|
||||
foundBranches.push_back(ISJ);
|
||||
break;
|
||||
case HexagonII::TypeCVI_VM_VP_LDU:
|
||||
++onlyNo1;
|
||||
|
@ -228,10 +316,14 @@ bool HexagonShuffler::check() {
|
|||
case HexagonII::TypeLD:
|
||||
++loads;
|
||||
++memory;
|
||||
if (ISJ->Core.getUnits() == slotSingleLoad)
|
||||
if (ISJ->Core.getUnits() == slotSingleLoad ||
|
||||
HexagonMCInstrInfo::getType(MCII, ID) ==
|
||||
HexagonII::TypeCVI_VM_VP_LDU)
|
||||
++load0;
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, *ID).isReturn())
|
||||
++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, ID).isReturn()) {
|
||||
++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
|
||||
foundBranches.push_back(ISJ);
|
||||
}
|
||||
break;
|
||||
case HexagonII::TypeCVI_VM_STU:
|
||||
++onlyNo1;
|
||||
|
@ -241,26 +333,50 @@ bool HexagonShuffler::check() {
|
|||
case HexagonII::TypeST:
|
||||
++stores;
|
||||
++memory;
|
||||
if (ISJ->Core.getUnits() == slotSingleStore)
|
||||
if (ISJ->Core.getUnits() == slotSingleStore ||
|
||||
HexagonMCInstrInfo::getType(MCII, ID) == HexagonII::TypeCVI_VM_STU)
|
||||
++store0;
|
||||
break;
|
||||
case HexagonII::TypeV4LDST:
|
||||
++loads;
|
||||
++stores;
|
||||
++store1;
|
||||
++memops;
|
||||
++memory;
|
||||
break;
|
||||
case HexagonII::TypeNV:
|
||||
case HexagonII::TypeNCJ:
|
||||
++memory; // NV insns are memory-like.
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch())
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch()) {
|
||||
++jumps, ++jump1;
|
||||
foundBranches.push_back(ISJ);
|
||||
}
|
||||
break;
|
||||
case HexagonII::TypeCR:
|
||||
// Legacy conditional branch predicated on a register.
|
||||
case HexagonII::TypeSYSTEM:
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad())
|
||||
++loads;
|
||||
case HexagonII::TypeCJ:
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch()) {
|
||||
++jumps;
|
||||
foundBranches.push_back(ISJ);
|
||||
}
|
||||
break;
|
||||
case HexagonII::TypeDUPLEX: {
|
||||
++duplex;
|
||||
MCInst const &Inst0 = *ID.getOperand(0).getInst();
|
||||
MCInst const &Inst1 = *ID.getOperand(1).getInst();
|
||||
if (HexagonMCInstrInfo::isCofMax1(MCII, Inst0))
|
||||
++jump1;
|
||||
if (HexagonMCInstrInfo::isCofMax1(MCII, Inst1))
|
||||
++jump1;
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isBranch()) {
|
||||
++jumps;
|
||||
foundBranches.push_back(ISJ);
|
||||
}
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isBranch()) {
|
||||
++jumps;
|
||||
foundBranches.push_back(ISJ);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,12 +393,20 @@ bool HexagonShuffler::check() {
|
|||
Error = SHUFFLE_ERROR_BRANCHES;
|
||||
return false;
|
||||
}
|
||||
if (memops && stores > 1) {
|
||||
Error = SHUFFLE_ERROR_STORE_LOAD_CONFLICT;
|
||||
return false;
|
||||
}
|
||||
if (deallocs && stores) {
|
||||
Error = SHUFFLE_ERROR_STORE_LOAD_CONFLICT;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Modify packet accordingly.
|
||||
// TODO: need to reserve slots #0 and #1 for duplex insns.
|
||||
bool bOnlySlot3 = false;
|
||||
for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
|
||||
MCInst const *ID = ISJ->getDesc();
|
||||
MCInst const &ID = ISJ->getDesc();
|
||||
|
||||
if (!ISJ->Core.getUnits()) {
|
||||
// Error if insn may not be executed in any slot.
|
||||
|
@ -291,40 +415,24 @@ bool HexagonShuffler::check() {
|
|||
}
|
||||
|
||||
// Exclude from slot #1 any insn but A2_nop.
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, *ID).getOpcode() != Hexagon::A2_nop)
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, ID).getOpcode() != Hexagon::A2_nop)
|
||||
if (onlyNo1)
|
||||
ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
|
||||
|
||||
// Exclude from slot #1 any insn but A-type.
|
||||
if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32)
|
||||
if (HexagonMCInstrInfo::getType(MCII, ID) != HexagonII::TypeALU32)
|
||||
if (onlyAin1)
|
||||
ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
|
||||
|
||||
// Branches must keep the original order.
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch() ||
|
||||
HexagonMCInstrInfo::getDesc(MCII, *ID).isCall())
|
||||
if (jumps > 1) {
|
||||
if (slotJump < slotLastJump) {
|
||||
// Error if indirect branch with another branch or
|
||||
// no more slots available for branches.
|
||||
Error = SHUFFLE_ERROR_BRANCHES;
|
||||
return false;
|
||||
}
|
||||
// Pin the branch to the highest slot available to it.
|
||||
ISJ->Core.setUnits(ISJ->Core.getUnits() & slotJump);
|
||||
// Update next highest slot available to branches.
|
||||
slotJump >>= 1;
|
||||
}
|
||||
|
||||
// A single load must use slot #0.
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad()) {
|
||||
if (loads == 1 && loads == memory)
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) {
|
||||
if (loads == 1 && loads == memory && memops == 0)
|
||||
// Pin the load to slot #0.
|
||||
ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);
|
||||
}
|
||||
|
||||
// A single store must use slot #0.
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayStore()) {
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, ID).mayStore()) {
|
||||
if (!store0) {
|
||||
if (stores == 1)
|
||||
ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore);
|
||||
|
@ -347,7 +455,7 @@ bool HexagonShuffler::check() {
|
|||
}
|
||||
}
|
||||
|
||||
// flag if an instruction can only be executed in slot 3
|
||||
// flag if an instruction requires to be in slot 3
|
||||
if (ISJ->Core.getUnits() == slotThree)
|
||||
bOnlySlot3 = true;
|
||||
|
||||
|
@ -358,14 +466,61 @@ bool HexagonShuffler::check() {
|
|||
}
|
||||
}
|
||||
|
||||
// preserve branch order
|
||||
bool validateSlots = true;
|
||||
if (bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) {
|
||||
if (jumps > 1) {
|
||||
if (foundBranches.size() > 2) {
|
||||
Error = SHUFFLE_ERROR_BRANCHES;
|
||||
return false;
|
||||
}
|
||||
|
||||
// try all possible choices
|
||||
for (unsigned int i = 0 ; i < MAX_JUMP_SLOTS ; ++i) {
|
||||
// validate first jump with this slot rule
|
||||
if (!(jumpSlots[i].first & foundBranches[0]->Core.getUnits()))
|
||||
continue;
|
||||
|
||||
// validate second jump with this slot rule
|
||||
if (!(jumpSlots[i].second & foundBranches[1]->Core.getUnits()))
|
||||
continue;
|
||||
|
||||
// both valid for this configuration, set new slot rules
|
||||
PacketSave = Packet;
|
||||
foundBranches[0]->Core.setUnits(jumpSlots[i].first);
|
||||
foundBranches[1]->Core.setUnits(jumpSlots[i].second);
|
||||
|
||||
HexagonUnitAuction AuctionCore(reservedSlots);
|
||||
std::sort(begin(), end(), HexagonInstr::lessCore);
|
||||
|
||||
// see if things ok with that instruction being pinned to slot "slotJump"
|
||||
bool bFail = false;
|
||||
for (iterator I = begin(); I != end() && bFail != true; ++I)
|
||||
if (!AuctionCore.bid(I->Core.getUnits()))
|
||||
bFail = true;
|
||||
|
||||
// if yes, great, if not then restore original slot mask
|
||||
if (!bFail) {
|
||||
validateSlots = false; // all good, no need to re-do auction
|
||||
break;
|
||||
}
|
||||
else
|
||||
// restore original values
|
||||
Packet = PacketSave;
|
||||
}
|
||||
if (validateSlots == true) {
|
||||
Error = SHUFFLE_ERROR_NOSLOTS;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (jumps <= 1 && bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) {
|
||||
validateSlots = true;
|
||||
// save off slot mask of instruction marked with A_PREFER_SLOT3
|
||||
// and then pin it to slot #3
|
||||
unsigned saveUnits = slot3ISJ->Core.getUnits();
|
||||
slot3ISJ->Core.setUnits(saveUnits & slotThree);
|
||||
|
||||
HexagonUnitAuction AuctionCore;
|
||||
HexagonUnitAuction AuctionCore(reservedSlots);
|
||||
std::sort(begin(), end(), HexagonInstr::lessCore);
|
||||
|
||||
// see if things ok with that instruction being pinned to slot #3
|
||||
|
@ -379,16 +534,16 @@ bool HexagonShuffler::check() {
|
|||
validateSlots = false; // all good, no need to re-do auction
|
||||
else
|
||||
for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
|
||||
MCInst const *ID = ISJ->getDesc();
|
||||
if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID))
|
||||
MCInst const &ID = ISJ->getDesc();
|
||||
if (HexagonMCInstrInfo::prefersSlot3(MCII, ID))
|
||||
ISJ->Core.setUnits(saveUnits);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if any slot, core, is over-subscribed.
|
||||
// Check if any slot, core or CVI, is over-subscribed.
|
||||
// Verify the core slot subscriptions.
|
||||
if (validateSlots) {
|
||||
HexagonUnitAuction AuctionCore;
|
||||
HexagonUnitAuction AuctionCore(reservedSlots);
|
||||
|
||||
std::sort(begin(), end(), HexagonInstr::lessCore);
|
||||
|
||||
|
@ -399,17 +554,27 @@ bool HexagonShuffler::check() {
|
|||
}
|
||||
}
|
||||
// Verify the CVI slot subscriptions.
|
||||
{
|
||||
HexagonUnitAuction AuctionCVI;
|
||||
|
||||
std::sort(begin(), end(), HexagonInstr::lessCVI);
|
||||
|
||||
for (iterator I = begin(); I != end(); ++I)
|
||||
for (unsigned i = 0; i < I->CVI.getLanes(); ++i) // TODO: I->CVI.isValid?
|
||||
if (!AuctionCVI.bid(I->CVI.getUnits() << i)) {
|
||||
Error = SHUFFLE_ERROR_SLOTS;
|
||||
return false;
|
||||
}
|
||||
std::sort(begin(), end(), HexagonInstr::lessCVI);
|
||||
// create vector of hvx instructions to check
|
||||
HVXInstsT hvxInsts;
|
||||
hvxInsts.clear();
|
||||
for (iterator I = begin(); I != end(); ++I) {
|
||||
struct CVIUnits inst;
|
||||
inst.Units = I->CVI.getUnits();
|
||||
inst.Lanes = I->CVI.getLanes();
|
||||
if (inst.Units == 0)
|
||||
continue; // not an hvx inst or an hvx inst that doesn't uses any pipes
|
||||
hvxInsts.push_back(inst);
|
||||
}
|
||||
// if there are any hvx instructions in this packet, check pipe usage
|
||||
if (hvxInsts.size() > 0) {
|
||||
unsigned startIdx, usedUnits;
|
||||
startIdx = usedUnits = 0x0;
|
||||
if (checkHVXPipes(hvxInsts, startIdx, usedUnits) == false) {
|
||||
// too many pipes used to be valid
|
||||
Error = SHUFFLE_ERROR_SLOTS;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Error = SHUFFLE_SUCCESS;
|
||||
|
@ -452,10 +617,12 @@ bool HexagonShuffler::shuffle() {
|
|||
}
|
||||
|
||||
for (iterator ISJ = begin(); ISJ != end(); ++ISJ)
|
||||
DEBUG(dbgs().write_hex(ISJ->Core.getUnits());
|
||||
dbgs() << ':'
|
||||
<< HexagonMCInstrInfo::getDesc(MCII, *ISJ->getDesc())
|
||||
.getOpcode();
|
||||
DEBUG(dbgs().write_hex(ISJ->Core.getUnits()); if (ISJ->CVI.isValid()) {
|
||||
dbgs() << '/';
|
||||
dbgs().write_hex(ISJ->CVI.getUnits()) << '|';
|
||||
dbgs() << ISJ->CVI.getLanes();
|
||||
} dbgs() << ':'
|
||||
<< HexagonMCInstrInfo::getDesc(MCII, ISJ->getDesc()).getOpcode();
|
||||
dbgs() << '\n');
|
||||
DEBUG(dbgs() << '\n');
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ public:
|
|||
|
||||
void setUnits(unsigned s) {
|
||||
Slots = s & ~(~0U << HEXAGON_PACKET_SIZE);
|
||||
setWeight(s);
|
||||
};
|
||||
unsigned setWeight(unsigned s);
|
||||
|
||||
|
@ -44,7 +45,8 @@ public:
|
|||
|
||||
// Check if the resources are in ascending slot order.
|
||||
static bool lessUnits(const HexagonResource &A, const HexagonResource &B) {
|
||||
return (countPopulation(A.getUnits()) < countPopulation(B.getUnits()));
|
||||
return (countPopulation(A.getUnits()) <
|
||||
countPopulation(B.getUnits()));
|
||||
};
|
||||
// Check if the resources are in ascending weight order.
|
||||
static bool lessWeight(const HexagonResource &A, const HexagonResource &B) {
|
||||
|
@ -86,10 +88,10 @@ public:
|
|||
unsigned s, MCInst const *id);
|
||||
static void SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU);
|
||||
|
||||
bool isValid() const { return (Valid); };
|
||||
unsigned getLanes() const { return (Lanes); };
|
||||
bool mayLoad() const { return (Load); };
|
||||
bool mayStore() const { return (Store); };
|
||||
bool isValid() const { return Valid; };
|
||||
unsigned getLanes() const { return Lanes; };
|
||||
bool mayLoad() const { return Load; };
|
||||
bool mayStore() const { return Store; };
|
||||
};
|
||||
|
||||
// Handle to an insn used by the shuffling algorithm.
|
||||
|
@ -100,21 +102,17 @@ class HexagonInstr {
|
|||
MCInst const *Extender;
|
||||
HexagonResource Core;
|
||||
HexagonCVIResource CVI;
|
||||
bool SoloException;
|
||||
|
||||
public:
|
||||
HexagonInstr(HexagonCVIResource::TypeUnitsAndLanes *T,
|
||||
MCInstrInfo const &MCII, MCInst const *id,
|
||||
MCInst const *Extender, unsigned s, bool x = false)
|
||||
: ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id),
|
||||
SoloException(x) {};
|
||||
MCInst const *Extender, unsigned s)
|
||||
: ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id) {}
|
||||
|
||||
MCInst const *getDesc() const { return (ID); };
|
||||
MCInst const &getDesc() const { return *ID; };
|
||||
|
||||
MCInst const *getExtender() const { return Extender; }
|
||||
|
||||
unsigned isSoloException() const { return (SoloException); };
|
||||
|
||||
// Check if the handles are in ascending order for shuffling purposes.
|
||||
bool operator<(const HexagonInstr &B) const {
|
||||
return (HexagonResource::lessWeight(B.Core, Core));
|
||||
|
@ -136,6 +134,7 @@ class HexagonShuffler {
|
|||
|
||||
// Insn handles in a bundle.
|
||||
HexagonPacket Packet;
|
||||
HexagonPacket PacketSave;
|
||||
|
||||
// Shuffling error code.
|
||||
unsigned Error;
|
||||
|
@ -178,8 +177,7 @@ public:
|
|||
iterator end() { return (Packet.end()); };
|
||||
|
||||
// Add insn handle to the bundle .
|
||||
void append(MCInst const *ID, MCInst const *Extender, unsigned S,
|
||||
bool X = false);
|
||||
void append(MCInst const &ID, MCInst const *Extender, unsigned S);
|
||||
|
||||
// Return the error code for the last check or shuffling of the bundle.
|
||||
void setError(unsigned Err) { Error = Err; };
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
# RUN: llvm-mc -arch=hexagon -filetype=obj %s | llvm-objdump -t - | FileCheck %s
|
||||
|
||||
# CHECK: 00000062 g *COM* 00000008 quartet_table_isqrt
|
||||
|
||||
.common quartet_table_isqrt, 98, 8
|
||||
.common quartet_table_isqrt, 98, 8
|
|
@ -0,0 +1,8 @@
|
|||
# RUN: not llvm-mc -arch=hexagon -filetype=obj %s
|
||||
|
||||
#CHECK: 9400c000 { dcfetch(r0 + #0) }
|
||||
|
||||
junk:
|
||||
{
|
||||
dcfetch(r0 + #junk)
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
// RUN: llvm-mc -arch=hexagon -filetype=obj -o - %s | llvm-objdump -d - | FileCheck %s
|
||||
// REQUIRES: asserts
|
||||
.text
|
||||
// CHECK: { r7 = #-1; r7 = #-1 }
|
||||
.long 0x3a373a27
|
||||
// CHECK: { if (!p0.new) r7 = #0; if (p0.new) r7 = #0 }
|
||||
.long 0x3a573a47
|
||||
|
||||
{ r7 = #-1
|
||||
r6 = #-1 }
|
||||
// CHECK: { r7 = #-1; r6 = #-1 }
|
||||
|
||||
{ p0 = r0
|
||||
if (p0.new) r7 = #0
|
||||
if (!p0.new) r7 = #0 }
|
||||
// CHECK: if (p0.new) r7 = #0; if (!p0.new) r7 = #0
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# RUN: not llvm-mc -arch=hexagon %s 2> %t
|
||||
# RUN: FileCheck < %t %s
|
||||
|
||||
.equ a, 0
|
||||
.set a, 1
|
||||
.equ a, 2
|
||||
.equiv a, 3
|
||||
# CHECK: {{[Ee]}}rror: redefinition of 'a'
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
; RUN: llc -filetype=obj -march=hexagon %s -o - | llvm-objdump -r - | FileCheck %s
|
||||
|
||||
; CHECK: RELOCATION RECORDS FOR [.rela.text]:
|
||||
; CHECK: 00000000 R_HEX_B22_PCREL printf
|
||||
; CHECK: 00000004 R_HEX_32_6_X .rodata.str1.1
|
||||
; CHECK: 00000008 R_HEX_6_X .rodata.str1.1
|
||||
|
||||
target triple = "hexagon-unknown--elf"
|
||||
|
||||
@.str = private unnamed_addr constant [10 x i8] c"cxfir.log\00", align 1
|
||||
|
||||
declare i32 @printf(i8*, ...) #1
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define i32 @main() #0 {
|
||||
entry:
|
||||
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i32 0, i32 0))
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
# RUN: llvm-mc -arch=hexagon -filetype=obj %s | llvm-objdump -d - | FileCheck %s
|
||||
#
|
||||
|
||||
.I1:
|
||||
nop
|
||||
|
||||
# CHECK: .I1:
|
||||
# CHECK: nop
|
|
@ -0,0 +1,10 @@
|
|||
# RUN: not llvm-mc -arch=hexagon -filetype=obj %s 2>%t; FileCheck %s <%t
|
||||
|
||||
# Don't allow a symbolic operand for an insn that cannot take a
|
||||
# relocation.
|
||||
|
||||
r7:6 = rol(r5:4,#r2)
|
||||
|
||||
# This should produce an error
|
||||
#CHECK: error:
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
# RUN: llvm-mc -arch=hexagon -filetype=asm %s 2>%t; FileCheck %s <%t
|
||||
#
|
||||
|
||||
# Check that proper packets are not wrongly flagged as invalid.
|
||||
|
||||
1-3-4-f:
|
||||
{
|
||||
r3 = memub(r2++#1)
|
||||
if (cmp.eq(r3.new,#0)) jump:nt .
|
||||
jumpr lr
|
||||
r4 = #4
|
||||
}
|
||||
# CHECK-NOT: rror: invalid instruction packet
|
||||
|
||||
1-3-f-f:
|
||||
{
|
||||
r3 = memub(r2++#1)
|
||||
if (cmp.eq(r3.new,#0)) jump:nt .
|
||||
r5 = #5
|
||||
r4 = #4
|
||||
}
|
||||
# CHECK-NOT: rror: invalid instruction packet
|
||||
|
||||
# Special case of a fat packet that will slim when a compound is formed.
|
||||
3-3-8-c:
|
||||
{ LOOP0(3-3-8-c, R7)
|
||||
P0 = CMP.GT(R7, #0)
|
||||
IF (!P0.NEW) JUMP:NT .
|
||||
R21:20 = MEMD(R0+#16)
|
||||
R23:22 = MEMD(R0+#24)
|
||||
}
|
||||
# CHECK-NOT: rror: invalid instruction packet
|
||||
|
||||
1-f-f-f:
|
||||
{
|
||||
r3 = #3
|
||||
if (cmp.eq(r3.new,#0)) jump:nt .
|
||||
r5 = #5
|
||||
r4 = #4
|
||||
}
|
||||
# CHECK-NOT: rror: invalid instruction packet
|
||||
|
||||
4:
|
||||
jumpr lr
|
||||
# CHECK-NOT: rror: invalid instruction packet
|
||||
|
||||
f-f-f-f:
|
||||
{
|
||||
r3 = #3
|
||||
r2 = #2
|
||||
r5 = #5
|
||||
r4 = #4
|
||||
}
|
||||
# CHECK-NOT: rror: invalid instruction packet
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
# RUN: not llvm-mc -arch=hexagon -filetype=asm junk123.s 2>%t ; FileCheck %s < %t
|
||||
#
|
||||
|
||||
# CHECK: junk123.s: {{[N|n]}}o such file or directory
|
|
@ -0,0 +1,7 @@
|
|||
# RUN: llvm-mc -arch=hexagon -filetype=obj %s | llvm-objdump -t - | FileCheck %s
|
||||
#
|
||||
|
||||
sym_a:
|
||||
.set sym_d, sym_a + 8
|
||||
# CHECK: 00000000 .text 00000000 sym_a
|
||||
# CHECK: 00000008 .text 00000000 sym_d
|
|
@ -0,0 +1,7 @@
|
|||
# RUN: not llvm-mc -arch=hexagon -filetype=asm %s 2>&1 | FileCheck %s
|
||||
|
||||
# Expect errors here, insn needs to be extended
|
||||
R1 = mpyi(R2, #-256)
|
||||
# CHECK: error:
|
||||
R3 = mpyi(R4, #256)
|
||||
# CHECK: error:
|
|
@ -0,0 +1,10 @@
|
|||
# RUN: llvm-mc -triple hexagon -filetype=obj %s | llvm-objdump -d - | FileCheck %s
|
||||
|
||||
# CHECK: 11 df 75 f1
|
||||
r17 = xor(r21, lr)
|
||||
|
||||
# CHECK: 1d df 35 f3
|
||||
sp = sub(lr, r21)
|
||||
|
||||
# CHECK: 15 c0 3e 71
|
||||
fp.l = #21
|
|
@ -12,6 +12,14 @@ r_hex_b15_pcrel:
|
|||
r_hex_b7_pcrel:
|
||||
{ loop1 (#undefined, #0) }
|
||||
|
||||
# CHECK: R_HEX_LO16
|
||||
r_hex_lo16:
|
||||
{ r0.l = #lo(undefined) }
|
||||
|
||||
# CHECK: R_HEX_HI16
|
||||
r_hex_hi16:
|
||||
{ r0.h = #hi(undefined) }
|
||||
|
||||
# CHECK: R_HEX_32
|
||||
r_hex_32:
|
||||
.word undefined
|
||||
|
@ -68,10 +76,6 @@ r_hex_b22_pcrel_x:
|
|||
r_hex_b15_pcrel_x:
|
||||
{ if (p0) jump ##undefined }
|
||||
|
||||
# CHECK: R_HEX_B9_PCREL_X
|
||||
r_hex_b9_pcrel_x:
|
||||
{ r0 = #0 ; jump ##undefined }
|
||||
|
||||
# CHECK: R_HEX_B7_PCREL_X
|
||||
r_hex_b7_pcrel_x:
|
||||
{ loop1 (##undefined, #0) }
|
||||
|
|
Loading…
Reference in New Issue