1 //===- 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 // 10 /// \file This file contains the AArch64 implementation of the DAG scheduling 11 /// mutation to pair instructions back to back. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "AArch64Subtarget.h" 16 #include "llvm/CodeGen/MacroFusion.h" 17 #include "llvm/CodeGen/TargetInstrInfo.h" 18 19 using namespace llvm; 20 21 namespace { 22 23 /// \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. 26 static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, 27 const TargetSubtargetInfo &TSI, 28 const MachineInstr *FirstMI, 29 const MachineInstr &SecondMI) { 30 const AArch64InstrInfo &II = static_cast<const AArch64InstrInfo&>(TII); 31 const AArch64Subtarget &ST = static_cast<const AArch64Subtarget&>(TSI); 32 33 // Assume wildcards for unspecified instrs. 34 unsigned FirstOpcode = 35 FirstMI ? FirstMI->getOpcode() 36 : static_cast<unsigned>(AArch64::INSTRUCTION_LIST_END); 37 unsigned SecondOpcode = SecondMI.getOpcode(); 38 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... 69 return !II.hasShiftedReg(*FirstMI); 70 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... 111 return !II.hasShiftedReg(*FirstMI); 112 case AArch64::INSTRUCTION_LIST_END: 113 return true; 114 } 115 116 if (ST.hasFuseAES()) 117 // Fuse AES crypto operations. 118 switch(SecondOpcode) { 119 // AES encode. 120 case AArch64::AESMCrr: 121 case AArch64::AESMCrrTied: 122 return FirstOpcode == AArch64::AESErr || 123 FirstOpcode == AArch64::INSTRUCTION_LIST_END; 124 // AES decode. 125 case AArch64::AESIMCrr: 126 case AArch64::AESIMCrrTied: 127 return FirstOpcode == AArch64::AESDrr || 128 FirstOpcode == AArch64::INSTRUCTION_LIST_END; 129 } 130 131 if (ST.hasFuseLiterals()) 132 // Fuse literal generation operations. 133 switch (SecondOpcode) { 134 // PC relative address. 135 case AArch64::ADDXri: 136 return FirstOpcode == AArch64::ADRP || 137 FirstOpcode == AArch64::INSTRUCTION_LIST_END; 138 // 32 bit immediate. 139 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. 144 case AArch64::MOVKXi: 145 return FirstOpcode == AArch64::INSTRUCTION_LIST_END || 146 (FirstOpcode == AArch64::MOVZXi && 147 SecondMI.getOperand(3).getImm() == 16) || 148 (FirstOpcode == AArch64::MOVKXi && 149 FirstMI->getOperand(3).getImm() == 32 && 150 SecondMI.getOperand(3).getImm() == 48); 151 } 152 153 return false; 154 } 155 156 } // end namespace 157 158 159 namespace llvm { 160 161 std::unique_ptr<ScheduleDAGMutation> createAArch64MacroFusionDAGMutation () { 162 return createMacroFusionDAGMutation(shouldScheduleAdjacent); 163 } 164 165 } // end namespace llvm 166