Also handle the case when Pat->Child(i) is null in
CodeGenDAGPatterns::FindPatternInputsAndOutputs().
Fixes issue #157619 : TableGen asserts on invalid cast
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.
This should convert the type set for each HwMode to an MVT for that
HwMode. Instead, if a single type existed for the DefaultMode, that was
used for the MVT of every other mode.
This didn't cause an issue because there is only one place this function
is used before HwModes are expanded. That's just verifying that
constants are small enough for the MVT for each mode. So you would need
a large constant and a HwMode with a smaller VT than the default mode.
Previously we would assert when a ValueTypeByHwMode was missing a case
for the current mode, now we report an error instead. Interestingly this
error only ocurrs when the DAG patterns use RegClassByHwMode, but not
normal RegisterClass instances. Found while I added RegClassByHwMode
to RISC-V and was getting an assertion due to `XLenFVT`/`XLenVecI32VT`
not having an entry for the default mode.
Reviewed By: arsenm
Pull Request: https://github.com/llvm/llvm-project/pull/171254
Fix the dependency of `CodeGenDAGPatterns::ParseDefaultOperands()` on
the particular order of SDNode definitions. Implicit usage of the first
definition as a placeholder makes `llvm-tblgen -gen-dag-isel` fail if
that SDNode is not usable as an output pattern operator and an instance
of `OperandWithDefaultOps` is used in a pattern.
Presently, each `OperandWithDefaultOps` record is processed by
constructing an instance of TreePattern from its `DefaultOps` argument
that has the form `(ops ...)`. Even though the result of processing the
root operator of that DAG is not inspected by `ParseDefaultOperands()`
function itself, that operator has to be supported by the underlying
`TreePattern::ParseTreePattern()` function. For that reason, a temporary
DAG is created by replacing the root operator of `DefaultOps` argument
with the first SDNode defined, which is usually `def imm : ...` defined
in `TargetSelectionDAG.td` file.
This results in misleading errors being reported when implementing new
`SDNode` types, if the new definition happens to be added before the
`def imm : ...` line. The error is reported by several test cases
executed by `check-llvm` target, as well as by the regular build, if one
of the enabled targets inherit one of its operand types from
`OperandWithDefaultOps`:
OptionalIntOperand: ../llvm/test/TableGen/DAGDefaultOps.td:28:5: error: In OptionalIntOperand: Cannot use 'unexpected_node' in an output pattern!
def OptionalIntOperand: OperandWithDefaultOps<i32, (ops (i32 0))>;
This commit implements a dedicated constructor of `TreePattern` to be
used if the caller does not care about the particular root operator of
the pattern being processed.
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>
cPTR is a wildcard CHERI capability value type, used analogously to iPTR. This allows TableGen patterns to abstract over CHERI capability widths.
Co-authored-by: Jessica Clarke <jrtc27@jrtc27.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.
`Predicates` and `Features` fields serve the same purpose. They should
be kept in sync, but not all predicates are based on features. This
resulted in introducing dummy features for that only reason.
This patch removes `Features` field and changes TableGen emitters to use
`Predicates` instead.
Historically, predicates were written with the assumption that the
checking code will be used in `SelectionDAGISel` subclasses, meaning
they will have access to the subclass variables, such as `Subtarget`.
There are no such variables in the generated
`GenSubtargetInfo::getHwModeSet()`, so we need to provide them. This can
be achieved by subclassing `HwModePredicateProlog`, see an example in
`Hexagon.td`.
Previously PatLeafs could not be imported, causing the following
warnings to be emitted when running tblgen with
`-warn-on-skipped-patterns:`
```
/work/clean/llvm/lib/Target/AArch64/AArch64InstrInfo.td:2631:1: warning: Skipped pattern: Src pattern child has unsupported predicate
def : Pat<(i64 (mul top32Zero:$Rn, top32Zero:$Rm)),
^
```
These changes allow the patterns to now be imported successfully.
- 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.
Rename `ListInit::getValues()` to `getElements()` to better match with
other `ListInit` members like `getElement`. Keep `getValues()` for
existing downstream code but mark it deprecated.
- Add `DagInit::get` overloads that do not need ValName to be specified.
- Fix some calls to either not create temporary arrays for DAG args or
use the std::pair<> overload.
If the SDNode is used it can pick up the wrong results number, for
example looking at the known bits of the first result where it should be
looking at the second. The SDValue is already present as the
SelectCodeCommon checks move from parent to child, pass the SDValue
through to CheckNodePredicate as Op so that it can use it if necessary.
SDNode *N is still generated, keeping most PatFrags the same.
Fixes#137274
Support isAnyExtLoad() for IsAtomic in GISel.
Modify atomic_load_az* to check for extload or zextload. And rename to
atomic_load_azext*
Add atomic_load_asext* and use in RISC-V. I used "asext" rather than
"as" so it wouldn't be confused with the word "as".
We can use *Set::insert_range to collapse:
for (auto Elem : Range)
Set.insert(E.first);
down to:
Set.insert_range(llvm::make_first_range(Range));
In some cases, we can further fold that into the set declaration.
DenseSet, SmallPtrSet, SmallSet, SetVector, and StringSet recently
gained C++23-style insert_range. This patch replaces:
Dest.insert(Src.begin(), Src.end());
with:
Dest.insert_range(Src);
This patch does not touch custom begin like succ_begin for now.
This patch adds a simplistic backend that gathers all target-specific
SelectionDAG nodes and emits descriptions for most of them.
This includes generating node enumeration, node names, and information
about node "prototype" that can be used to verify that a node is valid.
The patch also extends SDNode by adding target-specific flags, which are
also included in the generated tables.
Part of #119709,
[RFC](https://discourse.llvm.org/t/rfc-tablegen-erating-sdnode-descriptions/83627).
Pull Request: https://github.com/llvm/llvm-project/pull/123002
On loongarch64 with lsx extension, we select `VBITREV_W` for `v4i32 (xor
X, (shl splat(1), Y))`:
8e66303916/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td (L1583-L1584)
And `vsplat_imm_eq_1` is defined as:
8e66303916/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td (L77-L87)
For the `(bitconvert (v4i32 (build_vector)))` case, the pattern is
expected to be:
```
PATTERN: (xor:{ *:[v4i32] } v4i32:{ *:[v4i32] }:$vj, (shl:{ *:[v4i32] } (bitconvert:{ *:[v4i32] } (build_vector:{ *:[v4i32] }))<<P:Predicate_vsplat_imm_eq_1>>, v4i32:{ *:[v4i32] }:$vk))
RESULT: (VBITREV_W:{ *:[v4i32] } v4i32:{ *:[v4i32] }:$vj, v4i32:{ *:[v4i32] }:$vk)
```
However, `simplifyTree` drops the `bitconvert` node and its predicates:
8e66303916/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp (L3036-L3062)
Then llvm will match `vsplat_imm_eq_1` for any v4i32 splats and cause a
miscompilation:
```
PATTERN: (xor:{ *:[v4i32] } v4i32:{ *:[v4i32] }:$vj, (shl:{ *:[v4i32] } (build_vector:{ *:[v4i32] }), v4i32:{ *:[v4i32] }:$vk))
RESULT: (VBITREV_W:{ *:[v4i32] } v4i32:{ *:[v4i32] }:$vj, v4i32:{ *:[v4i32] }:$vk)
```
This patch adds additional checks for predicates associated with the
trivial bitconvert node. Unused patterns in the LoongArch target are
also removed.
Fixes https://github.com/llvm/llvm-project/issues/116008.
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.