1 //===- ARMMacroFusion.cpp - ARM 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 ARM implementation of the DAG scheduling 11 /// mutation to pair instructions back to back. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "ARMMacroFusion.h" 16 #include "ARMSubtarget.h" 17 #include "llvm/CodeGen/MacroFusion.h" 18 #include "llvm/CodeGen/TargetInstrInfo.h" 19 20 namespace llvm { 21 22 // Fuse AES crypto encoding or decoding. 23 static bool isAESPair(const MachineInstr *FirstMI, 24 const MachineInstr &SecondMI) { 25 // Assume the 1st instr to be a wildcard if it is unspecified. 26 unsigned FirstOpcode = 27 FirstMI ? FirstMI->getOpcode() 28 : static_cast<unsigned>(ARM::INSTRUCTION_LIST_END); 29 unsigned SecondOpcode = SecondMI.getOpcode(); 30 31 switch(SecondOpcode) { 32 // AES encode. 33 case ARM::AESMC : 34 return FirstOpcode == ARM::AESE || 35 FirstOpcode == ARM::INSTRUCTION_LIST_END; 36 // AES decode. 37 case ARM::AESIMC: 38 return FirstOpcode == ARM::AESD || 39 FirstOpcode == ARM::INSTRUCTION_LIST_END; 40 } 41 42 return false; 43 } 44 45 // Fuse literal generation. 46 static bool isLiteralsPair(const MachineInstr *FirstMI, 47 const MachineInstr &SecondMI) { 48 // Assume the 1st instr to be a wildcard if it is unspecified. 49 unsigned FirstOpcode = 50 FirstMI ? FirstMI->getOpcode() 51 : static_cast<unsigned>(ARM::INSTRUCTION_LIST_END); 52 unsigned SecondOpcode = SecondMI.getOpcode(); 53 54 // 32 bit immediate. 55 if ((FirstOpcode == ARM::INSTRUCTION_LIST_END || 56 FirstOpcode == ARM::MOVi16) && 57 SecondOpcode == ARM::MOVTi16) 58 return true; 59 60 return false; 61 } 62 63 /// Check if the instr pair, FirstMI and SecondMI, should be fused 64 /// together. Given SecondMI, when FirstMI is unspecified, then check if 65 /// SecondMI may be part of a fused pair at all. 66 static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, 67 const TargetSubtargetInfo &TSI, 68 const MachineInstr *FirstMI, 69 const MachineInstr &SecondMI) { 70 const ARMSubtarget &ST = static_cast<const ARMSubtarget&>(TSI); 71 72 if (ST.hasFuseAES() && isAESPair(FirstMI, SecondMI)) 73 return true; 74 if (ST.hasFuseLiterals() && isLiteralsPair(FirstMI, SecondMI)) 75 return true; 76 77 return false; 78 } 79 80 std::unique_ptr<ScheduleDAGMutation> createARMMacroFusionDAGMutation () { 81 return createMacroFusionDAGMutation(shouldScheduleAdjacent); 82 } 83 84 } // end namespace llvm 85