mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
7fff32705f
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
222 lines
6.7 KiB
C++
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;
|
|
}
|
|
}
|