diff options
-rw-r--r-- | llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp | 86 | ||||
-rw-r--r-- | llvm/test/MC/Hexagon/align.s | 60 |
2 files changed, 129 insertions, 17 deletions
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp index 6ac57dbf079..7d37b42ef4d 100644 --- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp +++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp @@ -11,7 +11,10 @@ #include "HexagonFixupKinds.h" #include "HexagonMCTargetDesc.h" #include "MCTargetDesc/HexagonBaseInfo.h" +#include "MCTargetDesc/HexagonMCChecker.h" +#include "MCTargetDesc/HexagonMCCodeEmitter.h" #include "MCTargetDesc/HexagonMCInstrInfo.h" +#include "MCTargetDesc/HexagonMCShuffler.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" @@ -41,6 +44,19 @@ class HexagonAsmBackend : public MCAsmBackend { std::unique_ptr <MCInstrInfo> MCII; std::unique_ptr <MCInst *> RelaxTarget; MCInst * Extender; + + void ReplaceInstruction(MCCodeEmitter &E, MCRelaxableFragment &RF, + MCInst &HMB) const { + SmallVector<MCFixup, 4> Fixups; + SmallString<256> Code; + raw_svector_ostream VecOS(Code); + E.encodeInstruction(HMB, VecOS, Fixups, RF.getSubtargetInfo()); + + // Update the fragment. + RF.setInst(HMB); + RF.getContents() = Code; + RF.getFixups() = Fixups; + } public: HexagonAsmBackend(const Target &T, uint8_t OSABI, StringRef CPU) : OSABI(OSABI), MCII (T.createMCInstrInfo()), RelaxTarget(new MCInst *), @@ -530,23 +546,7 @@ public: /// /// \param Inst - The instruction to test. bool mayNeedRelaxation(MCInst const &Inst) const override { - assert(HexagonMCInstrInfo::isBundle(Inst)); - bool PreviousIsExtender = false; - for (auto const &I : HexagonMCInstrInfo::bundleInstructions(Inst)) { - auto const &Inst = *I.getInst(); - if (!PreviousIsExtender) { - if (HexagonMCInstrInfo::isDuplex(*MCII, Inst)) { - if (isInstRelaxable(*Inst.getOperand(0).getInst()) || - isInstRelaxable(*Inst.getOperand(1).getInst())) - return true; - } else { - if (isInstRelaxable(Inst)) - return true; - } - } - PreviousIsExtender = HexagonMCInstrInfo::isImmext(Inst); - } - return false; + return true; } /// fixupNeedsRelaxation - Target specific predicate for whether a given @@ -686,6 +686,58 @@ public: } return true; } + + void finishLayout(MCAssembler const &Asm, + MCAsmLayout &Layout) const override { + for (auto I : Layout.getSectionOrder()) { + auto &Fragments = I->getFragmentList(); + for (auto &J : Fragments) { + switch (J.getKind()) { + default: + break; + case MCFragment::FT_Align: { + auto Size = Asm.computeFragmentSize(Layout, J); + for (auto K = J.getIterator(); + K != Fragments.begin() && Size >= HEXAGON_PACKET_SIZE;) { + --K; + switch (K->getKind()) { + default: + break; + case MCFragment::FT_Align: { + // Don't pad before other alignments + Size = 0; + break; + } + case MCFragment::FT_Relaxable: { + auto &RF = cast<MCRelaxableFragment>(*K); + auto &Inst = const_cast<MCInst &>(RF.getInst()); + while (Size > 0 && HexagonMCInstrInfo::bundleSize(Inst) < 4) { + MCInst *Nop = new (Asm.getContext()) MCInst; + Nop->setOpcode(Hexagon::A2_nop); + Inst.addOperand(MCOperand::createInst(Nop)); + Size -= 4; + if (!HexagonMCChecker( + *MCII, RF.getSubtargetInfo(), Inst, Inst, + *Asm.getContext().getRegisterInfo()).check()) { + Inst.erase(Inst.end() - 1); + Size = 0; + } + } + bool Error = HexagonMCShuffle(*MCII, RF.getSubtargetInfo(), Inst); + //assert(!Error); + (void)Error; + ReplaceInstruction(Asm.getEmitter(), RF, Inst); + Layout.invalidateFragmentsFrom(&RF); + Size = 0; // Only look back one instruction + break; + } + } + } + } + } + } + } + } }; } // end anonymous namespace diff --git a/llvm/test/MC/Hexagon/align.s b/llvm/test/MC/Hexagon/align.s new file mode 100644 index 00000000000..01a112392ed --- /dev/null +++ b/llvm/test/MC/Hexagon/align.s @@ -0,0 +1,60 @@ +# RUN: llvm-mc -triple=hexagon -filetype=obj %s | llvm-objdump -d - | FileCheck %s + +# Verify that the .align directive emits the proper insn packets. + +{ r1 = sub(#1, r1) } +# CHECK: 76414021 { r1 = sub(#1, r1) +# CHECK-NEXT: 7f004000 nop +# CHECK-NEXT: 7f004000 nop +# CHECK-NEXT: 7f00c000 nop } + +.align 16 +{ r1 = sub(#1, r1) + r2 = sub(#1, r2) } +# CHECK: 76414021 { r1 = sub(#1, r1) +# CHECK-NEXT: 76424022 r2 = sub(#1, r2) +# CHECK-NEXT: 7f004000 nop +# CHECK-NEXT: 7f00c000 nop } + +.p2align 5 +{ r1 = sub(#1, r1) + r2 = sub(#1, r2) + r3 = sub(#1, r3) } +# CHECK: 76434023 r3 = sub(#1, r3) +# CHECK-NEXT: 7f00c000 nop } + +.align 16 +{ r1 = sub(#1, r1) + r2 = sub(#1, r2) + r3 = sub(#1, r3) + r4 = sub(#1, r4) } + +# Don't pad packets that can't be padded e.g. solo insts +# CHECK: 9200c020 { r0 = vextract(v0,r0) } +r0 = vextract(v0, r0) +.align 128 +# CHECK: 76414021 { r1 = sub(#1, r1) +# CHECK-NEXT: 7f00c000 nop } +{ r1 = sub(#1, r1) } + +#CHECK: { r1 = sub(#1, r1) +#CHECK: r2 = sub(#1, r2) +#CHECK: r3 = sub(#1, r3) } +.falign +.align 8 +{ r1 = sub(#1, r1) + r2 = sub(#1, r2) + r3 = sub(#1, r3) } + +# CHECK: { immext(#0) +# CHECK: r0 = sub(##1, r0) +# CHECK: immext(#0) +# CHECK: r1 = sub(##1, r1) } +# CHECK: { nop +# CHECK: nop +# CHECK: nop } +# CHECK: { r0 = sub(#1, r0) } +{ r0 = sub (##1, r0) + r1 = sub (##1, r1) } +.align 16 +{ r0 = sub (#1, r0) }
\ No newline at end of file |