1 //===- RISCVMacroFusion.cpp - RISCV Macro Fusion --------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// \file This file contains the RISCV implementation of the DAG scheduling 10 /// mutation to pair instructions back to back. 11 // 12 //===----------------------------------------------------------------------===// 13 // 14 #include "RISCVMacroFusion.h" 15 #include "RISCVSubtarget.h" 16 #include "llvm/CodeGen/MacroFusion.h" 17 #include "llvm/CodeGen/TargetInstrInfo.h" 18 19 using namespace llvm; 20 21 // Fuse LUI followed by ADDI or ADDIW. 22 // rd = imm[31:0] which decomposes to 23 // lui rd, imm[31:12] 24 // addi(w) rd, rd, imm[11:0] 25 static bool isLUIADDI(const MachineInstr *FirstMI, 26 const MachineInstr &SecondMI) { 27 if (SecondMI.getOpcode() != RISCV::ADDI && 28 SecondMI.getOpcode() != RISCV::ADDIW) 29 return false; 30 31 // Assume the 1st instr to be a wildcard if it is unspecified. 32 if (!FirstMI) 33 return true; 34 35 if (FirstMI->getOpcode() != RISCV::LUI) 36 return false; 37 38 // The first operand of ADDI might be a frame index. 39 if (!SecondMI.getOperand(1).isReg()) 40 return false; 41 42 Register FirstDest = FirstMI->getOperand(0).getReg(); 43 44 // Destination of LUI should be the ADDI(W) source register. 45 if (SecondMI.getOperand(1).getReg() != FirstDest) 46 return false; 47 48 // If the FirstMI destination is non-virtual, it should match the SecondMI 49 // destination. 50 return FirstDest.isVirtual() || SecondMI.getOperand(0).getReg() == FirstDest; 51 } 52 53 static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, 54 const TargetSubtargetInfo &TSI, 55 const MachineInstr *FirstMI, 56 const MachineInstr &SecondMI) { 57 const RISCVSubtarget &ST = static_cast<const RISCVSubtarget &>(TSI); 58 59 if (ST.hasLUIADDIFusion() && isLUIADDI(FirstMI, SecondMI)) 60 return true; 61 62 return false; 63 } 64 65 std::unique_ptr<ScheduleDAGMutation> llvm::createRISCVMacroFusionDAGMutation() { 66 return createMacroFusionDAGMutation(shouldScheduleAdjacent); 67 } 68