LLVM 23.0.0git
WebAssemblyRegisterInfo.cpp
Go to the documentation of this file.
1//===-- WebAssemblyRegisterInfo.cpp - WebAssembly Register 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/// \file
10/// This file contains the WebAssembly implementation of the
11/// TargetRegisterInfo class.
12///
13//===----------------------------------------------------------------------===//
14
27using namespace llvm;
28
29#define DEBUG_TYPE "wasm-reg-info"
30
31#define GET_REGINFO_TARGET_DESC
32#include "WebAssemblyGenRegisterInfo.inc"
33
36
37const MCPhysReg *
39 static const MCPhysReg CalleeSavedRegs[] = {0};
40 return CalleeSavedRegs;
41}
42
45 BitVector Reserved(getNumRegs());
46 for (auto Reg : {WebAssembly::SP32, WebAssembly::SP64, WebAssembly::FP32,
47 WebAssembly::FP64})
48 Reserved.set(Reg);
49 return Reserved;
50}
51
53 MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum,
54 RegScavenger * /*RS*/) const {
55 assert(SPAdj == 0);
56 MachineInstr &MI = *II;
57
58 MachineBasicBlock &MBB = *MI.getParent();
59 MachineFunction &MF = *MBB.getParent();
61 int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
62 const MachineFrameInfo &MFI = MF.getFrameInfo();
63 int64_t FrameOffset = MFI.getStackSize() + MFI.getObjectOffset(FrameIndex);
64
65 assert(MFI.getObjectSize(FrameIndex) != 0 &&
66 "We assume that variable-sized objects have already been lowered, "
67 "and don't use FrameIndex operands.");
68 Register FrameRegister = getFrameRegister(MF);
69
70 // If this is the address operand of a load or store, make it relative to SP
71 // and fold the frame offset directly in.
72 unsigned AddrOperandNum = WebAssembly::getNamedOperandIdx(
73 MI.getOpcode(), WebAssembly::OpName::addr);
74 if (AddrOperandNum == FIOperandNum) {
75 unsigned OffsetOperandNum = WebAssembly::getNamedOperandIdx(
76 MI.getOpcode(), WebAssembly::OpName::off);
77 assert(FrameOffset >= 0 && MI.getOperand(OffsetOperandNum).getImm() >= 0);
78 int64_t Offset = MI.getOperand(OffsetOperandNum).getImm() + FrameOffset;
79
80 if (static_cast<uint64_t>(Offset) <= std::numeric_limits<uint32_t>::max()) {
81 MI.getOperand(OffsetOperandNum).setImm(Offset);
82 MI.getOperand(FIOperandNum)
83 .ChangeToRegister(FrameRegister, /*isDef=*/false);
84 return false;
85 }
86 }
87
88 // If this is an address being added to a constant, fold the frame offset
89 // into the constant.
90 if (MI.getOpcode() == WebAssemblyFrameLowering::getOpcAdd(MF)) {
91 MachineOperand &OtherMO = MI.getOperand(3 - FIOperandNum);
92 if (OtherMO.isReg()) {
93 Register OtherMOReg = OtherMO.getReg();
94 if (OtherMOReg.isVirtual()) {
95 MachineInstr *Def = MF.getRegInfo().getUniqueVRegDef(OtherMOReg);
96 // TODO: For now we just opportunistically do this in the case where
97 // the CONST_I32/64 happens to have exactly one def and one use. We
98 // should generalize this to optimize in more cases.
99 if (Def && Def->getOpcode() ==
101 MRI.hasOneNonDBGUse(Def->getOperand(0).getReg())) {
102 MachineOperand &ImmMO = Def->getOperand(1);
103 if (ImmMO.isImm()) {
104 ImmMO.setImm(ImmMO.getImm() + uint32_t(FrameOffset));
105 MI.getOperand(FIOperandNum)
106 .ChangeToRegister(FrameRegister, /*isDef=*/false);
107 return false;
108 }
109 }
110 }
111 }
112 }
113
114 // Otherwise create an i32/64.add SP, offset and make it the operand.
115 const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
116
117 unsigned FIRegOperand = FrameRegister;
118 if (FrameOffset) {
119 // Create i32/64.add SP, offset and make it the operand.
120 const TargetRegisterClass *PtrRC =
123 BuildMI(MBB, *II, II->getDebugLoc(),
125 OffsetOp)
126 .addImm(FrameOffset);
127 FIRegOperand = MRI.createVirtualRegister(PtrRC);
128 BuildMI(MBB, *II, II->getDebugLoc(),
130 FIRegOperand)
131 .addReg(FrameRegister)
133 }
134 MI.getOperand(FIOperandNum).ChangeToRegister(FIRegOperand, /*isDef=*/false);
135 return false;
136}
137
140 // If the PReg has been replaced by a VReg, return that.
141 const auto &MFI = MF.getInfo<WebAssemblyFunctionInfo>();
142 if (MFI->isFrameBaseVirtual())
143 return MFI->getFrameBaseVreg();
144 static const unsigned Regs[2][2] = {
145 /* !isArch64Bit isArch64Bit */
146 /* !hasFP */ {WebAssembly::SP32, WebAssembly::SP64},
147 /* hasFP */ {WebAssembly::FP32, WebAssembly::FP64}};
148 const WebAssemblyFrameLowering *TFI = getFrameLowering(MF);
149 return Regs[TFI->hasFP(MF)][TT.isArch64Bit()];
150}
151
154 assert(Kind == 0 && "Only one kind of pointer on WebAssembly");
155 return TT.getArch() == Triple::wasm64 ? &WebAssembly::I64RegClass
156 : &WebAssembly::I32RegClass;
157}
158
160 switch (RB.getID()) {
161 case WebAssembly::I32RegBankID:
162 return WebAssembly::I32RegClass;
163 case WebAssembly::I64RegBankID:
164 return WebAssembly::I64RegClass;
165 case WebAssembly::F32RegBankID:
166 return WebAssembly::F32RegClass;
167 case WebAssembly::F64RegBankID:
168 return WebAssembly::F64RegClass;
169 case WebAssembly::EXNREFRegBankID:
170 return WebAssembly::EXNREFRegClass;
171 case WebAssembly::EXTERNREFRegBankID:
172 return WebAssembly::EXTERNREFRegClass;
173 case WebAssembly::FUNCREFRegBankID:
174 return WebAssembly::FUNCREFRegClass;
175 case WebAssembly::V128RegBankID:
176 return WebAssembly::V128RegClass;
177 default:
178 llvm_unreachable("Found unexpected RegisterBank in `getRegClassForBank`");
179 }
180}
181
184 const MachineOperand &MO, const MachineRegisterInfo &MRI) const {
185 assert(MO.isReg());
186
187 const RegClassOrRegBank &RegClassOrBank =
189
190 if (RegClassOrBank.isNull())
191 return nullptr;
192
193 const TargetRegisterClass *DefRC =
195
196 if (!DefRC) {
197 const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
198 DefRC = &getRegClassForBank(RB);
199 }
200
201 return DefRC;
202}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
uint64_t IntrinsicInst * II
This class implements WebAssembly-specific bits of TargetFrameLowering class.
This file contains the WebAssembly implementation of the TargetInstrInfo class.
This file provides WebAssembly-specific target descriptions.
This file declares WebAssembly-specific per-machine-function information.
This file declares the targeting of the RegisterBankInfo class for WebAssembly.
static const TargetRegisterClass & getRegClassForBank(const RegisterBank &RB)
This file contains the WebAssembly implementation of the WebAssemblyRegisterInfo class.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const RegClassOrRegBank & getRegClassOrRegBank(Register Reg) const
Return the register bank or register class of Reg.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
bool isNull() const
Test if the pointer held in the union is null, regardless of which type it is.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual const TargetRegisterClass * getPointerRegClass(unsigned Kind=0) const
Returns a TargetRegisterClass used for pointer values.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
static unsigned getOpcAdd(const MachineFunction &MF)
static unsigned getOpcConst(const MachineFunction &MF)
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
const TargetRegisterClass * getConstrainedRegClassForOperand(const MachineOperand &MO, const MachineRegisterInfo &MRI) const override
bool eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, unsigned FIOperandNum, RegScavenger *RS=nullptr) const override
Register getFrameRegister(const MachineFunction &MF) const override
BitVector getReservedRegs(const MachineFunction &MF) const override
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
const TargetRegisterClass * getPointerRegClass(unsigned Kind=0) const override
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
PointerUnion< const TargetRegisterClass *, const RegisterBank * > RegClassOrRegBank
Convenient type to represent either a register class or a register bank.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559