//===-- TargetMacroFusion.td - Target Macro Fusion ---------*- tablegen -*-===// // // 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 file defines the TableGen-based macro fusion classes. // The target instruction that FusionPredicate will be evaluated on. class FusionTarget; def first_fusion_target : FusionTarget; def second_fusion_target : FusionTarget; def both_fusion_target : FusionTarget; // Base class of FusionPredicate, etc. The avaliable variables are: // * const TargetInstrInfo &TII // * const TargetSubtargetInfo &STI // * const MachineRegisterInfo &MRI // * const MachineInstr *FirstMI // * const MachineInstr &SecondMI class FusionPredicate { FusionTarget Target = target; } class FirstFusionPredicate: FusionPredicate; class SecondFusionPredicate: FusionPredicate; class BothFusionPredicate: FusionPredicate; // FusionPredicate with raw code predicate. class FusionPredicateWithCode : FusionPredicate { code Predicate = pred; } // FusionPredicate with MCInstPredicate. class FusionPredicateWithMCInstPredicate : FusionPredicate { MCInstPredicate Predicate = pred; } class FirstFusionPredicateWithMCInstPredicate : FusionPredicateWithMCInstPredicate; class SecondFusionPredicateWithMCInstPredicate : FusionPredicateWithMCInstPredicate; // The pred will be applied on both firstMI and secondMI. class BothFusionPredicateWithMCInstPredicate : FusionPredicateWithMCInstPredicate; // Tie firstOpIdx and secondOpIdx. The operand of `FirstMI` at position // `firstOpIdx` should be the same as the operand of `SecondMI` at position // `secondOpIdx`. // If the fusion has `IsCommutable` being true and the operand at `secondOpIdx` // has commutable operand, then the commutable operand will be checked too. class TieReg : BothFusionPredicate { int FirstOpIdx = firstOpIdx; int SecondOpIdx = secondOpIdx; } // The operand of `SecondMI` at position `firstOpIdx` should be the same as the // operand at position `secondOpIdx`. // If the fusion has `IsCommutable` being true and the operand at `secondOpIdx` // has commutable operand, then the commutable operand will be checked too. class SameReg : SecondFusionPredicate { int FirstOpIdx = firstOpIdx; int SecondOpIdx = secondOpIdx; } // A predicate for wildcard. The generated code will be like: // ``` // if (!FirstMI) // return ReturnValue; // ``` class WildcardPred : FirstFusionPredicate { bit ReturnValue = ret; } def WildcardFalse : WildcardPred<0>; def WildcardTrue : WildcardPred<1>; // Indicates that the destination register of `FirstMI` should have one use if // it is a virtual register. class OneUsePred : FirstFusionPredicate; def OneUse : OneUsePred; // Handled by MacroFusionPredicatorEmitter backend. // The generated predicator will be like: // ``` // bool isNAME(const TargetInstrInfo &TII, // const TargetSubtargetInfo &STI, // const MachineInstr *FirstMI, // const MachineInstr &SecondMI) { // auto &MRI = SecondMI.getMF()->getRegInfo(); // /* Predicates */ // return true; // } // ``` // // `IsCommutable` means whether we should handle commutable operands. class Fusion predicates> : SubtargetFeature { list Predicates = predicates; bit IsCommutable = 0; } // The generated predicator will be like: // ``` // bool isNAME(const TargetInstrInfo &TII, // const TargetSubtargetInfo &STI, // const MachineInstr *FirstMI, // const MachineInstr &SecondMI) { // auto &MRI = SecondMI.getMF()->getRegInfo(); // /* Prolog */ // /* Predicate for `SecondMI` */ // /* Wildcard */ // /* Predicate for `FirstMI` */ // /* Check same registers */ // /* Check One Use */ // /* Tie registers */ // /* Epilog */ // return true; // } // ``` class SimpleFusion prolog = [], list epilog = []> : Fusion, WildcardTrue, FirstFusionPredicateWithMCInstPredicate, SameReg<0, 1>, OneUse, TieReg<0, 1>, ], epilog)>; class SingleFusion prolog = [], list epilog = []> : SimpleFusion], [firstInstPred])>, CheckAll], [secondInstPred])>, prolog, epilog> { let IsCommutable = secondInst.isCommutable; }