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
29using namespace llvm;
30
31#define GET_INSTRINFO_CTOR_DTOR
32#include "VEGenInstrInfo.inc"
33
34// Pin the vtable to this file.
35void VEInstrInfo::anchor() {}
36
37VEInstrInfo::VEInstrInfo(VESubtarget &ST)
38    : VEGenInstrInfo(VE::ADJCALLSTACKDOWN, VE::ADJCALLSTACKUP), RI(),
39      Subtarget(ST) {}
40
41bool VEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
42  switch (MI.getOpcode()) {
43  case VE::EXTEND_STACK: {
44    return expandExtendStackPseudo(MI);
45  }
46  case VE::EXTEND_STACK_GUARD: {
47    MI.eraseFromParent(); // The pseudo instruction is gone now.
48    return true;
49  }
50  }
51  return false;
52}
53
54bool VEInstrInfo::expandExtendStackPseudo(MachineInstr &MI) const {
55  MachineBasicBlock &MBB = *MI.getParent();
56  MachineFunction &MF = *MBB.getParent();
57  const VEInstrInfo &TII =
58      *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
59  DebugLoc dl = MBB.findDebugLoc(MI);
60
61  // Create following instructions and multiple basic blocks.
62  //
63  // thisBB:
64  //   brge.l.t %sp, %sl, sinkBB
65  // syscallBB:
66  //   ld      %s61, 0x18(, %tp)        // load param area
67  //   or      %s62, 0, %s0             // spill the value of %s0
68  //   lea     %s63, 0x13b              // syscall # of grow
69  //   shm.l   %s63, 0x0(%s61)          // store syscall # at addr:0
70  //   shm.l   %sl, 0x8(%s61)           // store old limit at addr:8
71  //   shm.l   %sp, 0x10(%s61)          // store new limit at addr:16
72  //   monc                             // call monitor
73  //   or      %s0, 0, %s62             // restore the value of %s0
74  // sinkBB:
75
76  // Create new MBB
77  MachineBasicBlock *BB = &MBB;
78  const BasicBlock *LLVM_BB = BB->getBasicBlock();
79  MachineBasicBlock *syscallMBB = MF.CreateMachineBasicBlock(LLVM_BB);
80  MachineBasicBlock *sinkMBB = MF.CreateMachineBasicBlock(LLVM_BB);
81  MachineFunction::iterator It = ++(BB->getIterator());
82  MF.insert(It, syscallMBB);
83  MF.insert(It, sinkMBB);
84
85  // Transfer the remainder of BB and its successor edges to sinkMBB.
86  sinkMBB->splice(sinkMBB->begin(), BB,
87                  std::next(std::next(MachineBasicBlock::iterator(MI))),
88                  BB->end());
89  sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
90
91  // Next, add the true and fallthrough blocks as its successors.
92  BB->addSuccessor(syscallMBB);
93  BB->addSuccessor(sinkMBB);
94  BuildMI(BB, dl, TII.get(VE::BCRLrr))
95      .addImm(VECC::CC_IGE)
96      .addReg(VE::SX11) // %sp
97      .addReg(VE::SX8)  // %sl
98      .addMBB(sinkMBB);
99
100  BB = syscallMBB;
101
102  // Update machine-CFG edges
103  BB->addSuccessor(sinkMBB);
104
105  BuildMI(BB, dl, TII.get(VE::LDSri), VE::SX61)
106      .addReg(VE::SX14)
107      .addImm(0x18);
108  BuildMI(BB, dl, TII.get(VE::ORri), VE::SX62)
109      .addReg(VE::SX0)
110      .addImm(0);
111  BuildMI(BB, dl, TII.get(VE::LEAzzi), VE::SX63)
112      .addImm(0x13b);
113  BuildMI(BB, dl, TII.get(VE::SHMri))
114      .addReg(VE::SX61)
115      .addImm(0)
116      .addReg(VE::SX63);
117  BuildMI(BB, dl, TII.get(VE::SHMri))
118      .addReg(VE::SX61)
119      .addImm(8)
120      .addReg(VE::SX8);
121  BuildMI(BB, dl, TII.get(VE::SHMri))
122      .addReg(VE::SX61)
123      .addImm(16)
124      .addReg(VE::SX11);
125  BuildMI(BB, dl, TII.get(VE::MONC));
126
127  BuildMI(BB, dl, TII.get(VE::ORri), VE::SX0)
128      .addReg(VE::SX62)
129      .addImm(0);
130
131  MI.eraseFromParent(); // The pseudo instruction is gone now.
132  return true;
133}
134