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-exception
6 //
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 
22 using namespace llvm;
23 
24 #define DEBUG_TYPE "arc-expand-pseudos"
25 
26 namespace {
27 
28 class ARCExpandPseudos : public MachineFunctionPass {
29 public:
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 
37 private:
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 
45 char ARCExpandPseudos::ID = 0;
46 
47 } // end anonymous namespace
48 
49 static 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 
62 void 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 
79 void 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 
108 void 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 
131 bool 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 
163 FunctionPass *llvm::createARCExpandPseudosPass() {
164   return new ARCExpandPseudos();
165 }
166