reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    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
  210
  211
//===-- MCInstrDescView.h ---------------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Provide views around LLVM structures to represents an instruction instance,
/// as well as its implicit and explicit arguments in a uniform way.
/// Arguments that are explicit and independant (non tied) also have a Variable
/// associated to them so the instruction can be fully defined by reading its
/// Variables.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H
#define LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H

#include <random>
#include <unordered_map>

#include "RegisterAliasing.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCInstrInfo.h"

namespace llvm {
namespace exegesis {

// A variable represents the value associated to an Operand or a set of Operands
// if they are tied together.
struct Variable {
  // Returns the index of this Variable inside Instruction's Variable.
  unsigned getIndex() const;

  // Returns the index of the Operand linked to this Variable.
  unsigned getPrimaryOperandIndex() const;

  // Returns whether this Variable has more than one Operand linked to it.
  bool hasTiedOperands() const;

  // The indices of the operands tied to this Variable.
  SmallVector<unsigned, 2> TiedOperands;

  // The index of this Variable in Instruction.Variables and its associated
  // Value in InstructionBuilder.VariableValues.
  int Index = -1;
};

// MCOperandInfo can only represents Explicit operands. This object gives a
// uniform view of Implicit and Explicit Operands.
// - Index: can be used to refer to MCInstrDesc::operands for Explicit operands.
// - Tracker: is set for Register Operands and is used to keep track of possible
// registers and the registers reachable from them (aliasing registers).
// - Info: a shortcut for MCInstrDesc::operands()[Index].
// - TiedToIndex: the index of the Operand holding the value or -1.
// - ImplicitReg: a pointer to the register value when Operand is Implicit,
// nullptr otherwise.
// - VariableIndex: the index of the Variable holding the value for this Operand
// or -1 if this operand is implicit.
struct Operand {
  bool isExplicit() const;
  bool isImplicit() const;
  bool isImplicitReg() const;
  bool isDef() const;
  bool isUse() const;
  bool isReg() const;
  bool isTied() const;
  bool isVariable() const;
  bool isMemory() const;
  bool isImmediate() const;
  unsigned getIndex() const;
  unsigned getTiedToIndex() const;
  unsigned getVariableIndex() const;
  unsigned getImplicitReg() const;
  const RegisterAliasingTracker &getRegisterAliasing() const;
  const MCOperandInfo &getExplicitOperandInfo() const;

  // Please use the accessors above and not the following fields.
  int Index = -1;
  bool IsDef = false;
  const RegisterAliasingTracker *Tracker = nullptr; // Set for Register Op.
  const MCOperandInfo *Info = nullptr;              // Set for Explicit Op.
  int TiedToIndex = -1;                             // Set for Reg&Explicit Op.
  const MCPhysReg *ImplicitReg = nullptr;           // Set for Implicit Op.
  int VariableIndex = -1;                           // Set for Explicit Op.
};

// A view over an MCInstrDesc offering a convenient interface to compute
// Register aliasing.
struct Instruction {
  Instruction(const MCInstrInfo &InstrInfo,
              const RegisterAliasingTrackerCache &RATC, unsigned Opcode);

  // Returns the Operand linked to this Variable.
  // In case the Variable is tied, the primary (i.e. Def) Operand is returned.
  const Operand &getPrimaryOperand(const Variable &Var) const;

  // Whether this instruction is self aliasing through its tied registers.
  // Repeating this instruction is guaranteed to executes sequentially.
  bool hasTiedRegisters() const;

  // Whether this instruction is self aliasing through its implicit registers.
  // Repeating this instruction is guaranteed to executes sequentially.
  bool hasAliasingImplicitRegisters() const;

  // Whether this instruction is self aliasing through some registers.
  // Repeating this instruction may execute sequentially by picking aliasing
  // Use and Def registers. It may also execute in parallel by picking non
  // aliasing Use and Def registers.
  bool hasAliasingRegisters(const BitVector &ForbiddenRegisters) const;

  // Whether this instruction's registers alias with OtherInstr's registers.
  bool hasAliasingRegistersThrough(const Instruction &OtherInstr,
                                   const BitVector &ForbiddenRegisters) const;

  // Returns whether this instruction has Memory Operands.
  // Repeating this instruction executes sequentially with an instruction that
  // reads or write the same memory region.
  bool hasMemoryOperands() const;

  // Returns whether this instruction as at least one use or one def.
  // Repeating this instruction may execute sequentially by adding an
  // instruction that aliases one of these.
  bool hasOneUseOrOneDef() const;

  // Convenient function to help with debugging.
  void dump(const MCRegisterInfo &RegInfo,
            const RegisterAliasingTrackerCache &RATC,
            raw_ostream &Stream) const;

  const MCInstrDesc *Description; // Never nullptr.
  StringRef Name;                 // The name of this instruction.
  SmallVector<Operand, 8> Operands;
  SmallVector<Variable, 4> Variables;
  BitVector ImplDefRegs; // The set of aliased implicit def registers.
  BitVector ImplUseRegs; // The set of aliased implicit use registers.
  BitVector AllDefRegs;  // The set of all aliased def registers.
  BitVector AllUseRegs;  // The set of all aliased use registers.
};

// Instructions are expensive to instantiate. This class provides a cache of
// Instructions with lazy construction.
struct InstructionsCache {
  InstructionsCache(const MCInstrInfo &InstrInfo,
                    const RegisterAliasingTrackerCache &RATC);

  // Returns the Instruction object corresponding to this Opcode.
  const Instruction &getInstr(unsigned Opcode) const;

private:
  const MCInstrInfo &InstrInfo;
  const RegisterAliasingTrackerCache &RATC;
  mutable std::unordered_map<unsigned, std::unique_ptr<Instruction>>
      Instructions;
};

// Represents the assignment of a Register to an Operand.
struct RegisterOperandAssignment {
  RegisterOperandAssignment(const Operand *Operand, MCPhysReg Reg)
      : Op(Operand), Reg(Reg) {}

  const Operand *Op; // Pointer to an Explicit Register Operand.
  MCPhysReg Reg;

  bool operator==(const RegisterOperandAssignment &other) const;
};

// Represents a set of Operands that would alias through the use of some
// Registers.
// There are two reasons why operands would alias:
// - The registers assigned to each of the operands are the same or alias each
//   other (e.g. AX/AL)
// - The operands are tied.
struct AliasingRegisterOperands {
  SmallVector<RegisterOperandAssignment, 1> Defs; // Unlikely size() > 1.
  SmallVector<RegisterOperandAssignment, 2> Uses;

  // True is Defs and Use contain an Implicit Operand.
  bool hasImplicitAliasing() const;

  bool operator==(const AliasingRegisterOperands &other) const;
};

// Returns all possible configurations leading Def registers of DefInstruction
// to alias with Use registers of UseInstruction.
struct AliasingConfigurations {
  AliasingConfigurations(const Instruction &DefInstruction,
                         const Instruction &UseInstruction);

  bool empty() const; // True if no aliasing configuration is found.
  bool hasImplicitAliasing() const;

  SmallVector<AliasingRegisterOperands, 32> Configurations;
};

// Writes MCInst to OS.
// This is not assembly but the internal LLVM's name for instructions and
// registers.
void DumpMCInst(const MCRegisterInfo &MCRegisterInfo,
                const MCInstrInfo &MCInstrInfo, const MCInst &MCInst,
                raw_ostream &OS);

} // namespace exegesis
} // namespace llvm

#endif // LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H