blob: ef1b5bcc65a96aa16e7e67bd8e529573dd8ed988 [file]
//===-- WebAssemblyRegisterBankInfo.cpp -------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
/// This file implements the targeting of the RegisterBankInfo class for
/// WebAssembly.
/// \todo This should be generated by TableGen.
//===----------------------------------------------------------------------===//
#include "WebAssemblyRegisterBankInfo.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "WebAssemblyRegisterInfo.h"
#include "WebAssemblySubtarget.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#define GET_TARGET_REGBANK_IMPL
#include "WebAssemblyGenRegisterBank.inc"
namespace llvm {
namespace WebAssembly {
enum PartialMappingIdx {
PMI_None = -1,
PMI_I32 = 1,
PMI_I64,
PMI_Min = PMI_I32,
};
enum ValueMappingIdx {
InvalidIdx = 0,
I32Idx = 1,
I64Idx = 5,
};
const RegisterBankInfo::PartialMapping PartMappings[]{{0, 32, I32RegBank},
{0, 64, I64RegBank}};
const RegisterBankInfo::ValueMapping ValueMappings[] = {
// invalid
{nullptr, 0},
// up to 4 operands as I32
{&PartMappings[PMI_I32 - PMI_Min], 1},
{&PartMappings[PMI_I32 - PMI_Min], 1},
{&PartMappings[PMI_I32 - PMI_Min], 1},
{&PartMappings[PMI_I32 - PMI_Min], 1},
// up to 4 operands as I64
{&PartMappings[PMI_I64 - PMI_Min], 1},
{&PartMappings[PMI_I64 - PMI_Min], 1},
{&PartMappings[PMI_I64 - PMI_Min], 1},
{&PartMappings[PMI_I64 - PMI_Min], 1},
};
} // namespace WebAssembly
} // namespace llvm
using namespace llvm;
WebAssemblyRegisterBankInfo::WebAssemblyRegisterBankInfo(
const TargetRegisterInfo &TRI) {}
const RegisterBankInfo::InstructionMapping &
WebAssemblyRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
unsigned Opc = MI.getOpcode();
const MachineFunction &MF = *MI.getParent()->getParent();
const MachineRegisterInfo &MRI = MF.getRegInfo();
const WebAssemblySubtarget &STI = MF.getSubtarget<WebAssemblySubtarget>();
const WebAssemblyRegisterInfo &TRI = *STI.getRegisterInfo();
if ((Opc != TargetOpcode::COPY && !isPreISelGenericOpcode(Opc)) ||
Opc == TargetOpcode::G_PHI) {
const RegisterBankInfo::InstructionMapping &Mapping =
getInstrMappingImpl(MI);
if (Mapping.isValid())
return Mapping;
}
const unsigned NumOperands = MI.getNumOperands();
const ValueMapping *OperandsMapping = nullptr;
unsigned MappingID = DefaultMappingID;
const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());
unsigned Op0Size = Op0Ty.getSizeInBits();
auto &Op0IntValueMapping =
WebAssembly::ValueMappings[Op0Size == 64 ? WebAssembly::I64Idx
: WebAssembly::I32Idx];
using namespace TargetOpcode;
switch (Opc) {
case G_CONSTANT:
OperandsMapping = getOperandsMapping({&Op0IntValueMapping, nullptr});
break;
case G_IMPLICIT_DEF:
OperandsMapping = &Op0IntValueMapping;
break;
case G_ADD:
case G_SUB:
case G_MUL:
case G_UDIV:
case G_SDIV:
case G_UREM:
case G_SREM:
case G_AND:
case G_OR:
case G_XOR:
case G_ASHR:
case G_LSHR:
case G_SHL:
case G_CTLZ:
case G_CTLZ_ZERO_UNDEF:
case G_CTTZ:
case G_CTTZ_ZERO_UNDEF:
case G_CTPOP:
case G_ROTL:
case G_ROTR:
OperandsMapping = &Op0IntValueMapping;
break;
case G_ZEXT:
case G_ANYEXT:
case G_SEXT:
case G_TRUNC: {
const LLT Op1Ty = MRI.getType(MI.getOperand(1).getReg());
unsigned Op1Size = Op1Ty.getSizeInBits();
auto &Op1IntValueMapping =
WebAssembly::ValueMappings[Op1Size == 64 ? WebAssembly::I64Idx
: WebAssembly::I32Idx];
OperandsMapping =
getOperandsMapping({&Op0IntValueMapping, &Op1IntValueMapping});
break;
}
case G_SEXT_INREG:
OperandsMapping =
getOperandsMapping({&Op0IntValueMapping, &Op0IntValueMapping, nullptr});
break;
case COPY: {
Register DstReg = MI.getOperand(0).getReg();
Register SrcReg = MI.getOperand(1).getReg();
const RegisterBank *DstRB = getRegBank(DstReg, MRI, TRI);
const RegisterBank *SrcRB = getRegBank(SrcReg, MRI, TRI);
if (!DstRB)
DstRB = SrcRB;
else if (!SrcRB)
SrcRB = DstRB;
assert(DstRB && SrcRB && "Both RegBank were nullptr");
if (DstRB != SrcRB) {
break; // for now, only allow no-op copies
}
return getInstructionMapping(
MappingID, /*Cost=*/1, &Op0IntValueMapping,
// We only care about the mapping of the destination for COPY.
1);
}
}
if (!OperandsMapping)
return getInvalidInstructionMapping();
return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
NumOperands);
}