| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 
 | //===- HexagonVectorPrint.cpp - Generate vector printing instructions -----===//
//
// 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 pass adds the capability to generate pseudo vector/predicate register
// printing instructions. These pseudo instructions should be used with the
// simulator, NEVER on hardware.
//
//===----------------------------------------------------------------------===//
#include "HexagonInstrInfo.h"
#include "HexagonSubtarget.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/InlineAsm.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 <string>
#include <vector>
using namespace llvm;
#define DEBUG_TYPE "hexagon-vector-print"
static cl::opt<bool>
    TraceHexVectorStoresOnly("trace-hex-vector-stores-only", cl::Hidden,
                             cl::desc("Enables tracing of vector stores"));
namespace llvm {
FunctionPass *createHexagonVectorPrint();
void initializeHexagonVectorPrintPass(PassRegistry&);
} // end namespace llvm
namespace {
class HexagonVectorPrint : public MachineFunctionPass {
  const HexagonSubtarget *QST = nullptr;
  const HexagonInstrInfo *QII = nullptr;
  const HexagonRegisterInfo *QRI = nullptr;
public:
  static char ID;
  HexagonVectorPrint() : MachineFunctionPass(ID) {
    initializeHexagonVectorPrintPass(*PassRegistry::getPassRegistry());
  }
  StringRef getPassName() const override { return "Hexagon VectorPrint pass"; }
  bool runOnMachineFunction(MachineFunction &Fn) override;
};
} // end anonymous namespace
char HexagonVectorPrint::ID = 0;
static bool isVecReg(unsigned Reg) {
  return (Reg >= Hexagon::V0 && Reg <= Hexagon::V31) ||
         (Reg >= Hexagon::W0 && Reg <= Hexagon::W15) ||
         (Reg >= Hexagon::WR0 && Reg <= Hexagon::WR15) ||
         (Reg >= Hexagon::Q0 && Reg <= Hexagon::Q3);
}
static std::string getStringReg(unsigned R) {
  if (R >= Hexagon::V0 && R <= Hexagon::V31) {
    static const char* S[] = { "20", "21", "22", "23", "24", "25", "26", "27",
                        "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
                        "30", "31", "32", "33", "34", "35", "36", "37",
                        "38", "39", "3a", "3b", "3c", "3d", "3e", "3f"};
    return S[R-Hexagon::V0];
  }
  if (R >= Hexagon::Q0 && R <= Hexagon::Q3) {
    static const char* S[] = { "00", "01", "02", "03"};
    return S[R-Hexagon::Q0];
  }
  llvm_unreachable("valid vreg");
}
static void addAsmInstr(MachineBasicBlock *MBB, unsigned Reg,
                        MachineBasicBlock::instr_iterator I,
                        const DebugLoc &DL, const HexagonInstrInfo *QII,
                        MachineFunction &Fn) {
  std::string VDescStr = ".long 0x1dffe0" + getStringReg(Reg);
  const char *cstr = Fn.createExternalSymbolName(VDescStr);
  unsigned ExtraInfo = InlineAsm::Extra_HasSideEffects;
  BuildMI(*MBB, I, DL, QII->get(TargetOpcode::INLINEASM))
    .addExternalSymbol(cstr)
    .addImm(ExtraInfo);
}
static bool getInstrVecReg(const MachineInstr &MI, unsigned &Reg) {
  if (MI.getNumOperands() < 1) return false;
  // Vec load or compute.
  if (MI.getOperand(0).isReg() && MI.getOperand(0).isDef()) {
    Reg = MI.getOperand(0).getReg();
    if (isVecReg(Reg))
      return !TraceHexVectorStoresOnly;
  }
  // Vec store.
  if (MI.mayStore() && MI.getNumOperands() >= 3 && MI.getOperand(2).isReg()) {
    Reg = MI.getOperand(2).getReg();
    if (isVecReg(Reg))
      return true;
  }
  // Vec store post increment.
  if (MI.mayStore() && MI.getNumOperands() >= 4 && MI.getOperand(3).isReg()) {
    Reg = MI.getOperand(3).getReg();
    if (isVecReg(Reg))
      return true;
  }
  return false;
}
bool HexagonVectorPrint::runOnMachineFunction(MachineFunction &Fn) {
  bool Changed = false;
  QST = &Fn.getSubtarget<HexagonSubtarget>();
  QRI = QST->getRegisterInfo();
  QII = QST->getInstrInfo();
  std::vector<MachineInstr *> VecPrintList;
  for (auto &MBB : Fn)
    for (auto &MI : MBB) {
      if (MI.isBundle()) {
        MachineBasicBlock::instr_iterator MII = MI.getIterator();
        for (++MII; MII != MBB.instr_end() && MII->isInsideBundle(); ++MII) {
          if (MII->getNumOperands() < 1)
            continue;
          unsigned Reg = 0;
          if (getInstrVecReg(*MII, Reg)) {
            VecPrintList.push_back((&*MII));
            LLVM_DEBUG(dbgs() << "Found vector reg inside bundle \n";
                       MII->dump());
          }
        }
      } else {
        unsigned Reg = 0;
        if (getInstrVecReg(MI, Reg)) {
          VecPrintList.push_back(&MI);
          LLVM_DEBUG(dbgs() << "Found vector reg \n"; MI.dump());
        }
      }
    }
  Changed = !VecPrintList.empty();
  if (!Changed)
    return Changed;
  for (auto *I : VecPrintList) {
    DebugLoc DL = I->getDebugLoc();
    MachineBasicBlock *MBB = I->getParent();
    LLVM_DEBUG(dbgs() << "Evaluating V MI\n"; I->dump());
    unsigned Reg = 0;
    if (!getInstrVecReg(*I, Reg))
      llvm_unreachable("Need a vector reg");
    MachineBasicBlock::instr_iterator MII = I->getIterator();
    if (I->isInsideBundle()) {
      LLVM_DEBUG(dbgs() << "add to end of bundle\n"; I->dump());
      while (MBB->instr_end() != MII && MII->isInsideBundle())
        MII++;
    } else {
      LLVM_DEBUG(dbgs() << "add after instruction\n"; I->dump());
      MII++;
    }
    if (MBB->instr_end() == MII)
      continue;
    if (Reg >= Hexagon::V0 && Reg <= Hexagon::V31) {
      LLVM_DEBUG(dbgs() << "adding dump for V" << Reg - Hexagon::V0 << '\n');
      addAsmInstr(MBB, Reg, MII, DL, QII, Fn);
    } else if (Reg >= Hexagon::W0 && Reg <= Hexagon::W15) {
      LLVM_DEBUG(dbgs() << "adding dump for W" << Reg - Hexagon::W0 << '\n');
      addAsmInstr(MBB, Hexagon::V0 + (Reg - Hexagon::W0) * 2 + 1,
                  MII, DL, QII, Fn);
      addAsmInstr(MBB, Hexagon::V0 + (Reg - Hexagon::W0) * 2,
                   MII, DL, QII, Fn);
    } else if (Reg >= Hexagon::Q0 && Reg <= Hexagon::Q3) {
      LLVM_DEBUG(dbgs() << "adding dump for Q" << Reg - Hexagon::Q0 << '\n');
      addAsmInstr(MBB, Reg, MII, DL, QII, Fn);
    } else
      llvm_unreachable("Bad Vector reg");
  }
  return Changed;
}
//===----------------------------------------------------------------------===//
//                         Public Constructor Functions
//===----------------------------------------------------------------------===//
INITIALIZE_PASS(HexagonVectorPrint, "hexagon-vector-print",
  "Hexagon VectorPrint pass", false, false)
FunctionPass *llvm::createHexagonVectorPrint() {
  return new HexagonVectorPrint();
}
 |