diff options
author | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2017-02-06 19:35:46 +0000 |
---|---|---|
committer | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2017-02-06 19:35:46 +0000 |
commit | f0711c57126a349ad6b2c8b4f0773545c2302f69 (patch) | |
tree | f7b40a7f162904535487e5a167d93c404d511940 | |
parent | bc8099138a78ce2b34f64f9490a1cb51c583dd38 (diff) | |
download | llvm-f0711c57126a349ad6b2c8b4f0773545c2302f69.tar.gz |
[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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294226 91177308-0d34-0410-b5e6-96231b3b80d8
35 files changed, 1236 insertions, 714 deletions
diff --git a/lib/Target/Hexagon/Hexagon.td b/lib/Target/Hexagon/Hexagon.td index 0b2b46387b6..d310c0243e7 100644 --- a/lib/Target/Hexagon/Hexagon.td +++ b/lib/Target/Hexagon/Hexagon.td @@ -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 diff --git a/lib/Target/Hexagon/HexagonInstrFormats.td b/lib/Target/Hexagon/HexagonInstrFormats.td index fa3cccbd087..7b6610b8e1a 100644 --- a/lib/Target/Hexagon/HexagonInstrFormats.td +++ b/lib/Target/Hexagon/HexagonInstrFormats.td @@ -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 *** } diff --git a/lib/Target/Hexagon/HexagonInstrFormatsV4.td b/lib/Target/Hexagon/HexagonInstrFormatsV4.td index a00cf8d6a4b..7370c6a5767 100644 --- a/lib/Target/Hexagon/HexagonInstrFormatsV4.td +++ b/lib/Target/Hexagon/HexagonInstrFormatsV4.td @@ -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> diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp index 3bc238e84e2..cb7d450c3c5 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp @@ -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); } diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h index 4af8b327ffd..950fff12dba 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h @@ -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. diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp index c619c36164c..446b3b2ce66 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp @@ -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; } diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp index 07c9ad96a0d..51aba946183 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp @@ -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()); diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h index 33e22798c95..c3b3d4c14c8 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h @@ -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); }; diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp index 18a408ed89e..eab6a3c58b6 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp @@ -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))) { diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCompound.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCompound.cpp index 9a09a17767a..ffa980ca656 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCompound.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCompound.cpp @@ -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; + } + } } diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp index 413f052aa4b..e8f154a1fa5 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp @@ -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()), diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp index 226470cfbce..09819ccedd8 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp @@ -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 diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.h index 0ac1a68d4ef..5cb84a48a31 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.h @@ -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 diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp index e93906a0a39..14300edc7e1 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp @@ -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; -}
\ No newline at end of file +} diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp index 74c007c9a59..d756d1bd45c 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp @@ -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) { - // 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; + bool CheckOk = Check ? Check->check(false) : true; if (!CheckOk) return false; - HexagonMCShuffle(MCII, STI, MCB); + // Examine the packet and convert pairs of instructions to compound + // instructions when possible. + if (!HexagonDisableCompound) + 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; + + assert(HexagonMCInstrInfo::isExtendable(MCII, MCI) || + HexagonMCInstrInfo::isExtended(MCII, MCI)); - if (isSigned) // if value is signed - return ~(-1U << (bits - 1)); + 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; + + assert(HexagonMCInstrInfo::isExtendable(MCII, MCI) || + HexagonMCInstrInfo::isExtended(MCII, MCI)); - if (isSigned) // if value is signed - return -1U << (bits - 1); + 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,13 +370,39 @@ unsigned HexagonMCInstrInfo::getUnits(MCInstrInfo const &MCII, return ((II[SchedClass].FirstStage + HexagonStages)->getUnits()); } -bool HexagonMCInstrInfo::hasImmExt(MCInst const &MCI) { +/// 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 (isImmext(*MI)) + if (HexagonMCInstrInfo::isDuplex(MCII, *MI)) return true; } @@ -394,7 +413,20 @@ bool HexagonMCInstrInfo::hasExtenderForIndex(MCInst const &MCB, size_t Index) { return extenderForIndex(MCB, Index) != nullptr; } -// Return whether the instruction is a legal new-value producer. +bool HexagonMCInstrInfo::hasImmExt(MCInst const &MCI) { + if (!HexagonMCInstrInfo::isBundle(MCI)) + return false; + + for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCI)) { + auto MI = I.getInst(); + if (isImmext(*MI)) + return true; + } + + return false; +} + +/// 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, diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h index d701c3ade69..83b859af57b 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h @@ -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,16 +64,6 @@ bool canonicalizePacket(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCContext &Context, MCInst &MCB, HexagonMCChecker *Checker); -// Clamp off upper 26 bits of extendable operand for emission -void clampExtended(MCInstrInfo const &MCII, MCContext &Context, MCInst &MCI); - -MCInst createBundle(); - -// Return the extender for instruction at Index or nullptr if none -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); @@ -86,27 +73,28 @@ MCInst deriveExtender(MCInstrInfo const &MCII, MCInst const &Inst, // 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); + +MCInst createBundle(); + // Return the extender for instruction at Index or nullptr if none MCInst const *extenderForIndex(MCInst const &MCB, size_t Index); +void extendIfNeeded(MCContext &Context, MCInstrInfo const &MCII, MCInst &MCB, + MCInst const &MCI); // 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); } } diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp index 7f8e7a4edb0..3db645b5769 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp @@ -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) { diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h index a21cce1fc24..14bbfda4c91 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h @@ -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>); diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp index 694cf582f8d..52c61eb6e5d 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp @@ -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; -} - -static MCRegisterInfo *createHexagonMCRegisterInfo(const Triple &TT) { - MCRegisterInfo *X = new MCRegisterInfo(); - InitHexagonMCRegisterInfo(X, Hexagon::R31); - return X; +unsigned HexagonGetLastSlot() { + return HexagonItinerariesV4FU::SLOT3; } -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: + MCELFStreamer &getStreamer() { + return static_cast<MCELFStreamer &>(Streamer); + } 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); + MCAssembler &MCA = getStreamer().getAssembler(); + MCA.setELFHeaderEFlags(Hexagon_MC::GetELFFlags(STI)); } - MCELFStreamer &getStreamer() { - return static_cast<MCELFStreamer &>(Streamer); - } 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); } diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h index 6e677e9d9f8..82758a92004 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h @@ -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. diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp index 88f37d620dc..1bf04dd9b8e 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp @@ -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(); - - 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)) { + MCInst const &ID = ISJ->getDesc(); + + 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,27 +333,51 @@ 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; } + } } // Check if the packet is legal. @@ -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'); diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h index a093f854513..209a0e61ead 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h @@ -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; }; diff --git a/test/MC/Hexagon/common-redeclare.s b/test/MC/Hexagon/common-redeclare.s new file mode 100644 index 00000000000..52b77992a87 --- /dev/null +++ b/test/MC/Hexagon/common-redeclare.s @@ -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 diff --git a/test/MC/Hexagon/dcfetch-symbol.s b/test/MC/Hexagon/dcfetch-symbol.s new file mode 100644 index 00000000000..8309439a2aa --- /dev/null +++ b/test/MC/Hexagon/dcfetch-symbol.s @@ -0,0 +1,8 @@ +# RUN: not llvm-mc -arch=hexagon -filetype=obj %s + +#CHECK: 9400c000 { dcfetch(r0 + #0) } + +junk: +{ + dcfetch(r0 + #junk) +} diff --git a/test/MC/Hexagon/dis-duplex-p0.s b/test/MC/Hexagon/dis-duplex-p0.s index dc6a1260145..4ee518fa2a3 100644 --- a/test/MC/Hexagon/dis-duplex-p0.s +++ b/test/MC/Hexagon/dis-duplex-p0.s @@ -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 diff --git a/test/MC/Hexagon/equ.s b/test/MC/Hexagon/equ.s new file mode 100644 index 00000000000..fbf09edbbc1 --- /dev/null +++ b/test/MC/Hexagon/equ.s @@ -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' + diff --git a/test/MC/Hexagon/extended_relocations.ll b/test/MC/Hexagon/extended_relocations.ll new file mode 100644 index 00000000000..a16185c3994 --- /dev/null +++ b/test/MC/Hexagon/extended_relocations.ll @@ -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" } + diff --git a/test/MC/Hexagon/missing_label.s b/test/MC/Hexagon/missing_label.s new file mode 100644 index 00000000000..80f69472029 --- /dev/null +++ b/test/MC/Hexagon/missing_label.s @@ -0,0 +1,8 @@ +# RUN: llvm-mc -arch=hexagon -filetype=obj %s | llvm-objdump -d - | FileCheck %s +# + +.I1: +nop + +# CHECK: .I1: +# CHECK: nop diff --git a/test/MC/Hexagon/non-relocatable.s b/test/MC/Hexagon/non-relocatable.s new file mode 100644 index 00000000000..72a17901c62 --- /dev/null +++ b/test/MC/Hexagon/non-relocatable.s @@ -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: + diff --git a/test/MC/Hexagon/not-over.s b/test/MC/Hexagon/not-over.s new file mode 100644 index 00000000000..c31ce531230 --- /dev/null +++ b/test/MC/Hexagon/not-over.s @@ -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 + diff --git a/test/MC/Hexagon/not_found.s b/test/MC/Hexagon/not_found.s new file mode 100644 index 00000000000..2403042792d --- /dev/null +++ b/test/MC/Hexagon/not_found.s @@ -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 diff --git a/test/MC/Hexagon/offset.s b/test/MC/Hexagon/offset.s new file mode 100644 index 00000000000..b079634814d --- /dev/null +++ b/test/MC/Hexagon/offset.s @@ -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 diff --git a/test/MC/Hexagon/operand-range.s b/test/MC/Hexagon/operand-range.s new file mode 100644 index 00000000000..c38aab7060d --- /dev/null +++ b/test/MC/Hexagon/operand-range.s @@ -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: diff --git a/test/MC/Hexagon/reg_altnames.s b/test/MC/Hexagon/reg_altnames.s new file mode 100644 index 00000000000..9c7f7e9b0bf --- /dev/null +++ b/test/MC/Hexagon/reg_altnames.s @@ -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 diff --git a/test/MC/Hexagon/relocations.s b/test/MC/Hexagon/relocations.s index d52c37a66cc..4acc8084ae6 100644 --- a/test/MC/Hexagon/relocations.s +++ b/test/MC/Hexagon/relocations.s @@ -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) } |