llvm/llvm/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp

//===- HexagonPacketizer.cpp - VLIW packetizer ----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This implements a simple VLIW packetizer using DFA. The packetizer works on
// machine basic blocks. For each instruction I in BB, the packetizer consults
// the DFA to see if machine resources are available to execute I. If so, the
// packetizer checks if I depends on any instruction J in the current packet.
// If no dependency is found, I is added to current packet and machine resource
// is marked as taken. If any dependency is found, a target API call is made to
// prune the dependence.
//
//===----------------------------------------------------------------------===//

#include "HexagonVLIWPacketizer.h"
#include "Hexagon.h"
#include "HexagonInstrInfo.h"
#include "HexagonRegisterInfo.h"
#include "HexagonSubtarget.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/InitializePasses.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
#include <iterator>

usingnamespacellvm;

#define DEBUG_TYPE

static cl::opt<bool>
    DisablePacketizer("disable-packetizer", cl::Hidden,
                      cl::desc("Disable Hexagon packetizer pass"));

static cl::opt<bool> Slot1Store("slot1-store-slot0-load", cl::Hidden,
                                cl::init(true),
                                cl::desc("Allow slot1 store and slot0 load"));

static cl::opt<bool> PacketizeVolatiles(
    "hexagon-packetize-volatiles", cl::Hidden, cl::init(true),
    cl::desc("Allow non-solo packetization of volatile memory references"));

static cl::opt<bool>
    EnableGenAllInsnClass("enable-gen-insn", cl::Hidden,
                          cl::desc("Generate all instruction with TC"));

static cl::opt<bool>
    DisableVecDblNVStores("disable-vecdbl-nv-stores", cl::Hidden,
                          cl::desc("Disable vector double new-value-stores"));

extern cl::opt<bool> ScheduleInlineAsm;

namespace llvm {

FunctionPass *createHexagonPacketizer(bool Minimal);
void initializeHexagonPacketizerPass(PassRegistry&);

} // end namespace llvm

namespace {

  class HexagonPacketizer : public MachineFunctionPass {};

} // end anonymous namespace

char HexagonPacketizer::ID =;

