xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/VE/VEInstrInfo.cpp (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
1*480093f4SDimitry Andric //===-- VEInstrInfo.cpp - VE Instruction Information ----------------------===//
2*480093f4SDimitry Andric //
3*480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*480093f4SDimitry Andric //
7*480093f4SDimitry Andric //===----------------------------------------------------------------------===//
8*480093f4SDimitry Andric //
9*480093f4SDimitry Andric // This file contains the VE implementation of the TargetInstrInfo class.
10*480093f4SDimitry Andric //
11*480093f4SDimitry Andric //===----------------------------------------------------------------------===//
12*480093f4SDimitry Andric 
13*480093f4SDimitry Andric #include "VEInstrInfo.h"
14*480093f4SDimitry Andric #include "VE.h"
15*480093f4SDimitry Andric #include "VESubtarget.h"
16*480093f4SDimitry Andric #include "llvm/ADT/STLExtras.h"
17*480093f4SDimitry Andric #include "llvm/ADT/SmallVector.h"
18*480093f4SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
19*480093f4SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
20*480093f4SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
21*480093f4SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
22*480093f4SDimitry Andric #include "llvm/Support/CommandLine.h"
23*480093f4SDimitry Andric #include "llvm/Support/Debug.h"
24*480093f4SDimitry Andric #include "llvm/Support/ErrorHandling.h"
25*480093f4SDimitry Andric #include "llvm/Support/TargetRegistry.h"
26*480093f4SDimitry Andric 
27*480093f4SDimitry Andric #define DEBUG_TYPE "ve"
28*480093f4SDimitry Andric 
29*480093f4SDimitry Andric using namespace llvm;
30*480093f4SDimitry Andric 
31*480093f4SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
32*480093f4SDimitry Andric #include "VEGenInstrInfo.inc"
33*480093f4SDimitry Andric 
34*480093f4SDimitry Andric // Pin the vtable to this file.
35*480093f4SDimitry Andric void VEInstrInfo::anchor() {}
36*480093f4SDimitry Andric 
37*480093f4SDimitry Andric VEInstrInfo::VEInstrInfo(VESubtarget &ST)
38*480093f4SDimitry Andric     : VEGenInstrInfo(VE::ADJCALLSTACKDOWN, VE::ADJCALLSTACKUP), RI(),
39*480093f4SDimitry Andric       Subtarget(ST) {}
40*480093f4SDimitry Andric 
41*480093f4SDimitry Andric bool VEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
42*480093f4SDimitry Andric   switch (MI.getOpcode()) {
43*480093f4SDimitry Andric   case VE::EXTEND_STACK: {
44*480093f4SDimitry Andric     return expandExtendStackPseudo(MI);
45*480093f4SDimitry Andric   }
46*480093f4SDimitry Andric   case VE::EXTEND_STACK_GUARD: {
47*480093f4SDimitry Andric     MI.eraseFromParent(); // The pseudo instruction is gone now.
48*480093f4SDimitry Andric     return true;
49*480093f4SDimitry Andric   }
50*480093f4SDimitry Andric   }
51*480093f4SDimitry Andric   return false;
52*480093f4SDimitry Andric }
53*480093f4SDimitry Andric 
54*480093f4SDimitry Andric bool VEInstrInfo::expandExtendStackPseudo(MachineInstr &MI) const {
55*480093f4SDimitry Andric   MachineBasicBlock &MBB = *MI.getParent();
56*480093f4SDimitry Andric   MachineFunction &MF = *MBB.getParent();
57*480093f4SDimitry Andric   const VEInstrInfo &TII =
58*480093f4SDimitry Andric       *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
59*480093f4SDimitry Andric   DebugLoc dl = MBB.findDebugLoc(MI);
60*480093f4SDimitry Andric 
61*480093f4SDimitry Andric   // Create following instructions and multiple basic blocks.
62*480093f4SDimitry Andric   //
63*480093f4SDimitry Andric   // thisBB:
64*480093f4SDimitry Andric   //   brge.l.t %sp, %sl, sinkBB
65*480093f4SDimitry Andric   // syscallBB:
66*480093f4SDimitry Andric   //   ld      %s61, 0x18(, %tp)        // load param area
67*480093f4SDimitry Andric   //   or      %s62, 0, %s0             // spill the value of %s0
68*480093f4SDimitry Andric   //   lea     %s63, 0x13b              // syscall # of grow
69*480093f4SDimitry Andric   //   shm.l   %s63, 0x0(%s61)          // store syscall # at addr:0
70*480093f4SDimitry Andric   //   shm.l   %sl, 0x8(%s61)           // store old limit at addr:8
71*480093f4SDimitry Andric   //   shm.l   %sp, 0x10(%s61)          // store new limit at addr:16
72*480093f4SDimitry Andric   //   monc                             // call monitor
73*480093f4SDimitry Andric   //   or      %s0, 0, %s62             // restore the value of %s0
74*480093f4SDimitry Andric   // sinkBB:
75*480093f4SDimitry Andric 
76*480093f4SDimitry Andric   // Create new MBB
77*480093f4SDimitry Andric   MachineBasicBlock *BB = &MBB;
78*480093f4SDimitry Andric   const BasicBlock *LLVM_BB = BB->getBasicBlock();
79*480093f4SDimitry Andric   MachineBasicBlock *syscallMBB = MF.CreateMachineBasicBlock(LLVM_BB);
80*480093f4SDimitry Andric   MachineBasicBlock *sinkMBB = MF.CreateMachineBasicBlock(LLVM_BB);
81*480093f4SDimitry Andric   MachineFunction::iterator It = ++(BB->getIterator());
82*480093f4SDimitry Andric   MF.insert(It, syscallMBB);
83*480093f4SDimitry Andric   MF.insert(It, sinkMBB);
84*480093f4SDimitry Andric 
85*480093f4SDimitry Andric   // Transfer the remainder of BB and its successor edges to sinkMBB.
86*480093f4SDimitry Andric   sinkMBB->splice(sinkMBB->begin(), BB,
87*480093f4SDimitry Andric                   std::next(std::next(MachineBasicBlock::iterator(MI))),
88*480093f4SDimitry Andric                   BB->end());
89*480093f4SDimitry Andric   sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
90*480093f4SDimitry Andric 
91*480093f4SDimitry Andric   // Next, add the true and fallthrough blocks as its successors.
92*480093f4SDimitry Andric   BB->addSuccessor(syscallMBB);
93*480093f4SDimitry Andric   BB->addSuccessor(sinkMBB);
94*480093f4SDimitry Andric   BuildMI(BB, dl, TII.get(VE::BCRLrr))
95*480093f4SDimitry Andric       .addImm(VECC::CC_IGE)
96*480093f4SDimitry Andric       .addReg(VE::SX11) // %sp
97*480093f4SDimitry Andric       .addReg(VE::SX8)  // %sl
98*480093f4SDimitry Andric       .addMBB(sinkMBB);
99*480093f4SDimitry Andric 
100*480093f4SDimitry Andric   BB = syscallMBB;
101*480093f4SDimitry Andric 
102*480093f4SDimitry Andric   // Update machine-CFG edges
103*480093f4SDimitry Andric   BB->addSuccessor(sinkMBB);
104*480093f4SDimitry Andric 
105*480093f4SDimitry Andric   BuildMI(BB, dl, TII.get(VE::LDSri), VE::SX61)
106*480093f4SDimitry Andric       .addReg(VE::SX14)
107*480093f4SDimitry Andric       .addImm(0x18);
108*480093f4SDimitry Andric   BuildMI(BB, dl, TII.get(VE::ORri), VE::SX62)
109*480093f4SDimitry Andric       .addReg(VE::SX0)
110*480093f4SDimitry Andric       .addImm(0);
111*480093f4SDimitry Andric   BuildMI(BB, dl, TII.get(VE::LEAzzi), VE::SX63)
112*480093f4SDimitry Andric       .addImm(0x13b);
113*480093f4SDimitry Andric   BuildMI(BB, dl, TII.get(VE::SHMri))
114*480093f4SDimitry Andric       .addReg(VE::SX61)
115*480093f4SDimitry Andric       .addImm(0)
116*480093f4SDimitry Andric       .addReg(VE::SX63);
117*480093f4SDimitry Andric   BuildMI(BB, dl, TII.get(VE::SHMri))
118*480093f4SDimitry Andric       .addReg(VE::SX61)
119*480093f4SDimitry Andric       .addImm(8)
120*480093f4SDimitry Andric       .addReg(VE::SX8);
121*480093f4SDimitry Andric   BuildMI(BB, dl, TII.get(VE::SHMri))
122*480093f4SDimitry Andric       .addReg(VE::SX61)
123*480093f4SDimitry Andric       .addImm(16)
124*480093f4SDimitry Andric       .addReg(VE::SX11);
125*480093f4SDimitry Andric   BuildMI(BB, dl, TII.get(VE::MONC));
126*480093f4SDimitry Andric 
127*480093f4SDimitry Andric   BuildMI(BB, dl, TII.get(VE::ORri), VE::SX0)
128*480093f4SDimitry Andric       .addReg(VE::SX62)
129*480093f4SDimitry Andric       .addImm(0);
130*480093f4SDimitry Andric 
131*480093f4SDimitry Andric   MI.eraseFromParent(); // The pseudo instruction is gone now.
132*480093f4SDimitry Andric   return true;
133*480093f4SDimitry Andric }
134