The way HwMode is currently implemented, tablegen duplicates each
pattern that is dependent on hardware mode. The HwMode predicate is
added as a pattern predicate on the duplicated pattern.
RISC-V uses HwMode on the GPR register class which means almost every
isel pattern is affected by HwMode. This results in the isel table
being nearly twice the size it would be if we only had a single GPR
size.
This patch proposes to do the expansion at instruction selection time
instead. To accomplish this new opcodes like OPC_CheckTypeByHwMode
are added to the isel table. The unique combinations of types and HwMode
are converted to an index that is the payload for the new opcodes.
TableGen emits a new virtual function getValueTypeByHwMode that uses
this index and the current HwMode to look up the type.
This reduces the size of the isel table on RISC-V from ~2.38 million
bytes to ~1.38 million bytes.
I did not add an OPC_SwitchTypeByHwMode opcode yet. If the VT requires a
hardware mode, we emit an OPC_Scope+OPC_CheckTypeByHwMode instead. I
expect adding an OPC_SwitchTypeByHwMode could further reduce the table
size. I will investigate this as a follow up.
Many of the matcher classes in tablegen now use ValueTypeByHwMode
insteadof MVT. This may have an impact on the memory usage and runtime of
tablegen. We can mitigate some of this by splitting the matchers into MVT and
ValueTypeByHwMode versions. We can also explore alternate data
structures for ValueTypeByHwMode instead of a std::map. Maybe a sorted vector.
A similar change can be made to GlobalISel as a follow up.
These files contain the implementation of classes used by only the
-gen-dag-isel backend. I don't think they are reusable without
DAGISelMatcherGen.cpp and DAGISelMatcherEmitter.cpp. I don't think
there's anything worth unittesting in just these files either.
Instead emit this as an OPC_EmitInteger, but print the string
when the value is known to be 0..63 (when we don't need a VBR).
Also print the string into a comment when comments are not omitted
so it isn't lost when a VBR is needed.
This reverts commit 3ff2637d867a6cc23ea5d5127b065efb8299d196.
I accidentally merged another PR into this during a rebase. Reverting
to commit it correctly.
Previously, we used a VBR that stored the sign bit in bit 0 followed by
the absolute value in subsequent bits.
This patch changes it to use SLEB128 which discards redundant sign bits,
but keeps the bits in the same positions. This uses the same number of
bytes to encode values so doesn't change the table size.
My goal is to remove OPC_EmitStringInteger as a special opcode type.
Instead, we can print the string directly with OPC_EmitInteger for any
string that has an enum value of 0..63.
This improves type safety and is less verbose. Use SimpleTy only where
an integer is needed like switches or emitting a VBR.
---------
Co-authored-by: Sergei Barannikov <barannikov88@gmail.com>
This is a generalization of the LookupPtrRegClass mechanism.
AMDGPU has several use cases for swapping the register class of
instruction operands based on the subtarget, but none of them
really fit into the box of being pointer-like.
The current system requires manual management of an arbitrary integer
ID. For the AMDGPU use case, this would end up being around 40 new
entries to manage.
This just introduces the base infrastructure. I have ports of all
the target specific usage of PointerLikeRegClass ready.
Outside of CodeGenRegisters itself, we only want to find existing
SubRegIdxs, not create new ones. Change findSubRegIdx to assert and use
it consistently for this purpose.
- Change `Name`, `SubopNames`, `PrinterMethodName`, and
`EncoderMethodNames` to be stored as StringRef.
- Also changed `CheckComplexPatMatcher::Name` to StringRef as a fallout
from the above.
Verified that all the tablegen generated files within LLVM are
unchanged.
Print what result number the Emit* nodes are storing their results in.
This makes it easy to track the inputs of later opcodes that consume
these results.
The node was introduced in 59c39dc1 and was intended to allow writing
patterns like this:
`[(set AL, (mul AL, GR8:$src1)), (implicit EFLAGS)]`
However, it does not introduce new functionality because the same
pattern can be equivalently expressed as:
`[(set AL, EFLAGS, (mul AL, GR8:$src1))]`
The latter form is also more flexible as it allows reordering output
operands.
In most places uses of `implicit` were redundant -- removing them didn't
change anything in the generated DAG tables. The only three cases where
it did have effect are in X86InstrArithmetic.td and X86InstrSystem.td --
those were rewritten to use `set` node.
Removing `implicit` from some patterns made them importable by GISel,
hence the change in a test.
It is almost always simpler to use {} instead of std::nullopt to
initialize an empty ArrayRef. This patch changes all occurrences I could
find in LLVM itself. In future the ArrayRef(std::nullopt_t) constructor
could be deprecated or removed.
The original `CheckValueTypeMatcher` stores StringRef as the member
variable type, however it's more efficient to use use
MVT::SimpleValueType since it prevents string comparison in isEqualImpl,
it also reduce the memory consumption in each object.
Refactor of the llvm-tblgen source into:
- a "Basic" library, which contains the bare minimum utilities to build
`llvm-min-tablegen`
- a "Common" library which contains all of the helpers for TableGen
backends. Such helpers can be shared by more than one backend, and even
unit tested (e.g. CodeExpander is, maybe we can add more over time)
Fixes#80647
Almost all uses of `*TreePatternNode` expect it to be non-null. There
was the occasional check that it wasn't, which I have removed. Making
them references makes it clear that they exist.
This was attempted in 2018 (1b465767d6ca69f4b7201503f5f21e6125fe049a)
for `TreePatternNode::getChild()` but that was reverted.
While working on DAGISelMatcherEmitter I've hit several runtime errors
caused by accessing TreePatternNode::Types out of bounds. These were
difficult to debug because the switch from std::vector to unique_ptr
removes bounds checking.
I don't think the slight reduction in class size is worth the extra
debugging and memory safety problems, so I suggest we revert this.
This reverts commit d34125a1a825208b592cfa8f5fc3566303d691a4.
Differential Revision: https://reviews.llvm.org/D154781
I don't think this code would work correctly if the register class
used used HwModes. Add asserts to make sure it's not used with HwModes.
Also fix a long outdated comment on the function.
These vectors are resized in the constructor and never change size.
We can manually allocate two arrays instead.
This reduces the size of TreePatternNode by removing the
unneeded capacity end pointer fields from the std::vector.
Instead of storing a string containing the instruction name, store a
reference to the instruction. We can use that reference to print the
instruction name when we emit the table.
The only slightly annoying part is that we have to find the
CodeGenInstruction for IMPLICIT_DEF. GlobalISel is doing
a similar thing.
This code was creating 1 entry or 0 entry std::array to pass to
to ArrayRef arguments. ArrayRef has a constructor from a single
object and we can use std::nullopt for an empty ArrayRef.
Since 65b13610a5226b84889b923bae884ba395ad084d, raw_string_ostream has
been unbuffered by default. Based on an audit of llvm/utils/, this
commit removes every call to `raw_string_ostream::flush()` and any call
to `raw_string_ostream::str()` whose result is ignored or that doesn't
help with clarity.
I left behind a few calls to `str()`. In these cases, the underlying
std::string was declared pretty far away and never used again, whereas
stream recently had its last write. The code is easier to read as-is;
the no-op call to `flush()` inside `str()` isn't harmful, and when
https://reviews.llvm.org/D115421 lands it'll be gone anyway.
The TableGen immAllOnesV and immAllZerosV helpers implicitly wrapped the
ISD::isBuildVectorAll(Ones|Zeros) helper functions. This was inhibiting
their use for targets such as RISC-V which use ISD::SPLAT_VECTOR. In
particular, RISC-V had to define its own 'vnot' fragment.
In order to extend the scope of these nodes to include support for
ISD::SPLAT_VECTOR, two new ISD predicate functions have been introduced:
ISD::isConstantSplatVectorAll(Ones|Zeros). These effectively supersede
the older "isBuildVector" predicates, which are now simple wrappers for
the new functions. They pass a defaulted boolean toggle which preserves
the old behaviour. It is hoped that in time all call-sites can be ported
to the "isConstantSplatVector" functions.
While the use of ISD::isBuildVectorAll(Ones|Zeros) has not changed, the
behaviour of the TableGen immAll(Ones|Zeros)V **has**. To test the new
functionality, the custom RISC-V TableGen fragment has been removed and
replaced with the built-in 'vnot'. To test their use as pattern-roots, two
splat patterns have been updated accordingly.
Reviewed By: craig.topper
Differential Revision: https://reviews.llvm.org/D94223