166 lines · cpp
1//===- ARCExpandPseudosPass - ARC expand pseudo loads -----------*- C++ -*-===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This pass expands stores with large offsets into an appropriate sequence.10//===----------------------------------------------------------------------===//11 12#include "ARC.h"13#include "ARCInstrInfo.h"14#include "ARCRegisterInfo.h"15#include "ARCSubtarget.h"16#include "MCTargetDesc/ARCInfo.h"17#include "llvm/ADT/Statistic.h"18#include "llvm/CodeGen/MachineFunctionPass.h"19#include "llvm/CodeGen/MachineInstrBuilder.h"20#include "llvm/CodeGen/MachineRegisterInfo.h"21 22using namespace llvm;23 24#define DEBUG_TYPE "arc-expand-pseudos"25 26namespace {27 28class ARCExpandPseudos : public MachineFunctionPass {29public:30 static char ID;31 ARCExpandPseudos() : MachineFunctionPass(ID) {}32 33 bool runOnMachineFunction(MachineFunction &Fn) override;34 35 StringRef getPassName() const override { return "ARC Expand Pseudos"; }36 37private:38 void expandStore(MachineFunction &, MachineBasicBlock::iterator);39 void expandCTLZ(MachineFunction &, MachineBasicBlock::iterator);40 void expandCTTZ(MachineFunction &, MachineBasicBlock::iterator);41 42 const ARCInstrInfo *TII;43};44 45char ARCExpandPseudos::ID = 0;46 47} // end anonymous namespace48 49static unsigned getMappedOp(unsigned PseudoOp) {50 switch (PseudoOp) {51 case ARC::ST_FAR:52 return ARC::ST_rs9;53 case ARC::STH_FAR:54 return ARC::STH_rs9;55 case ARC::STB_FAR:56 return ARC::STB_rs9;57 default:58 llvm_unreachable("Unhandled pseudo op.");59 }60}61 62void ARCExpandPseudos::expandStore(MachineFunction &MF,63 MachineBasicBlock::iterator SII) {64 MachineInstr &SI = *SII;65 Register AddrReg = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass);66 Register AddOpc =67 isUInt<6>(SI.getOperand(2).getImm()) ? ARC::ADD_rru6 : ARC::ADD_rrlimm;68 BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(AddOpc), AddrReg)69 .addReg(SI.getOperand(1).getReg())70 .addImm(SI.getOperand(2).getImm());71 BuildMI(*SI.getParent(), SI, SI.getDebugLoc(),72 TII->get(getMappedOp(SI.getOpcode())))73 .addReg(SI.getOperand(0).getReg())74 .addReg(AddrReg)75 .addImm(0);76 SI.eraseFromParent();77}78 79void ARCExpandPseudos::expandCTLZ(MachineFunction &MF,80 MachineBasicBlock::iterator MII) {81 // Expand:82 // %R2<def> = CTLZ %R0, %STATUS<imp-def>83 // To:84 // %R2<def> = FLS_f_rr %R0, %STATUS<imp-def>85 // %R2<def,tied1> = MOV_cc_ru6 %R2<tied0>, 32, pred:1, %STATUS<imp-use>86 // %R2<def,tied1> = RSUB_cc_rru6 %R2<tied0>, 31, pred:2, %STATUS<imp-use>87 MachineInstr &MI = *MII;88 const MachineOperand &Dest = MI.getOperand(0);89 const MachineOperand &Src = MI.getOperand(1);90 Register Ra = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass);91 Register Rb = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass);92 93 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(ARC::FLS_f_rr), Ra)94 .add(Src);95 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(ARC::MOV_cc_ru6), Rb)96 .addImm(32)97 .addImm(ARCCC::EQ)98 .addReg(Ra);99 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(ARC::RSUB_cc_rru6))100 .add(Dest)101 .addImm(31)102 .addImm(ARCCC::NE)103 .addReg(Rb);104 105 MI.eraseFromParent();106}107 108void ARCExpandPseudos::expandCTTZ(MachineFunction &MF,109 MachineBasicBlock::iterator MII) {110 // Expand:111 // %R0<def> = CTTZ %R0<kill>, %STATUS<imp-def>112 // To:113 // %R0<def> = FFS_f_rr %R0<kill>, %STATUS<imp-def>114 // %R0<def,tied1> = MOVcc_ru6 %R0<tied0>, 32, pred:1, %STATUS<imp-use>115 MachineInstr &MI = *MII;116 const MachineOperand &Dest = MI.getOperand(0);117 const MachineOperand &Src = MI.getOperand(1);118 Register R = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass);119 120 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(ARC::FFS_f_rr), R)121 .add(Src);122 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(ARC::MOV_cc_ru6))123 .add(Dest)124 .addImm(32)125 .addImm(ARCCC::EQ)126 .addReg(R);127 128 MI.eraseFromParent();129}130 131bool ARCExpandPseudos::runOnMachineFunction(MachineFunction &MF) {132 const ARCSubtarget *STI = &MF.getSubtarget<ARCSubtarget>();133 TII = STI->getInstrInfo();134 bool Expanded = false;135 for (auto &MBB : MF) {136 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();137 while (MBBI != E) {138 MachineBasicBlock::iterator NMBBI = std::next(MBBI);139 switch (MBBI->getOpcode()) {140 case ARC::ST_FAR:141 case ARC::STH_FAR:142 case ARC::STB_FAR:143 expandStore(MF, MBBI);144 Expanded = true;145 break;146 case ARC::CTLZ:147 expandCTLZ(MF, MBBI);148 Expanded = true;149 break;150 case ARC::CTTZ:151 expandCTTZ(MF, MBBI);152 Expanded = true;153 break;154 default:155 break;156 }157 MBBI = NMBBI;158 }159 }160 return Expanded;161}162 163FunctionPass *llvm::createARCExpandPseudosPass() {164 return new ARCExpandPseudos();165}166