* Added Intel x86-64 encodings for 64bit loads and store instructions
* Using GPR registers instead of ABCD for istore8 with REX prefix
Fixed testing of 64bit intel encoding
* Emit REX and REX-less encodings for optional REX prefix
Value renumbering in binary64.cton
When an instruction doesn't have a valid encoding for the target ISA, it
needs to be legalized. Different legalization strategies can be
expressed as separate XFormGroup objects.
Make the choice of XFormGroup configurable per CPU mode, rather than
depending on a hard-coded default.
Add a CPUMode.legalize_type() method which assigns an XFormGroup to
controlling type variables and lets you set a default.
Add a `legalize` field to Level1Entry so the first-level hash table
lookup gives us the configured default legalization action for the
instruction's controlling type variable.
ARM has all of these as scalar integer instructions. Intel has band_not
in SSE and as a scalar in BMI1.
Add the trivial legalization patterns that use a bnot instruction.
This instruction returns a `b1` value which is represented as the output
of a setCC instruction which is the low 8 bits of a GPR register. Use a
cmp+setCC macro recipe to encode this. That is not ideal, but we can't
represent CPU flags yet.
Change the result type for the bit-counting instructions from a fixed i8
to the iB type variable which is the type of the input. This matches the
convention in WebAssembly, and at least Intel's instructions will set a
full register's worth of count result, even if it is always < 64.
Duplicate the Intel 'ur' encoding recipe into 'umr' and 'urm' variants
corresponding to the RM and MR encoding variants. The difference is
which register is encoded as 'reg' and which is 'r/m' in the ModR/M
byte. A 'mov' register copy uses the MR variant, a unary popcnt uses the
RM variant.
* Reduce code duplication in TypeConstraint subclasses; Add ConstrainWiderOrEqual to ti and to ireduce,{s,u}extend and f{promote,demote}; Fix bug in emitting constraint edges in TypeEnv.dot(); Modify runtime constraint checks to reject match when they encounter overflow
* Rename Constrain types to something shorter; Move lane_bits/lane_counts in subclasses of ValueType; Add wider_or_eq function in rust and python;
* Clarify that extended basic blocks are abbreviated as EBB.
* Fix typo.
* Fix a typo.
* Fix typos.
* Use the same phrase to indicate scalar-only as other places in the doc.
* Mention that `band_imm` and friends are scalar-only.
And mention that they're equivalent to their respective
non-immediate-form counterparts.
* Skeleton simple_gvn pass.
* Basic testing infrastructure for simple-gvn.
* Add can_load and can_store flags to instructions.
* Move the replace_values function into the DataFlowGraph.
* Make InstructionData derive from Hash, PartialEq, and Eq.
* Make EntityList's hash and eq functions panic.
* Change Ieee32 and Ieee64 to store u32 and u64, respectively.
This is off by default, but enabled by the parser when reading a textual
IL file. Test files can still override the default to turn off
verification.
The setting enables IL verifier passes at critical points of the
compilation pipeline.
This instruction behaves like icmp fused with brnz, and it can be used
to represent fused compare+branch instruction on Intel when optimizing
for macro-op fusion.
RISC-V provides compare-and-branch instructions directly, and it is
needed there too.
Compare a scalar integer to an immediate constant. Both Intel and RISC-V
ISAs have this operation.
This requires the addition of a new IntCompareImm instruction format.
The meta language patterns sometimes need to refer to specific values of
enumerated immediate operands. The dot syntax provides a namespaced,
typed way of doing that: icmp(intcc.ult, a, x).
Add an ast.Enumerator class for representing this kind of AST leaf node.
Add value definitions for the intcc and floatcc immediate operand kinds.
These two instructions make sense for vector types by simply performing
the same operation on each lane, like most other vector operations.
Problem found by @angusholder's verifier.
The carry and borrow values are boolean, so we have to convert them to
an integer type with bint(c) before we can add them to the result.
Also tweak the default legalizer action for unsupported types: Only
attempt a narrowing pattern for lane types > 32 bits.
This was found by @angusholder's new type checks in the verifier.
When the legalizer splits a value into halves, it would previously stop
if the value was an EBB argument. With this change, we also split EBB
arguments and iteratively split arguments on branches to the EBB.
The iterative splitting stops when we hit the entry block arguments or
an instruction that isn't one of the concatenation instructions.
The value_list flag can be inferred from the presence of VARIABLE_ARGS
in the operand list.
The boxed_storage flag is obsolete. We don't need boxed storage anywhere
no that we have value lists instead.
Allow some flexibility in the signature matching for instruction
formats. In particular, look for a value list format as a second chance
option.
The Return, ReturnReg, and TernaryOverflow formats all fit the single
MultiAry catch-all format for instructions without immediate operands.
No instruction sets actually have single instructions for materializing
vector constants. You always need to use a constant pool.
Cretonne doesn't have constant pools yet, but it will in the future, and
that is how vector constants should be represented.
Instruction formats are now identified by a signature that doesn't
include the ordering of value operands relative to immediate operands.
This means that the BinaryRev instruction format becomes redundant, so
delete it. The isub_imm instruction was the only one using that format.
Rename it to irsub_imm to make it clear what it does now that it is
printed as 'irsub_imm v2, 45'.
With the Return and ReturnReg formats converted to using value lists for
storing their arguments, thee are no remaining instruction formats with
variable argument lists in boxed storage.
The Return and ReturnReg formats are also going to be merged since
they are identical now.
The Branch format also stores its fixed argument in the value list. This
requires the value pool to be passed to a few more functions.
Note that this actually makes the Branch and Jump variants of
InstructionData identical. The instruction format hashing does not yet
understand that all value operands are stored in the value list. We'll
fix that in a later patch.
Also convert IndirectCall, noting that Call and IndirectCall remain
separate instruction formats because they have different immediate
fields.
Add a new kind of instruction format that keeps all of its value
arguments in a value list. These value lists are all allocated out of
the dfg.value_lists memory pool.
Instruction formats with the value_list property set store *all* of
their value arguments in a single value list. There is no distinction
between fixed arguments and variable arguments.
Change the Call instruction format to use the value list representation
for its arguments.
This change is only the beginning. The intent is to eliminate the
boxed_storage instruction formats completely. Value lists use less
memory, and when the transition is complete, InstructionData will have a
trivial Drop implementation.
Add support for two new type variable functions: half_vector() and
double_vector().
Use these two instructions to break down unsupported SIMD types and
build them up again.