blob: 6930c816b5ae3015f0406a4bf9979d1d5aad30a1 [file] [log] [blame]
Evandro Menezes94edf022017-02-01 02:54:34 +00001//===- AArch64MacroFusion.cpp - AArch64 Macro Fusion ----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Florian Hahn5f746c82017-06-19 12:53:31 +000010/// \file This file contains the AArch64 implementation of the DAG scheduling
11/// mutation to pair instructions back to back.
Evandro Menezes94edf022017-02-01 02:54:34 +000012//
13//===----------------------------------------------------------------------===//
14
Evandro Menezes94edf022017-02-01 02:54:34 +000015#include "AArch64Subtarget.h"
Florian Hahn5f746c82017-06-19 12:53:31 +000016#include "llvm/CodeGen/MacroFusion.h"
David Blaikie3f833ed2017-11-08 01:01:31 +000017#include "llvm/CodeGen/TargetInstrInfo.h"
Evandro Menezes94edf022017-02-01 02:54:34 +000018
Evandro Menezes94edf022017-02-01 02:54:34 +000019using namespace llvm;
20
Evandro Menezes94edf022017-02-01 02:54:34 +000021namespace {
22
Florian Hahn5f746c82017-06-19 12:53:31 +000023/// \brief Check if the instr pair, FirstMI and SecondMI, should be fused
24/// together. Given SecondMI, when FirstMI is unspecified, then check if
25/// SecondMI may be part of a fused pair at all.
Evandro Menezes203eef02017-04-11 19:13:11 +000026static bool shouldScheduleAdjacent(const TargetInstrInfo &TII,
27 const TargetSubtargetInfo &TSI,
28 const MachineInstr *FirstMI,
Florian Hahn5f746c82017-06-19 12:53:31 +000029 const MachineInstr &SecondMI) {
Evandro Menezes203eef02017-04-11 19:13:11 +000030 const AArch64InstrInfo &II = static_cast<const AArch64InstrInfo&>(TII);
31 const AArch64Subtarget &ST = static_cast<const AArch64Subtarget&>(TSI);
32
33 // Assume wildcards for unspecified instrs.
Simon Pilgrimb0921662017-02-18 22:50:28 +000034 unsigned FirstOpcode =
NAKAMURA Takumia1e97a72017-08-28 06:47:47 +000035 FirstMI ? FirstMI->getOpcode()
36 : static_cast<unsigned>(AArch64::INSTRUCTION_LIST_END);
Florian Hahn5f746c82017-06-19 12:53:31 +000037 unsigned SecondOpcode = SecondMI.getOpcode();
Evandro Menezes94edf022017-02-01 02:54:34 +000038
39 if (ST.hasArithmeticBccFusion())
40 // Fuse CMN, CMP, TST followed by Bcc.
41 if (SecondOpcode == AArch64::Bcc)
42 switch (FirstOpcode) {
43 default:
44 return false;
45 case AArch64::ADDSWri:
46 case AArch64::ADDSWrr:
47 case AArch64::ADDSXri:
48 case AArch64::ADDSXrr:
49 case AArch64::ANDSWri:
50 case AArch64::ANDSWrr:
51 case AArch64::ANDSXri:
52 case AArch64::ANDSXrr:
53 case AArch64::SUBSWri:
54 case AArch64::SUBSWrr:
55 case AArch64::SUBSXri:
56 case AArch64::SUBSXrr:
57 case AArch64::BICSWrr:
58 case AArch64::BICSXrr:
59 return true;
60 case AArch64::ADDSWrs:
61 case AArch64::ADDSXrs:
62 case AArch64::ANDSWrs:
63 case AArch64::ANDSXrs:
64 case AArch64::SUBSWrs:
65 case AArch64::SUBSXrs:
66 case AArch64::BICSWrs:
67 case AArch64::BICSXrs:
68 // Shift value can be 0 making these behave like the "rr" variant...
Evandro Menezes203eef02017-04-11 19:13:11 +000069 return !II.hasShiftedReg(*FirstMI);
Evandro Menezes94edf022017-02-01 02:54:34 +000070 case AArch64::INSTRUCTION_LIST_END:
71 return true;
72 }
73
74 if (ST.hasArithmeticCbzFusion())
75 // Fuse ALU operations followed by CBZ/CBNZ.
76 if (SecondOpcode == AArch64::CBNZW || SecondOpcode == AArch64::CBNZX ||
77 SecondOpcode == AArch64::CBZW || SecondOpcode == AArch64::CBZX)
78 switch (FirstOpcode) {
79 default:
80 return false;
81 case AArch64::ADDWri:
82 case AArch64::ADDWrr:
83 case AArch64::ADDXri:
84 case AArch64::ADDXrr:
85 case AArch64::ANDWri:
86 case AArch64::ANDWrr:
87 case AArch64::ANDXri:
88 case AArch64::ANDXrr:
89 case AArch64::EORWri:
90 case AArch64::EORWrr:
91 case AArch64::EORXri:
92 case AArch64::EORXrr:
93 case AArch64::ORRWri:
94 case AArch64::ORRWrr:
95 case AArch64::ORRXri:
96 case AArch64::ORRXrr:
97 case AArch64::SUBWri:
98 case AArch64::SUBWrr:
99 case AArch64::SUBXri:
100 case AArch64::SUBXrr:
101 return true;
102 case AArch64::ADDWrs:
103 case AArch64::ADDXrs:
104 case AArch64::ANDWrs:
105 case AArch64::ANDXrs:
106 case AArch64::SUBWrs:
107 case AArch64::SUBXrs:
108 case AArch64::BICWrs:
109 case AArch64::BICXrs:
110 // Shift value can be 0 making these behave like the "rr" variant...
Evandro Menezes203eef02017-04-11 19:13:11 +0000111 return !II.hasShiftedReg(*FirstMI);
Evandro Menezes94edf022017-02-01 02:54:34 +0000112 case AArch64::INSTRUCTION_LIST_END:
113 return true;
114 }
115
Evandro Menezesb21fb292017-02-01 02:54:39 +0000116 if (ST.hasFuseAES())
117 // Fuse AES crypto operations.
Florian Hahn5f746c82017-06-19 12:53:31 +0000118 switch(SecondOpcode) {
Evandro Menezesb21fb292017-02-01 02:54:39 +0000119 // AES encode.
Florian Hahnf63a5e92017-07-29 20:35:28 +0000120 case AArch64::AESMCrr:
121 case AArch64::AESMCrrTied:
Florian Hahn5f746c82017-06-19 12:53:31 +0000122 return FirstOpcode == AArch64::AESErr ||
123 FirstOpcode == AArch64::INSTRUCTION_LIST_END;
Evandro Menezesb21fb292017-02-01 02:54:39 +0000124 // AES decode.
Florian Hahn5f746c82017-06-19 12:53:31 +0000125 case AArch64::AESIMCrr:
Florian Hahnf63a5e92017-07-29 20:35:28 +0000126 case AArch64::AESIMCrrTied:
Florian Hahn5f746c82017-06-19 12:53:31 +0000127 return FirstOpcode == AArch64::AESDrr ||
128 FirstOpcode == AArch64::INSTRUCTION_LIST_END;
Evandro Menezesb21fb292017-02-01 02:54:39 +0000129 }
130
Evandro Menezes455382e2017-02-01 02:54:42 +0000131 if (ST.hasFuseLiterals())
132 // Fuse literal generation operations.
Florian Hahn5f746c82017-06-19 12:53:31 +0000133 switch (SecondOpcode) {
Evandro Menezes455382e2017-02-01 02:54:42 +0000134 // PC relative address.
Florian Hahn5f746c82017-06-19 12:53:31 +0000135 case AArch64::ADDXri:
136 return FirstOpcode == AArch64::ADRP ||
137 FirstOpcode == AArch64::INSTRUCTION_LIST_END;
Evandro Menezes455382e2017-02-01 02:54:42 +0000138 // 32 bit immediate.
Florian Hahn5f746c82017-06-19 12:53:31 +0000139 case AArch64::MOVKWi:
140 return (FirstOpcode == AArch64::MOVZWi &&
141 SecondMI.getOperand(3).getImm() == 16) ||
142 FirstOpcode == AArch64::INSTRUCTION_LIST_END;
143 // Lower and upper half of 64 bit immediate.
Evandro Menezes455382e2017-02-01 02:54:42 +0000144 case AArch64::MOVKXi:
Florian Hahn5f746c82017-06-19 12:53:31 +0000145 return FirstOpcode == AArch64::INSTRUCTION_LIST_END ||
146 (FirstOpcode == AArch64::MOVZXi &&
147 SecondMI.getOperand(3).getImm() == 16) ||
Florian Hahnfd44ca62017-06-19 13:45:41 +0000148 (FirstOpcode == AArch64::MOVKXi &&
149 FirstMI->getOperand(3).getImm() == 32 &&
Florian Hahn5f746c82017-06-19 12:53:31 +0000150 SecondMI.getOperand(3).getImm() == 48);
Evandro Menezes455382e2017-02-01 02:54:42 +0000151 }
152
Evandro Menezes94edf022017-02-01 02:54:34 +0000153 return false;
154}
155
Evandro Menezes94edf022017-02-01 02:54:34 +0000156} // end namespace
157
158
159namespace llvm {
160
161std::unique_ptr<ScheduleDAGMutation> createAArch64MacroFusionDAGMutation () {
Florian Hahn5f746c82017-06-19 12:53:31 +0000162 return createMacroFusionDAGMutation(shouldScheduleAdjacent);
Evandro Menezes94edf022017-02-01 02:54:34 +0000163}
164
165} // end namespace llvm