INITIALIZE_PASS_BEGIN(HexagonPacketizer, "hexagon-packetizer",
                      "Hexagon Packetizer", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_END(HexagonPacketizer, "hexagon-packetizer",
                    "Hexagon Packetizer", false, false)

HexagonPacketizerList::HexagonPacketizerList(MachineFunction &MF,
      MachineLoopInfo &MLI, AAResults *AA,
      const MachineBranchProbabilityInfo *MBPI, bool Minimal)
    :{}

// Check if FirstI modifies a register that SecondI reads.
static bool hasWriteToReadDep(const MachineInstr &FirstI,
                              const MachineInstr &SecondI,
                              const TargetRegisterInfo *TRI) {}


static MachineBasicBlock::iterator moveInstrOut(MachineInstr &MI,
      MachineBasicBlock::iterator BundleIt, bool Before) {}

bool HexagonPacketizer::runOnMachineFunction(MachineFunction &MF) {}

// Reserve resources for a constant extender. Trigger an assertion if the
// reservation fails.
void HexagonPacketizerList::reserveResourcesForConstExt() {}

bool HexagonPacketizerList::canReserveResourcesForConstExt() {}

// Allocate resources (i.e. 4 bytes) for constant extender. If succeeded,
// return true, otherwise, return false.
bool HexagonPacketizerList::tryAllocateResourcesForConstExt(bool Reserve) {}

bool HexagonPacketizerList::isCallDependent(const MachineInstr &MI,
      SDep::Kind DepType, unsigned DepReg) {}

static bool isRegDependence(const SDep::Kind DepType) {}

static bool isDirectJump(const MachineInstr &MI) {}

static bool isSchedBarrier(const MachineInstr &MI) {}

static bool isControlFlow(const MachineInstr &MI) {}

/// Returns true if the instruction modifies a callee-saved register.
static bool doesModifyCalleeSavedReg(const MachineInstr &MI,
                                     const TargetRegisterInfo *TRI) {}

// Returns true if an instruction can be promoted to .new predicate or
// new-value store.
bool HexagonPacketizerList::isNewifiable(const MachineInstr &MI,
      const TargetRegisterClass *NewRC) {}

// Promote an instructiont to its .cur form.
// At this time, we have already made a call to canPromoteToDotCur and made
// sure that it can *indeed* be promoted.
bool HexagonPacketizerList::promoteToDotCur(MachineInstr &MI,
      SDep::Kind DepType, MachineBasicBlock::iterator &MII,
      const TargetRegisterClass* RC) {}

void HexagonPacketizerList::cleanUpDotCur() {}

// Check to see if an instruction can be dot cur.
bool HexagonPacketizerList::canPromoteToDotCur(const MachineInstr &MI,
      const SUnit *PacketSU, unsigned DepReg, MachineBasicBlock::iterator &MII,
      const TargetRegisterClass *RC) {}

// Promote an instruction to its .new form. At this time, we have already
// made a call to canPromoteToDotNew and made sure that it can *indeed* be
// promoted.
bool HexagonPacketizerList::promoteToDotNew(MachineInstr &MI,
      SDep::Kind DepType, MachineBasicBlock::iterator &MII,
      const TargetRegisterClass* RC) {}

bool HexagonPacketizerList::demoteToDotOld(MachineInstr &MI) {}

bool HexagonPacketizerList::useCallersSP(MachineInstr &MI) {}

void HexagonPacketizerList::useCalleesSP(MachineInstr &MI) {}

/// Return true if we can update the offset in MI so that MI and MJ
/// can be packetized together.
bool HexagonPacketizerList::updateOffset(SUnit *SUI, SUnit *SUJ) {}

/// Undo the changed offset. This is needed if the instruction cannot be
/// added to the current packet due to a different instruction.
void HexagonPacketizerList::undoChangedOffset(MachineInstr &MI) {}

enum PredicateKind {};

/// Returns true if an instruction is predicated on p0 and false if it's
/// predicated on !p0.
static PredicateKind getPredicateSense(const MachineInstr &MI,
                                       const HexagonInstrInfo *HII) {}

static const MachineOperand &getPostIncrementOperand(const MachineInstr &MI,
      const HexagonInstrInfo *HII) {}

// Get the value being stored.
static const MachineOperand& getStoreValueOperand(const MachineInstr &MI) {}

static bool isLoadAbsSet(const MachineInstr &MI) {}

static const MachineOperand &getAbsSetOperand(const MachineInstr &MI) {}

// Can be new value store?
// Following restrictions are to be respected in convert a store into
// a new value store.
// 1. If an instruction uses auto-increment, its address register cannot
//    be a new-value register. Arch Spec 5.4.2.1
// 2. If an instruction uses absolute-set addressing mode, its address
//    register cannot be a new-value register. Arch Spec 5.4.2.1.
// 3. If an instruction produces a 64-bit result, its registers cannot be used
//    as new-value registers. Arch Spec 5.4.2.2.
// 4. If the instruction that sets the new-value register is conditional, then
//    the instruction that uses the new-value register must also be conditional,
//    and both must always have their predicates evaluate identically.
//    Arch Spec 5.4.2.3.
// 5. There is an implied restriction that a packet cannot have another store,
//    if there is a new value store in the packet. Corollary: if there is
//    already a store in a packet, there can not be a new value store.
//    Arch Spec: 3.4.4.2
bool HexagonPacketizerList::canPromoteToNewValueStore(const MachineInstr &MI,
      const MachineInstr &PacketMI, unsigned DepReg) {}

// Can this MI to promoted to either new value store or new value jump.
bool HexagonPacketizerList::canPromoteToNewValue(const MachineInstr &MI,
      const SUnit *PacketSU, unsigned DepReg,
      MachineBasicBlock::iterator &MII) {}

static bool isImplicitDependency(const MachineInstr &I, bool CheckDef,
      unsigned DepReg) {}

// Check to see if an instruction can be dot new.
bool HexagonPacketizerList::canPromoteToDotNew(const MachineInstr &MI,
      const SUnit *PacketSU, unsigned DepReg, MachineBasicBlock::iterator &MII,
      const TargetRegisterClass* RC) {}

// Go through the packet instructions and search for an anti dependency between
// them and DepReg from MI. Consider this case:
// Trying to add
// a) %r1 = TFRI_cdNotPt %p3, 2
// to this packet:
// {
//   b) %p0 = C2_or killed %p3, killed %p0
//   c) %p3 = C2_tfrrp %r23
//   d) %r1 = C2_cmovenewit %p3, 4
//  }
// The P3 from a) and d) will be complements after
// a)'s P3 is converted to .new form
// Anti-dep between c) and b) is irrelevant for this case
bool HexagonPacketizerList::restrictingDepExistInPacket(MachineInstr &MI,
                                                        unsigned DepReg) {}

/// Gets the predicate register of a predicated instruction.
static unsigned getPredicatedRegister(MachineInstr &MI,
                                      const HexagonInstrInfo *QII) {}

// Given two predicated instructions, this function detects whether
// the predicates are complements.
bool HexagonPacketizerList::arePredicatesComplements(MachineInstr &MI1,
                                                     MachineInstr &MI2) {}

// Initialize packetizer flags.
void HexagonPacketizerList::initPacketizerState() {}

// Ignore bundling of pseudo instructions.
bool HexagonPacketizerList::ignorePseudoInstruction(const MachineInstr &MI,
                                                    const MachineBasicBlock *) {}

bool HexagonPacketizerList::isSoloInstruction(const MachineInstr &MI) {}

// Quick check if instructions MI and MJ cannot coexist in the same packet.
// Limit the tests to be "one-way", e.g.  "if MI->isBranch and MJ->isInlineAsm",
// but not the symmetric case: "if MJ->isBranch and MI->isInlineAsm".
// For full test call this function twice:
//   cannotCoexistAsymm(MI, MJ) || cannotCoexistAsymm(MJ, MI)
// Doing the test only one way saves the amount of code in this function,
// since every test would need to be repeated with the MI and MJ reversed.
static bool cannotCoexistAsymm(const MachineInstr &MI, const MachineInstr &MJ,
      const HexagonInstrInfo &HII) {}

// Full, symmetric check.
bool HexagonPacketizerList::cannotCoexist(const MachineInstr &MI,
      const MachineInstr &MJ) {}

void HexagonPacketizerList::unpacketizeSoloInstrs(MachineFunction &MF) {}

// Check if a given instruction is of class "system".
static bool isSystemInstr(const MachineInstr &MI) {}

bool HexagonPacketizerList::hasDeadDependence(const MachineInstr &I,
                                              const MachineInstr &J) {}

bool HexagonPacketizerList::hasControlDependence(const MachineInstr &I,
                                                 const MachineInstr &J) {}

bool HexagonPacketizerList::hasRegMaskDependence(const MachineInstr &I,
                                                 const MachineInstr &J) {}

bool HexagonPacketizerList::hasDualStoreDependence(const MachineInstr &I,
                                                   const MachineInstr &J) {}

// SUI is the current instruction that is outside of the current packet.
// SUJ is the current instruction inside the current packet against which that
// SUI will be packetized.
bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) {}

bool HexagonPacketizerList::isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) {}


bool HexagonPacketizerList::foundLSInPacket() {}


MachineBasicBlock::iterator
HexagonPacketizerList::addToPacket(MachineInstr &MI) {}

void HexagonPacketizerList::endPacket(MachineBasicBlock *MBB,
                                      MachineBasicBlock::iterator EndMI) {}

bool HexagonPacketizerList::shouldAddToPacket(const MachineInstr &MI) {}

// V60 forward scheduling.
unsigned int HexagonPacketizerList::calcStall(const MachineInstr &I) {}

bool HexagonPacketizerList::producesStall(const MachineInstr &I) {}

//===----------------------------------------------------------------------===//
//                         Public Constructor Functions
//===----------------------------------------------------------------------===//

FunctionPass *llvm::createHexagonPacketizer(bool Minimal) {}