1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00
llvm-mirror/utils/TableGen/InfoByHwMode.cpp
James Molloy 7fff32705f [TableGen] Support encoding per-HwMode
Much like ValueTypeByHwMode/RegInfoByHwMode, this patch allows targets
to modify an instruction's encoding based on HwMode. When the
EncodingInfos field is non-empty the Inst and Size fields of the Instruction
are ignored and taken from EncodingInfos instead.

As part of this promote getHwMode() from TargetSubtargetInfo to MCSubtargetInfo.

This is NFC for all existing targets - new code is generated only if targets
use EncodingByHwMode.

llvm-svn: 372320
2019-09-19 13:39:54 +00:00

222 lines
6.7 KiB
C++

//===--- InfoByHwMode.cpp -------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// Classes that implement data parameterized by HW modes for instruction
// selection. Currently it is ValueTypeByHwMode (parameterized ValueType),
// and RegSizeInfoByHwMode (parameterized register/spill size and alignment
// data).
//===----------------------------------------------------------------------===//
#include "CodeGenTarget.h"
#include "InfoByHwMode.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <set>
#include <string>
using namespace llvm;
std::string llvm::getModeName(unsigned Mode) {
if (Mode == DefaultMode)
return "*";
return (Twine('m') + Twine(Mode)).str();
}
ValueTypeByHwMode::ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH) {
const HwModeSelect &MS = CGH.getHwModeSelect(R);
for (const HwModeSelect::PairType &P : MS.Items) {
auto I = Map.insert({P.first, MVT(llvm::getValueType(P.second))});
assert(I.second && "Duplicate entry?");
(void)I;
}
}
ValueTypeByHwMode::ValueTypeByHwMode(Record *R, MVT T) : ValueTypeByHwMode(T) {
if (R->isSubClassOf("PtrValueType"))
PtrAddrSpace = R->getValueAsInt("AddrSpace");
}
bool ValueTypeByHwMode::operator== (const ValueTypeByHwMode &T) const {
assert(isValid() && T.isValid() && "Invalid type in assignment");
bool Simple = isSimple();
if (Simple != T.isSimple())
return false;
if (Simple)
return getSimple() == T.getSimple();
return Map == T.Map;
}
bool ValueTypeByHwMode::operator< (const ValueTypeByHwMode &T) const {
assert(isValid() && T.isValid() && "Invalid type in comparison");
// Default order for maps.
return Map < T.Map;
}
MVT &ValueTypeByHwMode::getOrCreateTypeForMode(unsigned Mode, MVT Type) {
auto F = Map.find(Mode);
if (F != Map.end())
return F->second;
// If Mode is not in the map, look up the default mode. If it exists,
// make a copy of it for Mode and return it.
auto D = Map.find(DefaultMode);
if (D != Map.end())
return Map.insert(std::make_pair(Mode, D->second)).first->second;
// If default mode is not present either, use provided Type.
return Map.insert(std::make_pair(Mode, Type)).first->second;
}
StringRef ValueTypeByHwMode::getMVTName(MVT T) {
StringRef N = llvm::getEnumName(T.SimpleTy);
N.consume_front("MVT::");
return N;
}
void ValueTypeByHwMode::writeToStream(raw_ostream &OS) const {
if (isSimple()) {
OS << getMVTName(getSimple());
return;
}
std::vector<const PairType*> Pairs;
for (const auto &P : Map)
Pairs.push_back(&P);
llvm::sort(Pairs, deref<std::less<PairType>>());
OS << '{';
for (unsigned i = 0, e = Pairs.size(); i != e; ++i) {
const PairType *P = Pairs[i];
OS << '(' << getModeName(P->first)
<< ':' << getMVTName(P->second).str() << ')';
if (i != e-1)
OS << ',';
}
OS << '}';
}
LLVM_DUMP_METHOD
void ValueTypeByHwMode::dump() const {
dbgs() << *this << '\n';
}
ValueTypeByHwMode llvm::getValueTypeByHwMode(Record *Rec,
const CodeGenHwModes &CGH) {
#ifndef NDEBUG
if (!Rec->isSubClassOf("ValueType"))
Rec->dump();
#endif
assert(Rec->isSubClassOf("ValueType") &&
"Record must be derived from ValueType");
if (Rec->isSubClassOf("HwModeSelect"))
return ValueTypeByHwMode(Rec, CGH);
return ValueTypeByHwMode(Rec, llvm::getValueType(Rec));
}
RegSizeInfo::RegSizeInfo(Record *R, const CodeGenHwModes &CGH) {
RegSize = R->getValueAsInt("RegSize");
SpillSize = R->getValueAsInt("SpillSize");
SpillAlignment = R->getValueAsInt("SpillAlignment");
}
bool RegSizeInfo::operator< (const RegSizeInfo &I) const {
return std::tie(RegSize, SpillSize, SpillAlignment) <
std::tie(I.RegSize, I.SpillSize, I.SpillAlignment);
}
bool RegSizeInfo::isSubClassOf(const RegSizeInfo &I) const {
return RegSize <= I.RegSize &&
SpillAlignment && I.SpillAlignment % SpillAlignment == 0 &&
SpillSize <= I.SpillSize;
}
void RegSizeInfo::writeToStream(raw_ostream &OS) const {
OS << "[R=" << RegSize << ",S=" << SpillSize
<< ",A=" << SpillAlignment << ']';
}
RegSizeInfoByHwMode::RegSizeInfoByHwMode(Record *R,
const CodeGenHwModes &CGH) {
const HwModeSelect &MS = CGH.getHwModeSelect(R);
for (const HwModeSelect::PairType &P : MS.Items) {
auto I = Map.insert({P.first, RegSizeInfo(P.second, CGH)});
assert(I.second && "Duplicate entry?");
(void)I;
}
}
bool RegSizeInfoByHwMode::operator< (const RegSizeInfoByHwMode &I) const {
unsigned M0 = Map.begin()->first;
return get(M0) < I.get(M0);
}
bool RegSizeInfoByHwMode::operator== (const RegSizeInfoByHwMode &I) const {
unsigned M0 = Map.begin()->first;
return get(M0) == I.get(M0);
}
bool RegSizeInfoByHwMode::isSubClassOf(const RegSizeInfoByHwMode &I) const {
unsigned M0 = Map.begin()->first;
return get(M0).isSubClassOf(I.get(M0));
}
bool RegSizeInfoByHwMode::hasStricterSpillThan(const RegSizeInfoByHwMode &I)
const {
unsigned M0 = Map.begin()->first;
const RegSizeInfo &A0 = get(M0);
const RegSizeInfo &B0 = I.get(M0);
return std::tie(A0.SpillSize, A0.SpillAlignment) >
std::tie(B0.SpillSize, B0.SpillAlignment);
}
void RegSizeInfoByHwMode::writeToStream(raw_ostream &OS) const {
typedef typename decltype(Map)::value_type PairType;
std::vector<const PairType*> Pairs;
for (const auto &P : Map)
Pairs.push_back(&P);
llvm::sort(Pairs, deref<std::less<PairType>>());
OS << '{';
for (unsigned i = 0, e = Pairs.size(); i != e; ++i) {
const PairType *P = Pairs[i];
OS << '(' << getModeName(P->first) << ':' << P->second << ')';
if (i != e-1)
OS << ',';
}
OS << '}';
}
EncodingInfoByHwMode::EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH) {
const HwModeSelect &MS = CGH.getHwModeSelect(R);
for (const HwModeSelect::PairType &P : MS.Items) {
assert(P.second && P.second->isSubClassOf("InstructionEncoding") &&
"Encoding must subclass InstructionEncoding");
auto I = Map.insert({P.first, P.second});
assert(I.second && "Duplicate entry?");
(void)I;
}
}
namespace llvm {
raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T) {
T.writeToStream(OS);
return OS;
}
raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T) {
T.writeToStream(OS);
return OS;
}
raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T) {
T.writeToStream(OS);
return OS;
}
}