Revision 2 not available (showing current revision instead)

proj-plbook-plChTargetLanguagesConcordance2

Continued from Target Languages Concordance part I

Concordance of instructions supported by two platforms

In addition to the above, instructions or intrinsics for each of the following is provided by two platforms in this study:

Arithmetic:

Memory access:

Stack ops:

Atomics and Sync:

Control flow:

Data structures:

Misc:

Arithmetic

Constant loads

LuaJIT?2 and CIL have instructions to load various higher-level data structures such as strings.

JVM and LuaJIT?2 use constant tables/constant pools. (i think that LuaJIT?2's constant load instructions can be used for both immediate constants and constant tables, depending on if their argumens is negative or not). Note: CIL does not have a runtime-accessible constant table; it has a constant table for use at compile-time but "Compilers inspect this information, at compile time, when importing metadata, but the value of the constant itself, if used, becomes embedded into the CIL stream the compiler emits. There are no CIL instructions to access the Constant table at runtime" ([1] section II.22.9, page 216).

JVM provides instructions to push constants of null, or 0,1 sometimes 2, or -1...5, depending on type. CIL provides instructions to load -1..8 to i32 as well as null.

PC-relative instructions

RISC-V has an instruction to load PC-relative constant, and ARM has PC-relative addition.

Andreas Olofsson of Adapteva said on a blog that he is "not convinced that ((AUIPC)) is essential" [2], however a commenter, Chris, from the RISC-V project explained that it was useful [3].

Add, subtract, multiply, divide

LLVM, CIL, ARM have 32-bit signed integer addition and subtraction with overflow. Only LLVM, CIL have multiplication with overflow, as well as unsigned and 64-bit variants of addition, subtraction, multiplication with overflow.

LLVM offers 'constrained' floating point operations, which means that the rounding and exception modes are respected when those instructions are used. RISC-V provides a similar facility through its rounding mode and exception mode special registers; except that RISC-V does not provide a floating-point mod/remainder instruction.

integer addition with overflow (64-bit and unsigned variants):

integer subtraction with overflow (64-bit and unsigned variants):

integer multiplication, lower bits, with overflow:

floating point constrained operations (similar to corresponding RISC-V operations, not shown):

Moves (copies)

None.

Shifts

WASM and ARM provide right rotate.

Rotate right:

Logical

None.

Compares

WASM and LLVM provide inequality (integer and floating point), integer greater-than-or-equal-to, less-than-or-equal-to, floating point greater-than-or-equal-to (they also provide that for integer, but so do other platforms, so those are listed above rather than here).

Note that some other platforms provide these operations, but only as branches rather than vanilla compares.

Integer inequality:

Integer greater-than-or-equal-to, less-than-or-equal-to:

Floating point:

Misc integer arith

CLZ, CTZ, POPCNT are provided by WASM and LLVM (but only as LLVM intrinsics).

LLVM and ARM provide various byteswaps.

byte swap:

Floating-point-specific

WASM and LLVM provide abs(-olute-value), although LLVM abs is an intrinsic.

RISC-V and LLVM provide rounding in the form of conversion operations and rounding modes (LLVM requires the 'constrained' intrinsics to use these). WASM and LLVM provide rounding in the form of ceil, floor, trunc, nearest instructions (but WASM does not provide rounding mode control for other instructions; see [4] and [5]).

RISC-V and LLVM support IEEE exception flags and rounding modes (but LLVM only supports these with 'constrained' intrinsics. Because two platforms support this functionality it is included here, but note that some of the LLVM 'constrained' intrinsics are listed above, in the section 'Add, subtract, multiply, divide'.

Andreas Olofsson of Adapteva noted in a blog post that the Epiphany ISA does not include operations like RISC-V's exception flags, coercion operations, and rounding modes, because they were not needed for Epiphany's use case [6].

RISC-V provides an FCLASS instruction to report the attributes of a floating-point number. Andreas Olofsson of Adapteva said in a blog post that he felt that this instruction was "not essential" [7]. CIL provides ckfinite to check if a floating-point number is finite.

Fused multiply-add is provided by RISC-V and LLVM (but only as an LLVM intrinsic).

pow is provided by LLVM as an intrinsic and by LuaJIT?2.

some notes on the default rounding mode of other platforms: " WebAssembly? uses “non-stop” mode, and floating point exceptions are not otherwise observable. In particular, neither alternate floating point exception handling attributes nor the non-computational operators on status flags are supported. There is no observable difference between quiet and signalling NaN?. However, positive infinity, negative infinity, and NaN? are still always produced as result values to indicate overflow, invalid, and divide-by-zero conditions, as specified by IEEE 754-2008.

WebAssembly? uses the round-to-nearest ties-to-even rounding attribute, except where otherwise specified. Non-default directed rounding attributes are not supported. " -- [8]

" By default, LLVM optimization passes assume that the rounding mode is round-to-nearest and that floating-point exceptions will not be monitored. Constrained FP intrinsics are used to support non-default rounding modes and accurately preserve exception behavior " -- [9]

Fused multiply-add

Signs

absolute value:

Rounding

floor, ceiling, trunc:

nearest int or rounding-mode determined rounding:

FRM (3-bit floating point rounding mode):

Classify

Floating-point exceptions

FFLAGS (5-bit Accrued Exception Flags):

Pow

Misc floating-point

FCSR (32-bit floating point status and control register):

Conversions

LLVM and ARM provide instructions to convert from 8-bit or 16-bit quantities to larger ones.

Integer conversions from 8-bit or 16-bit to larger

sign extend:

zero extend:

Memory access

Loads and stores

Variable loads and stores

WASM and LuaJIT?2 support loads and stores to/from global variables. JVM and CIL provide short instructions to load/store the first 4 variables.

locals:

globals:

Stack ops

JVM, CIL provide dup.

dup:

Atomics and Sync

RISC-V and LLVM provide the AMOs (Atomic Memory Operations): SWAP, ADD, AND, OR, XOR, MIN, MAX, MINU, MAXU.

RISC-V provides load-release/store-conditional. LLVM provides compare-and-swap. These are different operations but in some sense they are similar in that each can be used as a primitive upon which to build synchronization/consensus/atomicity.

C/C++ are not included in this concordance, but it's worth noting that (as of 2019) C/C++ atomics [10] [11] offer the following atomics (this is a rough summary): (compare and) exchange, load, store, test-and-set flag, clear flag, add, sub, or, xor, and, fence.

Non-Cortex ARM instructions are not included in this concordance, but ARMv8.1-A provides the AMOs: SWP, CAS, LDADD, LDCLR, LDEOR, LDSET, LDSMAX, LDSMIN, LDUMAX, LDUMIN ([12] slide 14) (and in [13] there is also talk of MemAtomicOp?_BIC (result = data AND NOT(value)) and MemAtomicOp?_ORR (result = data OR value), so perhaps those were already in there in some other update?).

Note that the intersection of the C/C++ AMOs with ARMv8.1-A AMOs with the set of AMOs provided by RISC-V and LLVM is (if you assume that ARM's BIC corresponds to an AND): swap, add, and, or, xor.

RISC-V Geneology lists only AMOSWAP and AMOADD as appearing "in at least three" of the instruction set architectures under consideration in that paper.

load-release and store-conditional (LR/SC)

Compare-and-swap (CAS)

AMOs

swap:

add:

xor:

and:

or:

min:

unsigned min:

max:

unsigned max:

Control flow

RISC-V and ARM (all of the hardware processor ISAs included in this study) both provide unconditional jump instructions which also place the source address in a 'link register'. In fact, all of RISC-V unconditional jumps do this. JVM used to provide a similar instruction with JSR, but this has been effectively deprecated.

RISC-V and ARM (all of the hardware processor ISAs included in this study) both provide unconditional indirect branch instructions to an arbitrary location in code. The other platforms do provide indirect jumps, but either require an enumerated set of all potential destinations, or provide indirect jumps for higher-level constructs only (such as LuaJIT?2, which provides the CALL instruction to call a function).

Jumps (unconditional branch)

Jump to immediate / direct branch

Jump to register / indirect branch

Jump to register / indirect branch

Conditional branches

ARM and JVM provide <0, >=0.

Note: Instead of many conditional branches, WASM and LLVM instead provide separate comparison ops, and boolean conditional branch (listed above rather than here, because boolean conditional branch is instead grouped with branch-if-not-zero, which is offered by more than two platforms).

unary compare <0:

unary compare >=0:

Conditional non-branches

WASM and LLVM provide SELECT. Note that these are the same two platforms that separate compares and boolean-conditional-branch.

Subroutines

LuaJIT?2 and CIL provides tail calls.

WASM and Lua provide structured control flow loops.

JVM and CIL provide invoke instructions for object-oriented calling.

tailcall:

Loops:

OOP calls:

Allocation

None.

Data Structures

JVM, CIL provide OOP data structures.

LuaJIT?2 and CIL provide strings (but not many operations specifically for them, as far as i can tell; operations not shown).

OOP

creation, memory:

types:

accessors:

Misc

Cycle counters are provided by RISC-V and LLVM (as LLVM intrinsics).

RISC-V and ARM provide Control-and-Status-Registers. Note that these are all of the hardware processor ISAs in our dataset.

Memory operations such as memcpy are provided by LLVM intrinsics and CIL.

cycle counters:

special registers:

memory:


Concordance of instructions supported by only one platform

Unlike the above sections for classes of instructions supported by n platforms, where n>1, here we won't bother to introduce/provide a list at the beginning of the section of the instructions classes in this section.

Arithmetic

Constant loads

RISC-V alone provides LUI and AUIPC.

Andreas Olofsson of Adapteva said on a blog that he is "not convinced that ((AUIPC)) is essential" [14], however a commenter, Chris, from the RISC-V project explained that it was useful [15].

Load upper bits:

Load PC-relative constant:

Add, subtract, multiply, divide

RISC-V alone also provides integer multiplication instructions returning the high-order bits. Andreas Olofsson of Adapteva said on a blog that these operations had a "high expense/benefit ratio" [16].

LLVM intrinsics alone has saturated addition and subtraction (in both signed and unsigned forms); fixed point multiplication (in both signed and unsigned and signed saturated forms).

ARM alone has PC-relative addition.

JVM alone has increment (which operates directly on variables, not on the stack).

Integer addition

Increment:

PC-relative add:

Integer multiplication

Multiply, undefined upon overflow:

Multiply, upper bits:

Shifts

WASM alone provides left rotate.

Rotate left:

Logical

ARM alone also provides and bit-clear (bitwise-AND (x, bitwise-NOT (y)).

Compares

WASM alone provides equals-zero compares.

LLVM alone breaks out each floating point comparison into 'ordered' and 'unordered', which provide two options for what to do with NaNs?.

JVM alone provides trinary comparisons for floats, doubles, and longs.

Equals zero:

Trinary compare:

Floating-point comparisons

Trinary compare:

Other:

Misc integer arith

LLVM alone provides bitreverse, and funnel shifts.

Other bit manipulation:

Floating-point-specific

RISC-V alone provides copy-negated-sign (FSGNJN) and XOR-sign, although these could be thought of as binary generalizations replacements for the unary sign operations negate and abs, which are provided by other systems.

Andreas Olofsson of Adapteva said in a blog post that he felt that RISC-V's floating point sign instructions (FSGNJ, FSGNJN, FSGNJX) were "not essential" [17].

RISC-V alone provides three fused multiply-add variants.

In a blog post, Andreas Olofsson of Adapteva questioned whether the FNMSUB fused multiply-add instruction variant provided by RISC-V is needed [18]