From: Colin LeMahieu Date: Mon, 8 Jun 2015 16:34:47 +0000 (+0000) Subject: [Hexagon] Adding functionality for searching for compound instruction pairs. Compoun... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=838271c858c35f4aa0622c52b549074318e18f4e;p=oota-llvm.git [Hexagon] Adding functionality for searching for compound instruction pairs. Compound instructions reduce slot resource requirements freeing those packet slots up for more instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239307 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/lib/Target/Hexagon/HexagonAsmPrinter.cpp index 45d953ff40a..93ae7ef876c 100644 --- a/lib/Target/Hexagon/HexagonAsmPrinter.cpp +++ b/lib/Target/Hexagon/HexagonAsmPrinter.cpp @@ -200,11 +200,17 @@ void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { HexagonLowerToMC(MI, MCB, *this); HexagonMCInstrInfo::padEndloop(MCB); } + // Examine the packet and try to find instructions that can be converted + // to compounds. + HexagonMCInstrInfo::tryCompound(*Subtarget->getInstrInfo(), + OutStreamer->getContext(), MCB); // Examine the packet and convert pairs of instructions to duplex // instructions when possible. SmallVector possibleDuplexes; - possibleDuplexes = HexagonMCInstrInfo::getDuplexPossibilties(*Subtarget->getInstrInfo(), MCB); - HexagonMCShuffle(*Subtarget->getInstrInfo(), *Subtarget, OutStreamer->getContext(), MCB, possibleDuplexes); + possibleDuplexes = HexagonMCInstrInfo::getDuplexPossibilties( + *Subtarget->getInstrInfo(), MCB); + HexagonMCShuffle(*Subtarget->getInstrInfo(), *Subtarget, + OutStreamer->getContext(), MCB, possibleDuplexes); EmitToStreamer(*OutStreamer, MCB); } diff --git a/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt b/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt index d0fae8a5192..6253686b499 100644 --- a/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt @@ -4,6 +4,7 @@ add_llvm_library(LLVMHexagonDesc HexagonInstPrinter.cpp HexagonMCAsmInfo.cpp HexagonMCCodeEmitter.cpp + HexagonMCCompound.cpp HexagonMCDuplexInfo.cpp HexagonMCInstrInfo.cpp HexagonMCShuffler.cpp diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h index 4f84e0d79e6..f4d162ccf6a 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h @@ -202,6 +202,14 @@ namespace HexagonII { HSIG_Compound }; + // Hexagon Compound classes. + enum CompoundGroup { + HCG_None = 0, + HCG_A, + HCG_B, + HCG_C + }; + enum InstParseBits { INST_PARSE_MASK = 0x0000c000, INST_PARSE_PACKET_END = 0x0000c000, diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCompound.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCompound.cpp new file mode 100644 index 00000000000..108093547f8 --- /dev/null +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCompound.cpp @@ -0,0 +1,420 @@ + +//=== HexagonMCCompound.cpp - Hexagon Compound checker -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is looks at a packet and tries to form compound insns +// +//===----------------------------------------------------------------------===// +#include "Hexagon.h" +#include "MCTargetDesc/HexagonBaseInfo.h" +#include "MCTargetDesc/HexagonMCShuffler.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; +using namespace Hexagon; + +#define DEBUG_TYPE "hexagon-mccompound" + +enum OpcodeIndex { + fp0_jump_nt = 0, + fp0_jump_t, + fp1_jump_nt, + fp1_jump_t, + tp0_jump_nt, + tp0_jump_t, + tp1_jump_nt, + tp1_jump_t +}; + +unsigned tstBitOpcode[8] = {J4_tstbit0_fp0_jump_nt, J4_tstbit0_fp0_jump_t, + J4_tstbit0_fp1_jump_nt, J4_tstbit0_fp1_jump_t, + J4_tstbit0_tp0_jump_nt, J4_tstbit0_tp0_jump_t, + J4_tstbit0_tp1_jump_nt, J4_tstbit0_tp1_jump_t}; +unsigned cmpeqBitOpcode[8] = {J4_cmpeq_fp0_jump_nt, J4_cmpeq_fp0_jump_t, + J4_cmpeq_fp1_jump_nt, J4_cmpeq_fp1_jump_t, + J4_cmpeq_tp0_jump_nt, J4_cmpeq_tp0_jump_t, + J4_cmpeq_tp1_jump_nt, J4_cmpeq_tp1_jump_t}; +unsigned cmpgtBitOpcode[8] = {J4_cmpgt_fp0_jump_nt, J4_cmpgt_fp0_jump_t, + J4_cmpgt_fp1_jump_nt, J4_cmpgt_fp1_jump_t, + J4_cmpgt_tp0_jump_nt, J4_cmpgt_tp0_jump_t, + J4_cmpgt_tp1_jump_nt, J4_cmpgt_tp1_jump_t}; +unsigned cmpgtuBitOpcode[8] = {J4_cmpgtu_fp0_jump_nt, J4_cmpgtu_fp0_jump_t, + J4_cmpgtu_fp1_jump_nt, J4_cmpgtu_fp1_jump_t, + J4_cmpgtu_tp0_jump_nt, J4_cmpgtu_tp0_jump_t, + J4_cmpgtu_tp1_jump_nt, J4_cmpgtu_tp1_jump_t}; +unsigned cmpeqiBitOpcode[8] = {J4_cmpeqi_fp0_jump_nt, J4_cmpeqi_fp0_jump_t, + J4_cmpeqi_fp1_jump_nt, J4_cmpeqi_fp1_jump_t, + J4_cmpeqi_tp0_jump_nt, J4_cmpeqi_tp0_jump_t, + J4_cmpeqi_tp1_jump_nt, J4_cmpeqi_tp1_jump_t}; +unsigned cmpgtiBitOpcode[8] = {J4_cmpgti_fp0_jump_nt, J4_cmpgti_fp0_jump_t, + J4_cmpgti_fp1_jump_nt, J4_cmpgti_fp1_jump_t, + J4_cmpgti_tp0_jump_nt, J4_cmpgti_tp0_jump_t, + J4_cmpgti_tp1_jump_nt, J4_cmpgti_tp1_jump_t}; +unsigned cmpgtuiBitOpcode[8] = {J4_cmpgtui_fp0_jump_nt, J4_cmpgtui_fp0_jump_t, + J4_cmpgtui_fp1_jump_nt, J4_cmpgtui_fp1_jump_t, + J4_cmpgtui_tp0_jump_nt, J4_cmpgtui_tp0_jump_t, + J4_cmpgtui_tp1_jump_nt, J4_cmpgtui_tp1_jump_t}; +unsigned cmpeqn1BitOpcode[8] = {J4_cmpeqn1_fp0_jump_nt, J4_cmpeqn1_fp0_jump_t, + J4_cmpeqn1_fp1_jump_nt, J4_cmpeqn1_fp1_jump_t, + J4_cmpeqn1_tp0_jump_nt, J4_cmpeqn1_tp0_jump_t, + J4_cmpeqn1_tp1_jump_nt, J4_cmpeqn1_tp1_jump_t}; +unsigned cmpgtn1BitOpcode[8] = { + J4_cmpgtn1_fp0_jump_nt, J4_cmpgtn1_fp0_jump_t, J4_cmpgtn1_fp1_jump_nt, + J4_cmpgtn1_fp1_jump_t, J4_cmpgtn1_tp0_jump_nt, J4_cmpgtn1_tp0_jump_t, + J4_cmpgtn1_tp1_jump_nt, J4_cmpgtn1_tp1_jump_t, +}; + +// enum HexagonII::CompoundGroup +namespace { +unsigned getCompoundCandidateGroup(MCInst const &MI, bool IsExtended) { + unsigned DstReg, SrcReg, Src1Reg, Src2Reg; + + switch (MI.getOpcode()) { + default: + return HexagonII::HCG_None; + // + // Compound pairs. + // "p0=cmp.eq(Rs16,Rt16); if (p0.new) jump:nt #r9:2" + // "Rd16=#U6 ; jump #r9:2" + // "Rd16=Rs16 ; jump #r9:2" + // + case Hexagon::C2_cmpeq: + case Hexagon::C2_cmpgt: + case Hexagon::C2_cmpgtu: + if (IsExtended) + return false; + DstReg = MI.getOperand(0).getReg(); + Src1Reg = MI.getOperand(1).getReg(); + Src2Reg = MI.getOperand(2).getReg(); + if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) && + HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) && + HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg)) + return HexagonII::HCG_A; + break; + case Hexagon::C2_cmpeqi: + case Hexagon::C2_cmpgti: + case Hexagon::C2_cmpgtui: + if (IsExtended) + return false; + // P0 = cmp.eq(Rs,#u2) + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(1).getReg(); + if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) && + HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) && + MI.getOperand(2).isImm() && ((isUInt<5>(MI.getOperand(2).getImm())) || + (MI.getOperand(2).getImm() == -1))) + return HexagonII::HCG_A; + break; + case Hexagon::A2_tfr: + if (IsExtended) + return false; + // Rd = Rs + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(1).getReg(); + if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) && + HexagonMCInstrInfo::isIntRegForSubInst(SrcReg)) + return HexagonII::HCG_A; + break; + case Hexagon::A2_tfrsi: + if (IsExtended) + return false; + // Rd = #u6 + DstReg = MI.getOperand(0).getReg(); + if (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() <= 63 && + MI.getOperand(1).getImm() >= 0 && + HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) + return HexagonII::HCG_A; + break; + case Hexagon::S2_tstbit_i: + if (IsExtended) + return false; + DstReg = MI.getOperand(0).getReg(); + Src1Reg = MI.getOperand(1).getReg(); + if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) && + MI.getOperand(2).isImm() && + HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) && + (MI.getOperand(2).getImm() == 0)) + return HexagonII::HCG_A; + break; + // The fact that .new form is used pretty much guarantees + // that predicate register will match. Nevertheless, + // there could be some false positives without additional + // checking. + case Hexagon::J2_jumptnew: + case Hexagon::J2_jumpfnew: + case Hexagon::J2_jumptnewpt: + case Hexagon::J2_jumpfnewpt: + Src1Reg = MI.getOperand(0).getReg(); + if (Hexagon::P0 == Src1Reg || Hexagon::P1 == Src1Reg) + return HexagonII::HCG_B; + break; + // Transfer and jump: + // Rd=#U6 ; jump #r9:2 + // Rd=Rs ; jump #r9:2 + // Do not test for jump range here. + case Hexagon::J2_jump: + case Hexagon::RESTORE_DEALLOC_RET_JMP_V4: + return HexagonII::HCG_C; + break; + } + + return HexagonII::HCG_None; +} +} + +/// getCompoundOp - Return the index from 0-7 into the above opcode lists. +namespace { +unsigned getCompoundOp(MCInst const &HMCI) { + const MCOperand &Predicate = HMCI.getOperand(0); + unsigned PredReg = Predicate.getReg(); + + assert((PredReg == Hexagon::P0) || (PredReg == Hexagon::P1) || + (PredReg == Hexagon::P2) || (PredReg == Hexagon::P3)); + + switch (HMCI.getOpcode()) { + default: + llvm_unreachable("Expected match not found.\n"); + break; + case Hexagon::J2_jumpfnew: + return (PredReg == Hexagon::P0) ? fp0_jump_nt : fp1_jump_nt; + case Hexagon::J2_jumpfnewpt: + return (PredReg == Hexagon::P0) ? fp0_jump_t : fp1_jump_t; + case Hexagon::J2_jumptnew: + return (PredReg == Hexagon::P0) ? tp0_jump_nt : tp1_jump_nt; + case Hexagon::J2_jumptnewpt: + return (PredReg == Hexagon::P0) ? tp0_jump_t : tp1_jump_t; + } +} +} + +namespace { +MCInst *getCompoundInsn(MCContext &Context, MCInst const &L, MCInst const &R) { + MCInst *CompoundInsn = 0; + unsigned compoundOpcode; + MCOperand Rs, Rt; + + switch (L.getOpcode()) { + default: + DEBUG(dbgs() << "Possible compound ignored\n"); + return CompoundInsn; + + case Hexagon::A2_tfrsi: + Rt = L.getOperand(0); + compoundOpcode = J4_jumpseti; + CompoundInsn = new (Context) MCInst; + CompoundInsn->setOpcode(compoundOpcode); + + CompoundInsn->addOperand(Rt); + CompoundInsn->addOperand(L.getOperand(1)); // Immediate + CompoundInsn->addOperand(R.getOperand(0)); // Jump target + break; + + case Hexagon::A2_tfr: + Rt = L.getOperand(0); + Rs = L.getOperand(1); + + compoundOpcode = J4_jumpsetr; + CompoundInsn = new (Context) MCInst; + CompoundInsn->setOpcode(compoundOpcode); + CompoundInsn->addOperand(Rt); + CompoundInsn->addOperand(Rs); + CompoundInsn->addOperand(R.getOperand(0)); // Jump target. + + break; + + case Hexagon::C2_cmpeq: + DEBUG(dbgs() << "CX: C2_cmpeq\n"); + Rs = L.getOperand(1); + Rt = L.getOperand(2); + + compoundOpcode = cmpeqBitOpcode[getCompoundOp(R)]; + CompoundInsn = new (Context) MCInst; + CompoundInsn->setOpcode(compoundOpcode); + CompoundInsn->addOperand(Rs); + CompoundInsn->addOperand(Rt); + CompoundInsn->addOperand(R.getOperand(1)); + break; + + case Hexagon::C2_cmpgt: + DEBUG(dbgs() << "CX: C2_cmpgt\n"); + Rs = L.getOperand(1); + Rt = L.getOperand(2); + + compoundOpcode = cmpgtBitOpcode[getCompoundOp(R)]; + CompoundInsn = new (Context) MCInst; + CompoundInsn->setOpcode(compoundOpcode); + CompoundInsn->addOperand(Rs); + CompoundInsn->addOperand(Rt); + CompoundInsn->addOperand(R.getOperand(1)); + break; + + case Hexagon::C2_cmpgtu: + DEBUG(dbgs() << "CX: C2_cmpgtu\n"); + Rs = L.getOperand(1); + Rt = L.getOperand(2); + + compoundOpcode = cmpgtuBitOpcode[getCompoundOp(R)]; + CompoundInsn = new (Context) MCInst; + CompoundInsn->setOpcode(compoundOpcode); + CompoundInsn->addOperand(Rs); + CompoundInsn->addOperand(Rt); + CompoundInsn->addOperand(R.getOperand(1)); + break; + + case Hexagon::C2_cmpeqi: + DEBUG(dbgs() << "CX: C2_cmpeqi\n"); + if (L.getOperand(2).getImm() == -1) + compoundOpcode = cmpeqn1BitOpcode[getCompoundOp(R)]; + else + compoundOpcode = cmpeqiBitOpcode[getCompoundOp(R)]; + + Rs = L.getOperand(1); + CompoundInsn = new (Context) MCInst; + CompoundInsn->setOpcode(compoundOpcode); + CompoundInsn->addOperand(Rs); + if (L.getOperand(2).getImm() != -1) + CompoundInsn->addOperand(L.getOperand(2)); + CompoundInsn->addOperand(R.getOperand(1)); + break; + + case Hexagon::C2_cmpgti: + DEBUG(dbgs() << "CX: C2_cmpgti\n"); + if (L.getOperand(2).getImm() == -1) + compoundOpcode = cmpgtn1BitOpcode[getCompoundOp(R)]; + else + compoundOpcode = cmpgtiBitOpcode[getCompoundOp(R)]; + + Rs = L.getOperand(1); + CompoundInsn = new (Context) MCInst; + CompoundInsn->setOpcode(compoundOpcode); + CompoundInsn->addOperand(Rs); + if (L.getOperand(2).getImm() != -1) + CompoundInsn->addOperand(L.getOperand(2)); + CompoundInsn->addOperand(R.getOperand(1)); + break; + + case Hexagon::C2_cmpgtui: + DEBUG(dbgs() << "CX: C2_cmpgtui\n"); + Rs = L.getOperand(1); + compoundOpcode = cmpgtuiBitOpcode[getCompoundOp(R)]; + CompoundInsn = new (Context) MCInst; + CompoundInsn->setOpcode(compoundOpcode); + CompoundInsn->addOperand(Rs); + CompoundInsn->addOperand(L.getOperand(2)); + CompoundInsn->addOperand(R.getOperand(1)); + break; + + case Hexagon::S2_tstbit_i: + DEBUG(dbgs() << "CX: S2_tstbit_i\n"); + Rs = L.getOperand(1); + compoundOpcode = tstBitOpcode[getCompoundOp(R)]; + CompoundInsn = new (Context) MCInst; + CompoundInsn->setOpcode(compoundOpcode); + CompoundInsn->addOperand(Rs); + CompoundInsn->addOperand(R.getOperand(1)); + break; + } + + return CompoundInsn; +} +} + +/// Non-Symmetrical. See if these two instructions are fit for compound pair. +namespace { +bool isOrderedCompoundPair(MCInst const &MIa, bool IsExtendedA, + MCInst const &MIb, bool IsExtendedB) { + unsigned MIaG = getCompoundCandidateGroup(MIa, IsExtendedA); + unsigned MIbG = getCompoundCandidateGroup(MIb, IsExtendedB); + // We have two candidates - check that this is the same register + // we are talking about. + unsigned Opca = MIa.getOpcode(); + if (MIaG == HexagonII::HCG_A && MIbG == HexagonII::HCG_C && + (Opca == Hexagon::A2_tfr || Opca == Hexagon::A2_tfrsi)) + return true; + return ((MIaG == HexagonII::HCG_A && MIbG == HexagonII::HCG_B) && + (MIa.getOperand(0).getReg() == MIb.getOperand(0).getReg())); +} +} + +namespace { +bool lookForCompound(MCInstrInfo const &MCII, MCContext &Context, MCInst &MCI) { + assert(HexagonMCInstrInfo::isBundle(MCI)); + bool JExtended = false; + for (MCInst::iterator J = + MCI.begin() + HexagonMCInstrInfo::bundleInstructionsOffset; + J != MCI.end(); ++J) { + MCInst const *JumpInst = J->getInst(); + if (HexagonMCInstrInfo::isImmext(*JumpInst)) { + JExtended = true; + continue; + } + if (llvm::HexagonMCInstrInfo::getType(MCII, *JumpInst) == + HexagonII::TypeJ) { + // Try to pair with another insn (B)undled with jump. + bool BExtended = false; + for (MCInst::iterator B = + MCI.begin() + HexagonMCInstrInfo::bundleInstructionsOffset; + B != MCI.end(); ++B) { + MCInst const *Inst = B->getInst(); + if (JumpInst == Inst) + continue; + if (HexagonMCInstrInfo::isImmext(*Inst)) { + BExtended = true; + continue; + } + DEBUG(dbgs() << "J,B: " << JumpInst->getOpcode() << "," + << Inst->getOpcode() << "\n"); + if (isOrderedCompoundPair(*Inst, BExtended, *JumpInst, JExtended)) { + MCInst *CompoundInsn = getCompoundInsn(Context, *Inst, *JumpInst); + if (CompoundInsn) { + DEBUG(dbgs() << "B: " << Inst->getOpcode() << "," + << JumpInst->getOpcode() << " Compounds to " + << CompoundInsn->getOpcode() << "\n"); + J->setInst(CompoundInsn); + MCI.erase(B); + return true; + } + } + BExtended = false; + } + } + JExtended = false; + } + return false; +} +} + +/// tryCompound - Given a bundle check for compound insns when one +/// 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, + MCContext &Context, MCInst &MCI) { + assert(MCI.getOpcode() == Hexagon::BUNDLE && + "Non-Bundle where Bundle expected"); + + // By definition a compound must have 2 insn. + if (MCI.size() < 2) + return; + + // Look for compounds until none are found, only update the bundle when + // a compound is found. + while (lookForCompound(MCII, Context, MCI)) + ; + + return; +} diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h index f09dfd8cf47..09f305f638e 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h @@ -223,6 +223,9 @@ void setOuterLoop(MCInst &MCI); // Would duplexing this instruction create a requirement to extend bool subInstWouldBeExtended(MCInst const &potentialDuplex); + +// Attempt to find and replace compound pairs +void tryCompound(MCInstrInfo const &MCII, MCContext &Context, MCInst &MCI); } } diff --git a/test/CodeGen/Hexagon/compound.ll b/test/CodeGen/Hexagon/compound.ll new file mode 100644 index 00000000000..f8d36b8b77d --- /dev/null +++ b/test/CodeGen/Hexagon/compound.ll @@ -0,0 +1,17 @@ +; RUN: llc -march=hexagon -filetype=obj -o - %s | llvm-objdump -d - | FileCheck %s + +; CHECK: p0 = cmp.gt(r0,#-1); if (!p0.new) jump:nt + +declare void @a() +declare void @b() + +define void @foo(i32 %a) { +%b = icmp sgt i32 %a, -1 +br i1 %b, label %x, label %y +x: +call void @a() +ret void +y: +call void @b() +ret void +} \ No newline at end of file