1320374Sdim//===- ARMMacroFusion.cpp - ARM Macro Fusion ----------------------===//
2320374Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6320374Sdim//
7320374Sdim//===----------------------------------------------------------------------===//
8320374Sdim//
9320374Sdim/// \file This file contains the ARM implementation of the DAG scheduling
10320374Sdim///  mutation to pair instructions back to back.
11320374Sdim//
12320374Sdim//===----------------------------------------------------------------------===//
13320374Sdim
14320374Sdim#include "ARMMacroFusion.h"
15320374Sdim#include "ARMSubtarget.h"
16320374Sdim#include "llvm/CodeGen/MacroFusion.h"
17327952Sdim#include "llvm/CodeGen/TargetInstrInfo.h"
18320374Sdim
19320374Sdimnamespace llvm {
20320374Sdim
21341825Sdim// Fuse AES crypto encoding or decoding.
22341825Sdimstatic bool isAESPair(const MachineInstr *FirstMI,
23341825Sdim                      const MachineInstr &SecondMI) {
24341825Sdim  // Assume the 1st instr to be a wildcard if it is unspecified.
25344779Sdim  switch(SecondMI.getOpcode()) {
26341825Sdim  // AES encode.
27341825Sdim  case ARM::AESMC :
28344779Sdim    return FirstMI == nullptr || FirstMI->getOpcode() == ARM::AESE;
29341825Sdim  // AES decode.
30341825Sdim  case ARM::AESIMC:
31344779Sdim    return FirstMI == nullptr || FirstMI->getOpcode() == ARM::AESD;
32341825Sdim  }
33341825Sdim
34341825Sdim  return false;
35341825Sdim}
36341825Sdim
37341825Sdim// Fuse literal generation.
38341825Sdimstatic bool isLiteralsPair(const MachineInstr *FirstMI,
39341825Sdim                           const MachineInstr &SecondMI) {
40341825Sdim  // Assume the 1st instr to be a wildcard if it is unspecified.
41344779Sdim  if ((FirstMI == nullptr || FirstMI->getOpcode() == ARM::MOVi16) &&
42344779Sdim      SecondMI.getOpcode() == ARM::MOVTi16)
43341825Sdim    return true;
44341825Sdim
45341825Sdim  return false;
46341825Sdim}
47341825Sdim
48341825Sdim/// Check if the instr pair, FirstMI and SecondMI, should be fused
49320374Sdim/// together. Given SecondMI, when FirstMI is unspecified, then check if
50320374Sdim/// SecondMI may be part of a fused pair at all.
51320374Sdimstatic bool shouldScheduleAdjacent(const TargetInstrInfo &TII,
52320374Sdim                                   const TargetSubtargetInfo &TSI,
53320374Sdim                                   const MachineInstr *FirstMI,
54320374Sdim                                   const MachineInstr &SecondMI) {
55320374Sdim  const ARMSubtarget &ST = static_cast<const ARMSubtarget&>(TSI);
56320374Sdim
57341825Sdim  if (ST.hasFuseAES() && isAESPair(FirstMI, SecondMI))
58341825Sdim    return true;
59341825Sdim  if (ST.hasFuseLiterals() && isLiteralsPair(FirstMI, SecondMI))
60341825Sdim    return true;
61320374Sdim
62320374Sdim  return false;
63320374Sdim}
64320374Sdim
65320374Sdimstd::unique_ptr<ScheduleDAGMutation> createARMMacroFusionDAGMutation () {
66320374Sdim  return createMacroFusionDAGMutation(shouldScheduleAdjacent);
67320374Sdim}
68320374Sdim
69320374Sdim} // end namespace llvm
70