1//===-- TargetMacroFusion.td - Target Macro Fusion ---------*- tablegen -*-===//
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// This file defines the TableGen-based macro fusion classes.
10
11// The target instruction that FusionPredicate will be evaluated on.
12class FusionTarget;
13def first_fusion_target : FusionTarget;
14def second_fusion_target : FusionTarget;
15def both_fusion_target : FusionTarget;
16
17// Base class of FusionPredicate, etc. The avaliable variables are:
18// * const TargetInstrInfo &TII
19// * const TargetSubtargetInfo &STI
20// * const MachineRegisterInfo &MRI
21// * const MachineInstr *FirstMI
22// * const MachineInstr &SecondMI
23class FusionPredicate<FusionTarget target> {
24  FusionTarget Target = target;
25}
26class FirstFusionPredicate: FusionPredicate<first_fusion_target>;
27class SecondFusionPredicate: FusionPredicate<second_fusion_target>;
28class BothFusionPredicate: FusionPredicate<both_fusion_target>;
29
30// FusionPredicate with raw code predicate.
31class FusionPredicateWithCode<code pred> : FusionPredicate<both_fusion_target> {
32  code Predicate = pred;
33}
34
35// FusionPredicate with MCInstPredicate.
36class FusionPredicateWithMCInstPredicate<FusionTarget target, MCInstPredicate pred>
37  : FusionPredicate<target> {
38  MCInstPredicate Predicate = pred;
39}
40class FirstFusionPredicateWithMCInstPredicate<MCInstPredicate pred>
41  : FusionPredicateWithMCInstPredicate<first_fusion_target, pred>;
42class SecondFusionPredicateWithMCInstPredicate<MCInstPredicate pred>
43  : FusionPredicateWithMCInstPredicate<second_fusion_target, pred>;
44// The pred will be applied on both firstMI and secondMI.
45class BothFusionPredicateWithMCInstPredicate<MCInstPredicate pred>
46  : FusionPredicateWithMCInstPredicate<both_fusion_target, pred>;
47
48// Tie firstOpIdx and secondOpIdx. The operand of `FirstMI` at position
49// `firstOpIdx` should be the same as the operand of `SecondMI` at position
50// `secondOpIdx`.
51// If the fusion has `IsCommutable` being true and the operand at `secondOpIdx`
52// has commutable operand, then the commutable operand will be checked too.
53class TieReg<int firstOpIdx, int secondOpIdx> : BothFusionPredicate {
54  int FirstOpIdx = firstOpIdx;
55  int SecondOpIdx = secondOpIdx;
56}
57
58// The operand of `SecondMI` at position `firstOpIdx` should be the same as the
59// operand at position `secondOpIdx`.
60// If the fusion has `IsCommutable` being true and the operand at `secondOpIdx`
61// has commutable operand, then the commutable operand will be checked too.
62class SameReg<int firstOpIdx, int secondOpIdx> : SecondFusionPredicate {
63  int FirstOpIdx = firstOpIdx;
64  int SecondOpIdx = secondOpIdx;
65}
66
67// A predicate for wildcard. The generated code will be like:
68// ```
69// if (!FirstMI)
70//   return ReturnValue;
71// ```
72class WildcardPred<bit ret> : FirstFusionPredicate {
73  bit ReturnValue = ret;
74}
75def WildcardFalse : WildcardPred<0>;
76def WildcardTrue : WildcardPred<1>;
77
78// Indicates that the destination register of `FirstMI` should have one use if
79// it is a virtual register.
80class OneUsePred : FirstFusionPredicate;
81def OneUse : OneUsePred;
82
83// Handled by MacroFusionPredicatorEmitter backend.
84// The generated predicator will be like:
85// ```
86// bool isNAME(const TargetInstrInfo &TII,
87//             const TargetSubtargetInfo &STI,
88//             const MachineInstr *FirstMI,
89//             const MachineInstr &SecondMI) {
90//   auto &MRI = SecondMI.getMF()->getRegInfo();
91//   /* Predicates */
92//   return true;
93// }
94// ```
95//
96// `IsCommutable` means whether we should handle commutable operands.
97class Fusion<string name, string fieldName, string desc, list<FusionPredicate> predicates>
98  : SubtargetFeature<name, fieldName, "true", desc> {
99  list<FusionPredicate> Predicates = predicates;
100  bit IsCommutable = 0;
101}
102
103// The generated predicator will be like:
104// ```
105// bool isNAME(const TargetInstrInfo &TII,
106//             const TargetSubtargetInfo &STI,
107//             const MachineInstr *FirstMI,
108//             const MachineInstr &SecondMI) {
109//   auto &MRI = SecondMI.getMF()->getRegInfo();
110//   /* Prolog */
111//   /* Predicate for `SecondMI` */
112//   /* Wildcard */
113//   /* Predicate for `FirstMI` */
114//   /* Check same registers */
115//   /* Check One Use */
116//   /* Tie registers */
117//   /* Epilog */
118//   return true;
119// }
120// ```
121class SimpleFusion<string name, string fieldName, string desc,
122                   MCInstPredicate firstPred, MCInstPredicate secondPred,
123                   list<FusionPredicate> prolog = [],
124                   list<FusionPredicate> epilog = []>
125  : Fusion<name, fieldName, desc,
126           !listconcat(
127              prolog,
128              [
129                SecondFusionPredicateWithMCInstPredicate<secondPred>,
130                WildcardTrue,
131                FirstFusionPredicateWithMCInstPredicate<firstPred>,
132                SameReg<0, 1>,
133                OneUse,
134                TieReg<0, 1>,
135              ],
136              epilog)>;
137
138class SingleFusion<string name, string fieldName, string desc,
139                   Instruction firstInst, Instruction secondInst,
140                   MCInstPredicate firstInstPred = TruePred,
141                   MCInstPredicate secondInstPred = TruePred,
142                   list<FusionPredicate> prolog = [],
143                   list<FusionPredicate> epilog = []>
144  : SimpleFusion<name, fieldName, desc,
145                 CheckAll<!listconcat(
146                            [CheckOpcode<[firstInst]>],
147                            [firstInstPred])>,
148                 CheckAll<!listconcat(
149                            [CheckOpcode<[secondInst]>],
150                            [secondInstPred])>,
151                 prolog, epilog> {
152  let IsCommutable = secondInst.isCommutable;
153}
154