aboutsummaryrefslogtreecommitdiff
path: root/backend/utils/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'backend/utils/TableGen')
-rw-r--r--backend/utils/TableGen/Common/CodeGenSelection.cpp134
-rw-r--r--backend/utils/TableGen/Common/CodeGenTarget.h19
-rw-r--r--backend/utils/TableGen/GlobalISelEmitter.cpp24
3 files changed, 109 insertions, 68 deletions
diff --git a/backend/utils/TableGen/Common/CodeGenSelection.cpp b/backend/utils/TableGen/Common/CodeGenSelection.cpp
index 88f85f7..d3bc299 100644
--- a/backend/utils/TableGen/Common/CodeGenSelection.cpp
+++ b/backend/utils/TableGen/Common/CodeGenSelection.cpp
@@ -170,6 +170,36 @@ bool CodeGenTarget::normalizeSelectionRules(NormalizedTargetModel &Result) {
}
return NormalizedSelectionTypePredicate{.Kind = Kind, .Bits = Source.Bits};
};
+ const auto NormalizeRanges = [this](const std::vector<SourceSelectionConstantRange> &Ranges,
+ TextRange PredicateRange, std::string_view PredicateName)
+ -> std::optional<std::vector<NormalizedSelectionConstantRange>> {
+ if (Ranges.empty()) {
+ fail(PredicateRange, std::string(PredicateName) + " requires at least one range");
+ return std::nullopt;
+ }
+ std::vector<NormalizedSelectionConstantRange> NormalizedRanges;
+ NormalizedRanges.reserve(Ranges.size());
+ for (const SourceSelectionConstantRange &Range : Ranges) {
+ if (Range.Minimum > Range.Maximum) {
+ fail(Range.SourceRange, std::string(PredicateName) + " range is invalid");
+ return std::nullopt;
+ }
+ NormalizedRanges.push_back({
+ .Minimum = Range.Minimum,
+ .Maximum = Range.Maximum,
+ });
+ }
+ std::ranges::sort(NormalizedRanges, {}, &NormalizedSelectionConstantRange::Minimum);
+ for (std::size_t Index = 1; Index < NormalizedRanges.size(); ++Index) {
+ const auto &Previous = NormalizedRanges[Index - 1];
+ const auto &Current = NormalizedRanges[Index];
+ if (Current.Minimum <= Previous.Maximum) {
+ fail(PredicateRange, std::string(PredicateName) + " ranges overlap");
+ return std::nullopt;
+ }
+ }
+ return NormalizedRanges;
+ };
NormalizedSelectionRule Normalized;
Normalized.Symbol = Rule.Symbol;
@@ -213,6 +243,17 @@ bool CodeGenTarget::normalizeSelectionRules(NormalizedTargetModel &Result) {
++Normalized.Specificity;
}
+ std::unordered_set<std::string> TargetPredicateSymbols;
+ for (const SourceSelectionTargetPredicate &Predicate : Rule.TargetPredicates) {
+ if (!isIdentifier(Predicate.Symbol) ||
+ !TargetPredicateSymbols.insert(Predicate.Symbol).second) {
+ fail(Predicate.Range, "selection target predicates require distinct identifiers");
+ return false;
+ }
+ Normalized.TargetPredicates.push_back(Predicate.Symbol);
+ ++Normalized.Specificity;
+ }
+
std::unordered_set<std::uint32_t> TypeOperands;
for (const SourceSelectionOperandTypePredicate &Predicate : Rule.OperandTypes) {
auto Type = NormalizeType(Predicate.Type);
@@ -261,43 +302,40 @@ bool CodeGenTarget::normalizeSelectionRules(NormalizedTargetModel &Result) {
++Normalized.Specificity;
}
+ std::unordered_set<std::uint32_t> ImmediateOperands;
+ for (const SourceSelectionOperandImmediatePredicate &Predicate : Rule.OperandImmediates) {
+ if (!ImmediateOperands.insert(Predicate.OperandIndex).second) {
+ fail(Predicate.Range, "selection operand immediate predicates require distinct operands");
+ return false;
+ }
+ auto Ranges = NormalizeRanges(Predicate.Ranges, Predicate.Range,
+ "selection operand immediate predicate");
+ if (!Ranges)
+ return false;
+ Normalized.OperandImmediates.push_back({
+ .OperandIndex = Predicate.OperandIndex,
+ .Ranges = std::move(*Ranges),
+ });
+ ++Normalized.Specificity;
+ }
+
std::unordered_set<std::uint32_t> ConstantOperands;
for (const SourceSelectionOperandDefConstantPredicate &Predicate : Rule.OperandDefConstants) {
if (!ConstantOperands.insert(Predicate.OperandIndex).second ||
(MatchInstruction != nullptr &&
- !isRegisterOperand(*MatchInstruction, Predicate.OperandIndex)) ||
- Predicate.Ranges.empty()) {
+ !isRegisterOperand(*MatchInstruction, Predicate.OperandIndex))) {
fail(Predicate.Range,
- "selection operand definition constant predicates require distinct register "
- "operands and at least one range");
+ "selection operand definition constant predicates require distinct register operands");
return false;
}
- NormalizedSelectionOperandDefConstantPredicate NormalizedPredicate{
+ auto Ranges = NormalizeRanges(Predicate.Ranges, Predicate.Range,
+ "selection operand definition constant predicate");
+ if (!Ranges)
+ return false;
+ Normalized.OperandDefConstants.push_back({
.OperandIndex = Predicate.OperandIndex,
- .Ranges = {},
- };
- for (const SourceSelectionOperandDefConstantPredicate::ConstantRange &Range :
- Predicate.Ranges) {
- if (Range.Minimum > Range.Maximum) {
- fail(Range.SourceRange, "selection operand definition constant range is invalid");
- return false;
- }
- NormalizedPredicate.Ranges.push_back({
- .Minimum = Range.Minimum,
- .Maximum = Range.Maximum,
- });
- }
- std::ranges::sort(NormalizedPredicate.Ranges, {},
- &NormalizedSelectionOperandDefConstantPredicate::Range::Minimum);
- for (std::size_t Index = 1; Index < NormalizedPredicate.Ranges.size(); ++Index) {
- const auto &Previous = NormalizedPredicate.Ranges[Index - 1];
- const auto &Current = NormalizedPredicate.Ranges[Index];
- if (Current.Minimum <= Previous.Maximum) {
- fail(Predicate.Range, "selection operand definition constant ranges overlap");
- return false;
- }
- }
- Normalized.OperandDefConstants.push_back(std::move(NormalizedPredicate));
+ .Ranges = std::move(*Ranges),
+ });
++Normalized.Specificity;
}
@@ -338,38 +376,18 @@ bool CodeGenTarget::normalizeSelectionRules(NormalizedTargetModel &Result) {
std::unordered_set<std::uint32_t> ConstantOperandsInDef;
for (const SourceSelectionOperandDefConstantPredicate &Constant :
Predicate.OperandDefConstants) {
- if (!ConstantOperandsInDef.insert(Constant.OperandIndex).second ||
- Constant.Ranges.empty()) {
- fail(Constant.Range, "selection def-use constant predicates require distinct operands "
- "and at least one range");
+ if (!ConstantOperandsInDef.insert(Constant.OperandIndex).second) {
+ fail(Constant.Range, "selection def-use constant predicates require distinct operands");
return false;
}
- NormalizedSelectionOperandDefConstantPredicate NormalizedConstant{
+ auto Ranges = NormalizeRanges(Constant.Ranges, Constant.Range,
+ "selection def-use constant predicate");
+ if (!Ranges)
+ return false;
+ NormalizedPredicate.OperandDefConstants.push_back({
.OperandIndex = Constant.OperandIndex,
- .Ranges = {},
- };
- for (const SourceSelectionOperandDefConstantPredicate::ConstantRange &Range :
- Constant.Ranges) {
- if (Range.Minimum > Range.Maximum) {
- fail(Range.SourceRange, "selection def-use constant range is invalid");
- return false;
- }
- NormalizedConstant.Ranges.push_back({
- .Minimum = Range.Minimum,
- .Maximum = Range.Maximum,
- });
- }
- std::ranges::sort(NormalizedConstant.Ranges, {},
- &NormalizedSelectionOperandDefConstantPredicate::Range::Minimum);
- for (std::size_t Index = 1; Index < NormalizedConstant.Ranges.size(); ++Index) {
- const auto &Previous = NormalizedConstant.Ranges[Index - 1];
- const auto &Current = NormalizedConstant.Ranges[Index];
- if (Current.Minimum <= Previous.Maximum) {
- fail(Constant.Range, "selection def-use constant ranges overlap");
- return false;
- }
- }
- NormalizedPredicate.OperandDefConstants.push_back(std::move(NormalizedConstant));
+ .Ranges = std::move(*Ranges),
+ });
}
Normalized.DefUsePredicates.push_back(std::move(NormalizedPredicate));
Normalized.Specificity += 1U + static_cast<std::uint32_t>(Predicate.Captures.size()) +
diff --git a/backend/utils/TableGen/Common/CodeGenTarget.h b/backend/utils/TableGen/Common/CodeGenTarget.h
index 47dd598..d66cfee 100644
--- a/backend/utils/TableGen/Common/CodeGenTarget.h
+++ b/backend/utils/TableGen/Common/CodeGenTarget.h
@@ -194,14 +194,19 @@ struct NormalizedSelectionIntegerPredicate final {
std::uint32_t Predicate = 0;
};
-struct NormalizedSelectionOperandDefConstantPredicate final {
- struct Range final {
- std::int64_t Minimum = 0;
- std::int64_t Maximum = 0;
- };
+struct NormalizedSelectionConstantRange final {
+ std::int64_t Minimum = 0;
+ std::int64_t Maximum = 0;
+};
+struct NormalizedSelectionOperandImmediatePredicate final {
+ std::uint32_t OperandIndex = 0;
+ std::vector<NormalizedSelectionConstantRange> Ranges;
+};
+
+struct NormalizedSelectionOperandDefConstantPredicate final {
std::uint32_t OperandIndex = 0;
- std::vector<Range> Ranges;
+ std::vector<NormalizedSelectionConstantRange> Ranges;
};
struct NormalizedSelectionDefUseCapture final {
@@ -259,9 +264,11 @@ struct NormalizedSelectionRule final {
std::uint32_t MatchOpcode = 0;
std::optional<NormalizedSelectionTypePredicate> ResultType;
std::optional<NormalizedSelectionIntegerPredicate> IntegerPredicate;
+ std::vector<std::string> TargetPredicates;
std::vector<NormalizedSelectionOperandTypePredicate> OperandTypes;
std::vector<NormalizedSelectionOperandBankPredicate> OperandBanks;
std::vector<NormalizedSelectionOperandClassPredicate> OperandClasses;
+ std::vector<NormalizedSelectionOperandImmediatePredicate> OperandImmediates;
std::vector<NormalizedSelectionOperandDefConstantPredicate> OperandDefConstants;
std::vector<NormalizedSelectionDefUsePredicate> DefUsePredicates;
std::vector<NormalizedSelectionTemporary> Temporaries;
diff --git a/backend/utils/TableGen/GlobalISelEmitter.cpp b/backend/utils/TableGen/GlobalISelEmitter.cpp
index 562ff7c..98568b1 100644
--- a/backend/utils/TableGen/GlobalISelEmitter.cpp
+++ b/backend/utils/TableGen/GlobalISelEmitter.cpp
@@ -42,8 +42,9 @@ void emitTypePredicate(std::ostream &Output, std::uint32_t OperandIndex,
[[nodiscard]] std::size_t instructionCount(const NormalizedSelectionRule &Rule) noexcept {
std::size_t Count = 2U + (Rule.ResultType ? 1U : 0U) + (Rule.IntegerPredicate ? 1U : 0U) +
- Rule.OperandTypes.size() + Rule.OperandBanks.size() +
- Rule.OperandClasses.size() + Rule.OperandDefConstants.size() +
+ Rule.TargetPredicates.size() + Rule.OperandTypes.size() +
+ Rule.OperandBanks.size() + Rule.OperandClasses.size() +
+ Rule.OperandImmediates.size() + Rule.OperandDefConstants.size() +
Rule.Temporaries.size() + Rule.EraseOperandDefinitions.size();
for (const NormalizedSelectionDefUsePredicate &Predicate : Rule.DefUsePredicates)
Count += 1U + Predicate.Captures.size() + Predicate.OperandDefConstants.size();
@@ -60,6 +61,9 @@ std::string emitGlobalISel(const NormalizedTargetModel &Model, std::string_view
for (const NormalizedSelectionRule &Rule : Model.SelectionRules)
InstructionCount += instructionCount(Rule);
for (const NormalizedSelectionRule &Rule : Model.SelectionRules) {
+ for (const NormalizedSelectionOperandImmediatePredicate &Predicate : Rule.OperandImmediates) {
+ ConstantRangeCount += Predicate.Ranges.size();
+ }
for (const NormalizedSelectionOperandDefConstantPredicate &Predicate :
Rule.OperandDefConstants) {
ConstantRangeCount += Predicate.Ranges.size();
@@ -81,15 +85,19 @@ std::string emitGlobalISel(const NormalizedTargetModel &Model, std::string_view
Output << "constexpr std::array<GIMatchTableConstantRange, " << ConstantRangeCount
<< "> GeneratedGlobalISelConstantRanges = {{\n";
for (const NormalizedSelectionRule &Rule : Model.SelectionRules) {
+ for (const NormalizedSelectionOperandImmediatePredicate &Predicate : Rule.OperandImmediates) {
+ for (const NormalizedSelectionConstantRange &Range : Predicate.Ranges)
+ Output << " {" << Range.Minimum << ", " << Range.Maximum << "},\n";
+ }
for (const NormalizedSelectionOperandDefConstantPredicate &Predicate :
Rule.OperandDefConstants) {
- for (const NormalizedSelectionOperandDefConstantPredicate::Range &Range : Predicate.Ranges)
+ for (const NormalizedSelectionConstantRange &Range : Predicate.Ranges)
Output << " {" << Range.Minimum << ", " << Range.Maximum << "},\n";
}
for (const NormalizedSelectionDefUsePredicate &DefUse : Rule.DefUsePredicates) {
for (const NormalizedSelectionOperandDefConstantPredicate &Predicate :
DefUse.OperandDefConstants) {
- for (const NormalizedSelectionOperandDefConstantPredicate::Range &Range : Predicate.Ranges)
+ for (const NormalizedSelectionConstantRange &Range : Predicate.Ranges)
Output << " {" << Range.Minimum << ", " << Range.Maximum << "},\n";
}
}
@@ -106,12 +114,20 @@ std::string emitGlobalISel(const NormalizedTargetModel &Model, std::string_view
if (Rule.IntegerPredicate)
emitInstruction(Output, "CheckIntegerPredicate", Rule.IntegerPredicate->OperandIndex,
Rule.IntegerPredicate->Predicate);
+ for (const std::string &Predicate : Rule.TargetPredicates)
+ emitInstruction(Output, "CheckTargetPredicate", 0, 0, "0", 0, Predicate);
for (const NormalizedSelectionOperandTypePredicate &Predicate : Rule.OperandTypes)
emitTypePredicate(Output, Predicate.OperandIndex, Predicate.Type);
for (const NormalizedSelectionOperandBankPredicate &Predicate : Rule.OperandBanks)
emitInstruction(Output, "CheckOperandBank", Predicate.OperandIndex, Predicate.Bank);
for (const NormalizedSelectionOperandClassPredicate &Predicate : Rule.OperandClasses)
emitInstruction(Output, "CheckOperandClass", Predicate.OperandIndex, Predicate.RegClass);
+ for (const NormalizedSelectionOperandImmediatePredicate &Predicate : Rule.OperandImmediates) {
+ emitInstruction(Output, "CheckOperandImmediateRanges", Predicate.OperandIndex,
+ static_cast<std::uint32_t>(FirstConstantRange),
+ std::to_string(Predicate.Ranges.size()));
+ FirstConstantRange += Predicate.Ranges.size();
+ }
for (const NormalizedSelectionOperandDefConstantPredicate &Predicate :
Rule.OperandDefConstants) {
emitInstruction(Output, "CheckOperandDefConstantRanges", Predicate.OperandIndex,