1 //===-- VEInstrInfo.cpp - VE Instruction Information ----------------------===//
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 file contains the VE implementation of the TargetInstrInfo class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "VEInstrInfo.h"
14 #include "VE.h"
15 #include "VESubtarget.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/CodeGen/MachineFrameInfo.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/CodeGen/MachineMemOperand.h"
21 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #include "llvm/Support/CommandLine.h"
23 #include "llvm/Support/Debug.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/TargetRegistry.h"
26 
27 #define DEBUG_TYPE "ve"
28 
29 using namespace llvm;
30 
31 #define GET_INSTRINFO_CTOR_DTOR
32 #include "VEGenInstrInfo.inc"
33 
34 // Pin the vtable to this file.
35 void VEInstrInfo::anchor() {}
36 
37 VEInstrInfo::VEInstrInfo(VESubtarget &ST)
38     : VEGenInstrInfo(VE::ADJCALLSTACKDOWN, VE::ADJCALLSTACKUP), RI(),
39       Subtarget(ST) {}
40 
41 static bool IsAliasOfSX(Register Reg) {
42   return VE::I8RegClass.contains(Reg) || VE::I16RegClass.contains(Reg) ||
43          VE::I32RegClass.contains(Reg) || VE::I64RegClass.contains(Reg) ||
44          VE::F32RegClass.contains(Reg);
45 }
46 
47 void VEInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
48                               MachineBasicBlock::iterator I, const DebugLoc &DL,
49                               MCRegister DestReg, MCRegister SrcReg,
50                               bool KillSrc) const {
51 
52   if (IsAliasOfSX(SrcReg) && IsAliasOfSX(DestReg)) {
53     BuildMI(MBB, I, DL, get(VE::ORri), DestReg)
54         .addReg(SrcReg, getKillRegState(KillSrc))
55         .addImm(0);
56   } else {
57     const TargetRegisterInfo *TRI = &getRegisterInfo();
58     dbgs() << "Impossible reg-to-reg copy from " << printReg(SrcReg, TRI)
59            << " to " << printReg(DestReg, TRI) << "\n";
60     llvm_unreachable("Impossible reg-to-reg copy");
61   }
62 }
63 
64 bool VEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
65   switch (MI.getOpcode()) {
66   case VE::EXTEND_STACK: {
67     return expandExtendStackPseudo(MI);
68   }
69   case VE::EXTEND_STACK_GUARD: {
70     MI.eraseFromParent(); // The pseudo instruction is gone now.
71     return true;
72   }
73   }
74   return false;
75 }
76 
77 bool VEInstrInfo::expandExtendStackPseudo(MachineInstr &MI) const {
78   MachineBasicBlock &MBB = *MI.getParent();
79   MachineFunction &MF = *MBB.getParent();
80   const VEInstrInfo &TII =
81       *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
82   DebugLoc dl = MBB.findDebugLoc(MI);
83 
84   // Create following instructions and multiple basic blocks.
85   //
86   // thisBB:
87   //   brge.l.t %sp, %sl, sinkBB
88   // syscallBB:
89   //   ld      %s61, 0x18(, %tp)        // load param area
90   //   or      %s62, 0, %s0             // spill the value of %s0
91   //   lea     %s63, 0x13b              // syscall # of grow
92   //   shm.l   %s63, 0x0(%s61)          // store syscall # at addr:0
93   //   shm.l   %sl, 0x8(%s61)           // store old limit at addr:8
94   //   shm.l   %sp, 0x10(%s61)          // store new limit at addr:16
95   //   monc                             // call monitor
96   //   or      %s0, 0, %s62             // restore the value of %s0
97   // sinkBB:
98 
99   // Create new MBB
100   MachineBasicBlock *BB = &MBB;
101   const BasicBlock *LLVM_BB = BB->getBasicBlock();
102   MachineBasicBlock *syscallMBB = MF.CreateMachineBasicBlock(LLVM_BB);
103   MachineBasicBlock *sinkMBB = MF.CreateMachineBasicBlock(LLVM_BB);
104   MachineFunction::iterator It = ++(BB->getIterator());
105   MF.insert(It, syscallMBB);
106   MF.insert(It, sinkMBB);
107 
108   // Transfer the remainder of BB and its successor edges to sinkMBB.
109   sinkMBB->splice(sinkMBB->begin(), BB,
110                   std::next(std::next(MachineBasicBlock::iterator(MI))),
111                   BB->end());
112   sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
113 
114   // Next, add the true and fallthrough blocks as its successors.
115   BB->addSuccessor(syscallMBB);
116   BB->addSuccessor(sinkMBB);
117   BuildMI(BB, dl, TII.get(VE::BCRLrr))
118       .addImm(VECC::CC_IGE)
119       .addReg(VE::SX11) // %sp
120       .addReg(VE::SX8)  // %sl
121       .addMBB(sinkMBB);
122 
123   BB = syscallMBB;
124 
125   // Update machine-CFG edges
126   BB->addSuccessor(sinkMBB);
127 
128   BuildMI(BB, dl, TII.get(VE::LDSri), VE::SX61)
129       .addReg(VE::SX14)
130       .addImm(0x18);
131   BuildMI(BB, dl, TII.get(VE::ORri), VE::SX62)
132       .addReg(VE::SX0)
133       .addImm(0);
134   BuildMI(BB, dl, TII.get(VE::LEAzzi), VE::SX63)
135       .addImm(0x13b);
136   BuildMI(BB, dl, TII.get(VE::SHMri))
137       .addReg(VE::SX61)
138       .addImm(0)
139       .addReg(VE::SX63);
140   BuildMI(BB, dl, TII.get(VE::SHMri))
141       .addReg(VE::SX61)
142       .addImm(8)
143       .addReg(VE::SX8);
144   BuildMI(BB, dl, TII.get(VE::SHMri))
145       .addReg(VE::SX61)
146       .addImm(16)
147       .addReg(VE::SX11);
148   BuildMI(BB, dl, TII.get(VE::MONC));
149 
150   BuildMI(BB, dl, TII.get(VE::ORri), VE::SX0)
151       .addReg(VE::SX62)
152       .addImm(0);
153 
154   MI.eraseFromParent(); // The pseudo instruction is gone now.
155   return true;
156 }
157