1356843Sdim//===-- VEInstrInfo.cpp - VE Instruction Information ----------------------===//
2356843Sdim//
3356843Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4356843Sdim// See https://llvm.org/LICENSE.txt for license information.
5356843Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6356843Sdim//
7356843Sdim//===----------------------------------------------------------------------===//
8356843Sdim//
9356843Sdim// This file contains the VE implementation of the TargetInstrInfo class.
10356843Sdim//
11356843Sdim//===----------------------------------------------------------------------===//
12356843Sdim
13356843Sdim#include "VEInstrInfo.h"
14356843Sdim#include "VE.h"
15356843Sdim#include "VESubtarget.h"
16356843Sdim#include "llvm/ADT/STLExtras.h"
17356843Sdim#include "llvm/ADT/SmallVector.h"
18356843Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
19356843Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
20356843Sdim#include "llvm/CodeGen/MachineMemOperand.h"
21356843Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
22356843Sdim#include "llvm/Support/CommandLine.h"
23356843Sdim#include "llvm/Support/Debug.h"
24356843Sdim#include "llvm/Support/ErrorHandling.h"
25356843Sdim#include "llvm/Support/TargetRegistry.h"
26356843Sdim
27356843Sdim#define DEBUG_TYPE "ve"
28356843Sdim
29356843Sdimusing namespace llvm;
30356843Sdim
31356843Sdim#define GET_INSTRINFO_CTOR_DTOR
32356843Sdim#include "VEGenInstrInfo.inc"
33356843Sdim
34356843Sdim// Pin the vtable to this file.
35356843Sdimvoid VEInstrInfo::anchor() {}
36356843Sdim
37356843SdimVEInstrInfo::VEInstrInfo(VESubtarget &ST)
38356843Sdim    : VEGenInstrInfo(VE::ADJCALLSTACKDOWN, VE::ADJCALLSTACKUP), RI(),
39356843Sdim      Subtarget(ST) {}
40356843Sdim
41356843Sdimbool VEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
42356843Sdim  switch (MI.getOpcode()) {
43356843Sdim  case VE::EXTEND_STACK: {
44356843Sdim    return expandExtendStackPseudo(MI);
45356843Sdim  }
46356843Sdim  case VE::EXTEND_STACK_GUARD: {
47356843Sdim    MI.eraseFromParent(); // The pseudo instruction is gone now.
48356843Sdim    return true;
49356843Sdim  }
50356843Sdim  }
51356843Sdim  return false;
52356843Sdim}
53356843Sdim
54356843Sdimbool VEInstrInfo::expandExtendStackPseudo(MachineInstr &MI) const {
55356843Sdim  MachineBasicBlock &MBB = *MI.getParent();
56356843Sdim  MachineFunction &MF = *MBB.getParent();
57356843Sdim  const VEInstrInfo &TII =
58356843Sdim      *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
59356843Sdim  DebugLoc dl = MBB.findDebugLoc(MI);
60356843Sdim
61356843Sdim  // Create following instructions and multiple basic blocks.
62356843Sdim  //
63356843Sdim  // thisBB:
64356843Sdim  //   brge.l.t %sp, %sl, sinkBB
65356843Sdim  // syscallBB:
66356843Sdim  //   ld      %s61, 0x18(, %tp)        // load param area
67356843Sdim  //   or      %s62, 0, %s0             // spill the value of %s0
68356843Sdim  //   lea     %s63, 0x13b              // syscall # of grow
69356843Sdim  //   shm.l   %s63, 0x0(%s61)          // store syscall # at addr:0
70356843Sdim  //   shm.l   %sl, 0x8(%s61)           // store old limit at addr:8
71356843Sdim  //   shm.l   %sp, 0x10(%s61)          // store new limit at addr:16
72356843Sdim  //   monc                             // call monitor
73356843Sdim  //   or      %s0, 0, %s62             // restore the value of %s0
74356843Sdim  // sinkBB:
75356843Sdim
76356843Sdim  // Create new MBB
77356843Sdim  MachineBasicBlock *BB = &MBB;
78356843Sdim  const BasicBlock *LLVM_BB = BB->getBasicBlock();
79356843Sdim  MachineBasicBlock *syscallMBB = MF.CreateMachineBasicBlock(LLVM_BB);
80356843Sdim  MachineBasicBlock *sinkMBB = MF.CreateMachineBasicBlock(LLVM_BB);
81356843Sdim  MachineFunction::iterator It = ++(BB->getIterator());
82356843Sdim  MF.insert(It, syscallMBB);
83356843Sdim  MF.insert(It, sinkMBB);
84356843Sdim
85356843Sdim  // Transfer the remainder of BB and its successor edges to sinkMBB.
86356843Sdim  sinkMBB->splice(sinkMBB->begin(), BB,
87356843Sdim                  std::next(std::next(MachineBasicBlock::iterator(MI))),
88356843Sdim                  BB->end());
89356843Sdim  sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
90356843Sdim
91356843Sdim  // Next, add the true and fallthrough blocks as its successors.
92356843Sdim  BB->addSuccessor(syscallMBB);
93356843Sdim  BB->addSuccessor(sinkMBB);
94356843Sdim  BuildMI(BB, dl, TII.get(VE::BCRLrr))
95356843Sdim      .addImm(VECC::CC_IGE)
96356843Sdim      .addReg(VE::SX11) // %sp
97356843Sdim      .addReg(VE::SX8)  // %sl
98356843Sdim      .addMBB(sinkMBB);
99356843Sdim
100356843Sdim  BB = syscallMBB;
101356843Sdim
102356843Sdim  // Update machine-CFG edges
103356843Sdim  BB->addSuccessor(sinkMBB);
104356843Sdim
105356843Sdim  BuildMI(BB, dl, TII.get(VE::LDSri), VE::SX61)
106356843Sdim      .addReg(VE::SX14)
107356843Sdim      .addImm(0x18);
108356843Sdim  BuildMI(BB, dl, TII.get(VE::ORri), VE::SX62)
109356843Sdim      .addReg(VE::SX0)
110356843Sdim      .addImm(0);
111356843Sdim  BuildMI(BB, dl, TII.get(VE::LEAzzi), VE::SX63)
112356843Sdim      .addImm(0x13b);
113356843Sdim  BuildMI(BB, dl, TII.get(VE::SHMri))
114356843Sdim      .addReg(VE::SX61)
115356843Sdim      .addImm(0)
116356843Sdim      .addReg(VE::SX63);
117356843Sdim  BuildMI(BB, dl, TII.get(VE::SHMri))
118356843Sdim      .addReg(VE::SX61)
119356843Sdim      .addImm(8)
120356843Sdim      .addReg(VE::SX8);
121356843Sdim  BuildMI(BB, dl, TII.get(VE::SHMri))
122356843Sdim      .addReg(VE::SX61)
123356843Sdim      .addImm(16)
124356843Sdim      .addReg(VE::SX11);
125356843Sdim  BuildMI(BB, dl, TII.get(VE::MONC));
126356843Sdim
127356843Sdim  BuildMI(BB, dl, TII.get(VE::ORri), VE::SX0)
128356843Sdim      .addReg(VE::SX62)
129356843Sdim      .addImm(0);
130356843Sdim
131356843Sdim  MI.eraseFromParent(); // The pseudo instruction is gone now.
132356843Sdim  return true;
133356843Sdim}
134