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 15 #include "WebAssemblyRegisterInfo.h" 16 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 17 #include "WebAssemblyFrameLowering.h" 18 #include "WebAssemblyInstrInfo.h" 19 #include "WebAssemblyMachineFunctionInfo.h" 20 #include "WebAssemblySubtarget.h" 21 #include "llvm/CodeGen/MachineFrameInfo.h" 22 #include "llvm/CodeGen/MachineInstrBuilder.h" 23 #include "llvm/CodeGen/MachineRegisterInfo.h" 24 #include "llvm/CodeGen/TargetFrameLowering.h" 25 #include "llvm/Target/TargetOptions.h" 26 using namespace llvm; 27 28 #define DEBUG_TYPE "wasm-reg-info" 29 30 #define GET_REGINFO_TARGET_DESC 31 #include "WebAssemblyGenRegisterInfo.inc" 32 33 WebAssemblyRegisterInfo::WebAssemblyRegisterInfo(const Triple &TT) 34 : WebAssemblyGenRegisterInfo(0), TT(TT) {} 35 36 const MCPhysReg * 37 WebAssemblyRegisterInfo::getCalleeSavedRegs(const MachineFunction *) const { 38 static const MCPhysReg CalleeSavedRegs[] = {0}; 39 return CalleeSavedRegs; 40 } 41 42 BitVector 43 WebAssemblyRegisterInfo::getReservedRegs(const MachineFunction & /*MF*/) const { 44 BitVector Reserved(getNumRegs()); 45 for (auto Reg : {WebAssembly::SP32, WebAssembly::SP64, WebAssembly::FP32, 46 WebAssembly::FP64}) 47 Reserved.set(Reg); 48 return Reserved; 49 } 50 51 bool WebAssemblyRegisterInfo::eliminateFrameIndex( 52 MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, 53 RegScavenger * /*RS*/) const { 54 assert(SPAdj == 0); 55 MachineInstr &MI = *II; 56 57 MachineBasicBlock &MBB = *MI.getParent(); 58 MachineFunction &MF = *MBB.getParent(); 59 MachineRegisterInfo &MRI = MF.getRegInfo(); 60 int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 61 const MachineFrameInfo &MFI = MF.getFrameInfo(); 62 int64_t FrameOffset = MFI.getStackSize() + MFI.getObjectOffset(FrameIndex); 63 64 assert(MFI.getObjectSize(FrameIndex) != 0 && 65 "We assume that variable-sized objects have already been lowered, " 66 "and don't use FrameIndex operands."); 67 Register FrameRegister = getFrameRegister(MF); 68 69 // If this is the address operand of a load or store, make it relative to SP 70 // and fold the frame offset directly in. 71 unsigned AddrOperandNum = WebAssembly::getNamedOperandIdx( 72 MI.getOpcode(), WebAssembly::OpName::addr); 73 if (AddrOperandNum == FIOperandNum) { 74 unsigned OffsetOperandNum = WebAssembly::getNamedOperandIdx( 75 MI.getOpcode(), WebAssembly::OpName::off); 76 assert(FrameOffset >= 0 && MI.getOperand(OffsetOperandNum).getImm() >= 0); 77 int64_t Offset = MI.getOperand(OffsetOperandNum).getImm() + FrameOffset; 78 79 if (static_cast<uint64_t>(Offset) <= std::numeric_limits<uint32_t>::max()) { 80 MI.getOperand(OffsetOperandNum).setImm(Offset); 81 MI.getOperand(FIOperandNum) 82 .ChangeToRegister(FrameRegister, /*isDef=*/false); 83 return false; 84 } 85 } 86 87 // If this is an address being added to a constant, fold the frame offset 88 // into the constant. 89 if (MI.getOpcode() == WebAssemblyFrameLowering::getOpcAdd(MF)) { 90 MachineOperand &OtherMO = MI.getOperand(3 - FIOperandNum); 91 if (OtherMO.isReg()) { 92 Register OtherMOReg = OtherMO.getReg(); 93 if (OtherMOReg.isVirtual()) { 94 MachineInstr *Def = MF.getRegInfo().getUniqueVRegDef(OtherMOReg); 95 // TODO: For now we just opportunistically do this in the case where 96 // the CONST_I32/64 happens to have exactly one def and one use. We 97 // should generalize this to optimize in more cases. 98 if (Def && Def->getOpcode() == 99 WebAssemblyFrameLowering::getOpcConst(MF) && 100 MRI.hasOneNonDBGUse(Def->getOperand(0).getReg())) { 101 MachineOperand &ImmMO = Def->getOperand(1); 102 if (ImmMO.isImm()) { 103 ImmMO.setImm(ImmMO.getImm() + uint32_t(FrameOffset)); 104 MI.getOperand(FIOperandNum) 105 .ChangeToRegister(FrameRegister, /*isDef=*/false); 106 return false; 107 } 108 } 109 } 110 } 111 } 112 113 // Otherwise create an i32/64.add SP, offset and make it the operand. 114 const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 115 116 unsigned FIRegOperand = FrameRegister; 117 if (FrameOffset) { 118 // Create i32/64.add SP, offset and make it the operand. 119 const TargetRegisterClass *PtrRC = 120 MRI.getTargetRegisterInfo()->getPointerRegClass(MF); 121 Register OffsetOp = MRI.createVirtualRegister(PtrRC); 122 BuildMI(MBB, *II, II->getDebugLoc(), 123 TII->get(WebAssemblyFrameLowering::getOpcConst(MF)), 124 OffsetOp) 125 .addImm(FrameOffset); 126 FIRegOperand = MRI.createVirtualRegister(PtrRC); 127 BuildMI(MBB, *II, II->getDebugLoc(), 128 TII->get(WebAssemblyFrameLowering::getOpcAdd(MF)), 129 FIRegOperand) 130 .addReg(FrameRegister) 131 .addReg(OffsetOp); 132 } 133 MI.getOperand(FIOperandNum).ChangeToRegister(FIRegOperand, /*isDef=*/false); 134 return false; 135 } 136 137 Register 138 WebAssemblyRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 139 // If the PReg has been replaced by a VReg, return that. 140 const auto &MFI = MF.getInfo<WebAssemblyFunctionInfo>(); 141 if (MFI->isFrameBaseVirtual()) 142 return MFI->getFrameBaseVreg(); 143 static const unsigned Regs[2][2] = { 144 /* !isArch64Bit isArch64Bit */ 145 /* !hasFP */ {WebAssembly::SP32, WebAssembly::SP64}, 146 /* hasFP */ {WebAssembly::FP32, WebAssembly::FP64}}; 147 const WebAssemblyFrameLowering *TFI = getFrameLowering(MF); 148 return Regs[TFI->hasFP(MF)][TT.isArch64Bit()]; 149 } 150 151 const TargetRegisterClass * 152 WebAssemblyRegisterInfo::getPointerRegClass(const MachineFunction &MF, 153 unsigned Kind) const { 154 assert(Kind == 0 && "Only one kind of pointer on WebAssembly"); 155 if (MF.getSubtarget<WebAssemblySubtarget>().hasAddr64()) 156 return &WebAssembly::I64RegClass; 157 return &WebAssembly::I32RegClass; 158 } 159