Files
wasmtime/cranelift/filetests/filetests/isa/s390x/atomic_cas.clif
Ulrich Weigand 9c5c872b3b s390x: Add support for all remaining atomic operations (#3746)
This adds support for all atomic operations that were unimplemented
so far in the s390x back end:
- atomic_rmw operations xchg, nand, smin, smax, umin, umax
- $I8 and $I16 versions of atomic_rmw and atomic_cas
- little endian versions of atomic_rmw and atomic_cas

All of these have to be implemented by a compare-and-swap loop;
and for the $I8 and $I16 versions the actual atomic instruction
needs to operate on the surrounding aligned 32-bit word.

Since we cannot emit new control flow during ISLE instruction
selection, these compare-and-swap loops are emitted as a single
meta-instruction to be expanded at emit time.

However, since there is a large number of different versions of
the loop required to implement all the above operations, I've
implemented a facility to allow specifying the loop bodies
from within ISLE after all, by creating a vector of MInst
structures that will be emitted as part of the meta-instruction.

There are still restrictions, in particular instructions that
are part of the loop body may not modify any virtual register.
But even so, this approach looks preferable to doing everything
in emit.rs.

A few instructions needed in those compare-and-swap loop bodies
were added as well, in particular the RxSBG family of instructions
as well as the LOAD REVERSED in-register byte-swap instructions.

This patch also adds filetest runtests to verify the semantics
of all operations, in particular the subword and little-endian
variants (those are currently only executed on s390x).
2022-02-08 13:48:44 -08:00

55 lines
1.4 KiB
Plaintext

test compile
target s390x
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ATOMIC_CAS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function %atomic_cas_i64(i64, i64, i64) -> i64 {
block0(v0: i64, v1: i64, v2: i64):
v3 = atomic_cas.i64 v2, v0, v1
return v3
}
; check: csg %r2, %r3, 0(%r4)
; nextln: br %r14
function %atomic_cas_i32(i32, i32, i64) -> i32 {
block0(v0: i32, v1: i32, v2: i64):
v3 = atomic_cas.i32 v2, v0, v1
return v3
}
; check: cs %r2, %r3, 0(%r4)
; nextln: br %r14
function %atomic_cas_i16(i64, i16, i16, i64) -> i16 {
block0(v0: i64, v1: i16, v2: i16, v3: i64):
v4 = atomic_cas.i16 v3, v1, v2
return v4
}
; check: sllk %r2, %r5, 3
; nextln: nill %r5, 65532
; nextln: l %r0, 0(%r5)
; nextln: 0: rll %r1, %r0, 0(%r2) ; rxsbg %r1, %r3, 160, 48, 16 ; jglh 1f ; risbgn %r1, %r4, 32, 48, 16 ; rll %r1, %r1, 0(%r2) ; cs %r0, %r1, 0(%r5) ; jglh 0b ; 1:
; nextln: rll %r2, %r0, 16(%r2)
; nextln: br %r14
function %atomic_cas_i8(i64, i8, i8, i64) -> i8 {
block0(v0: i64, v1: i8, v2: i8, v3: i64):
v4 = atomic_cas.i8 v3, v1, v2
return v4
}
; check: stmg %r14, %r15, 112(%r15)
; nextln: sllk %r2, %r5, 3
; nextln: nill %r5, 65532
; nextln: lcr %r14, %r2
; nextln: l %r0, 0(%r5)
; nextln: 0: rll %r1, %r0, 0(%r2) ; rxsbg %r1, %r3, 160, 40, 24 ; jglh 1f ; risbgn %r1, %r4, 32, 40, 24 ; rll %r1, %r1, 0(%r14) ; cs %r0, %r1, 0(%r5) ; jglh 0b
; nextln: rll %r2, %r0, 8(%r2)
; nextln: lmg %r14, %r15, 112(%r15)
; nextln: br %r14