1 //===-- CodeTemplate.h ------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// A set of structures and functions to craft instructions for the
11 /// SnippetGenerator.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_TOOLS_LLVM_EXEGESIS_CODETEMPLATE_H
16 #define LLVM_TOOLS_LLVM_EXEGESIS_CODETEMPLATE_H
17 
18 #include "MCInstrDescView.h"
19 #include "llvm/ADT/BitmaskEnum.h"
20 
21 namespace llvm {
22 namespace exegesis {
23 
24 // A template for an Instruction holding values for each of its Variables.
25 struct InstructionTemplate {
26   InstructionTemplate(const Instruction *Instr);
27 
28   InstructionTemplate(const InstructionTemplate &);            // default
29   InstructionTemplate &operator=(const InstructionTemplate &); // default
30   InstructionTemplate(InstructionTemplate &&);                 // default
31   InstructionTemplate &operator=(InstructionTemplate &&);      // default
32 
33   unsigned getOpcode() const;
34   MCOperand &getValueFor(const Variable &Var);
35   const MCOperand &getValueFor(const Variable &Var) const;
36   MCOperand &getValueFor(const Operand &Op);
37   const MCOperand &getValueFor(const Operand &Op) const;
38   bool hasImmediateVariables() const;
getInstrInstructionTemplate39   const Instruction &getInstr() const { return *Instr; }
getVariableValuesInstructionTemplate40   ArrayRef<MCOperand> getVariableValues() const { return VariableValues; }
setVariableValuesInstructionTemplate41   void setVariableValues(ArrayRef<MCOperand> NewVariableValues) {
42     assert(VariableValues.size() == NewVariableValues.size() &&
43            "Value count mismatch");
44     VariableValues.assign(NewVariableValues.begin(), NewVariableValues.end());
45   }
46 
47   // Builds an MCInst from this InstructionTemplate setting its operands
48   // to the corresponding variable values. Precondition: All VariableValues must
49   // be set.
50   MCInst build() const;
51 
52 private:
53   const Instruction *Instr;
54   SmallVector<MCOperand, 4> VariableValues;
55 };
56 
57 enum class ExecutionMode : uint8_t {
58   UNKNOWN = 0U,
59   // The instruction is always serial because implicit Use and Def alias.
60   // e.g. AAA (alias via EFLAGS)
61   ALWAYS_SERIAL_IMPLICIT_REGS_ALIAS = 1u << 0,
62 
63   // The instruction is always serial because one Def is tied to a Use.
64   // e.g. AND32ri (alias via tied GR32)
65   ALWAYS_SERIAL_TIED_REGS_ALIAS = 1u << 1,
66 
67   // The execution can be made serial by inserting a second instruction that
68   // clobbers/reads memory.
69   // e.g. MOV8rm
70   SERIAL_VIA_MEMORY_INSTR = 1u << 2,
71 
72   // The execution can be made serial by picking one Def that aliases with one
73   // Use.
74   // e.g. VXORPSrr XMM1, XMM1, XMM2
75   SERIAL_VIA_EXPLICIT_REGS = 1u << 3,
76 
77   // The execution can be made serial by inserting a second instruction that
78   // uses one of the Defs and defs one of the Uses.
79   // e.g.
80   // 1st instruction: MMX_PMOVMSKBrr ECX, MM7
81   // 2nd instruction: MMX_MOVD64rr MM7, ECX
82   //  or instruction: MMX_MOVD64to64rr MM7, ECX
83   //  or instruction: MMX_PINSRWrr MM7, MM7, ECX, 1
84   SERIAL_VIA_NON_MEMORY_INSTR = 1u << 4,
85 
86   // The execution is always parallel because the instruction is missing Use or
87   // Def operands.
88   ALWAYS_PARALLEL_MISSING_USE_OR_DEF = 1u << 5,
89 
90   // The execution can be made parallel by repeating the same instruction but
91   // making sure that Defs of one instruction do not alias with Uses of the
92   // second one.
93   PARALLEL_VIA_EXPLICIT_REGS = 1u << 6,
94 
95   LLVM_MARK_AS_BITMASK_ENUM(/*Largest*/ PARALLEL_VIA_EXPLICIT_REGS)
96 };
97 
98 // Returns whether Execution is one of the values defined in the enum above.
99 bool isEnumValue(ExecutionMode Execution);
100 
101 // Returns a human readable string for the enum.
102 StringRef getName(ExecutionMode Execution);
103 
104 // Returns a sequence of increasing powers of two corresponding to all the
105 // Execution flags.
106 ArrayRef<ExecutionMode> getAllExecutionBits();
107 
108 // Decomposes Execution into individual set bits.
109 SmallVector<ExecutionMode, 4> getExecutionModeBits(ExecutionMode);
110 
111 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
112 
113 // A CodeTemplate is a set of InstructionTemplates that may not be fully
114 // specified (i.e. some variables are not yet set). This allows the
115 // SnippetGenerator to instantiate it many times with specific values to study
116 // their impact on instruction's performance.
117 struct CodeTemplate {
118   CodeTemplate() = default;
119 
120   CodeTemplate(CodeTemplate &&);            // default
121   CodeTemplate &operator=(CodeTemplate &&); // default
122 
123   CodeTemplate clone() const;
124 
125   ExecutionMode Execution = ExecutionMode::UNKNOWN;
126   // See InstructionBenchmarkKey.::Config.
127   std::string Config;
128   // Some information about how this template has been created.
129   std::string Info;
130   // The list of the instructions for this template.
131   std::vector<InstructionTemplate> Instructions;
132   // If the template uses the provided scratch memory, the register in which
133   // the pointer to this memory is passed in to the function.
134   unsigned ScratchSpacePointerInReg = 0;
135 
136 #if defined(__GNUC__) && (defined(__clang__) || LLVM_GNUC_PREREQ(8, 0, 0))
137   // FIXME: GCC7 bug workaround. Drop #if after GCC7 no longer supported.
138 private:
139 #endif
140   CodeTemplate(const CodeTemplate &);            // default
141   CodeTemplate &operator=(const CodeTemplate &); // default
142 };
143 
144 } // namespace exegesis
145 } // namespace llvm
146 
147 #endif // LLVM_TOOLS_LLVM_EXEGESIS_CODETEMPLATE_H
148