Remove incomplete/unmaintained ARM32 backend (for now). (#3799)

In #3721, we have been discussing what to do about the ARM32 backend in
Cranelift. Currently, this backend supports only 32-bit types, which is
insufficient for full Wasm-MVP; it's missing other critical bits, like
floating-point support; and it has only ever been exercised, AFAIK, via
the filetests for the individual CLIF instructions that are implemented.

We were very very thankful for the original contribution of this
backend, even in its partial state, and we had hoped at the time that we
could eventually mature it in-tree until it supported e.g. Wasm and
other use-cases. But that hasn't yet happened -- to the blame of no-one,
to be clear, we just haven't had a contributor with sufficient time.

Unfortunately, the existence of the backend and lack of active
maintainer now potentially pose a bit of a burden as we hope to make
continuing changes to the backend framework. For example, the ISLE
migration, and the use of regalloc2 that it will allow, would need all
of the existing lowering patterns in the hand-written ARM32 backend to
be rewritten as ISLE rules.

Given that we don't currently have the resources to do this, we think
it's probably best if we, sadly, for now remove this partial backend.
This is not in any way a statement of what we might accept in the
future, though. If, in the future, an ARM32 backend updated to our
latest codebase with an active maintainer were to appear, we'd be happy
to merge it (and likewise for any other architecture!). But for now,
this is probably the best path. Thanks again to the original contributor
@jmkrauz and we hope that this work can eventually be brought back and
reused if someone has the time to do so!
This commit is contained in:
Chris Fallin
2022-02-14 15:03:52 -08:00
committed by GitHub
parent dc86e7a6dc
commit ca0e8d0a1d
27 changed files with 6 additions and 7189 deletions

View File

@@ -1,244 +0,0 @@
test compile
target arm
feature "experimental_arm32"
function %iadd(i8, i8) -> i8 {
block0(v0: i8, v1: i8):
v2 = iadd v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: add r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %iadd(i16, i16) -> i16 {
block0(v0: i16, v1: i16):
v2 = iadd v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: add r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %iadd(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = iadd v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: add r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %isub(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = isub v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: sub r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %ineg(i32) -> i32 {
block0(v0: i32):
v1 = ineg v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: rsb r0, r0, #0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %imul(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = imul v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: mul r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %umulhi(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = umulhi v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: umull r1, r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %smulhi(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = smulhi v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: smull r1, r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %udiv(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = udiv v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: udiv r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %sdiv(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = sdiv v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: sdiv r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %iadd_flags(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2, v3 = iadd_ifcout v0, v1
v4, v5 = iadd_ifcarry v1, v2, v3
v6 = iadd_ifcin v1, v4, v5
return v6
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: adds r0, r0, r1
; nextln: adcs r0, r1, r0
; nextln: adc r0, r1, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %isub_flags(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2, v3 = isub_ifbout v0, v1
v4, v5 = isub_ifborrow v1, v2, v3
v6 = isub_ifbin v1, v4, v5
return v6
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: subs r0, r0, r1
; nextln: sbcs r0, r1, r0
; nextln: sbc r0, r1, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %band(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = band v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: and r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %bor(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = bor v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: orr r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %bxor(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = bxor v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: eor r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %bnot(i32) -> i32 {
block0(v0: i32):
v1 = bnot v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: mvn r0, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %band_not(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = band_not v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: bic r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %bor_not(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = bor_not v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: orn r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr

View File

@@ -1,133 +0,0 @@
test compile
target arm
feature "experimental_arm32"
function %bitrev_i8(i8) -> i8 {
block0(v0: i8):
v1 = bitrev v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: mov r0, r0, lsl #24
; nextln: rbit r0, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %bitrev_i16(i16) -> i16 {
block0(v0: i16):
v1 = bitrev v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: mov r0, r0, lsl #16
; nextln: rbit r0, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %bitrev_i32(i32) -> i32 {
block0(v0: i32):
v1 = bitrev v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: rbit r0, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %clz_i8(i8) -> i8 {
block0(v0: i8):
v1 = clz v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: uxtb r0, r0
; nextln: clz r0, r0
; nextln: sub r0, r0, #24
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %clz_i16(i16) -> i16 {
block0(v0: i16):
v1 = clz v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: uxth r0, r0
; nextln: clz r0, r0
; nextln: sub r0, r0, #16
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %clz_i32(i32) -> i32 {
block0(v0: i32):
v1 = clz v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: clz r0, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %ctz_i8(i8) -> i8 {
block0(v0: i8):
v1 = ctz v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: uxtb r0, r0
; nextln: rbit r0, r0
; nextln: clz r0, r0
; nextln: sub r0, r0, #24
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %ctz_i16(i16) -> i16 {
block0(v0: i16):
v1 = ctz v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: uxth r0, r0
; nextln: rbit r0, r0
; nextln: clz r0, r0
; nextln: sub r0, r0, #16
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %ctz_i32(i32) -> i32 {
block0(v0: i32):
v1 = ctz v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: rbit r0, r0
; nextln: clz r0, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr

View File

@@ -1,61 +0,0 @@
test compile
target arm
feature "experimental_arm32"
function %icmp(i32, i32) -> b1 {
block0(v0: i32, v1: i32):
v2 = icmp eq v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: cmp r0, r1
; nextln: ite eq ; mov r0, #1 ; mov r0, #0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %ifcmp_trueif(i32, i32) -> b1 {
block0(v0: i32, v1: i32):
v2 = ifcmp v0, v1
v3 = trueif eq v2
return v3
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: cmp r0, r1
; nextln: ite eq ; mov r0, #1 ; mov r0, #0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %select(i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32):
v3 = select v0, v1, v2
return v3
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: cmp r0, #0
; nextln: ite ne ; mov r0, r1 ; mov r0, r2
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %selectif(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = ifcmp v0, v1
v5 = selectif.i32 eq v4, v2, v3
return v5
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: cmp r0, r1
; nextln: ite eq ; mov r0, r2 ; mov r0, r3
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr

View File

@@ -1,108 +0,0 @@
test compile
target arm
feature "experimental_arm32"
function %b1() -> b1 {
block0:
v0 = bconst.b1 true
return v0
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: mov r0, #1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %b8() -> b8 {
block0:
v0 = bconst.b8 false
return v0
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: mov r0, #0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %b16() -> b16 {
block0:
v0 = bconst.b16 true
return v0
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: mov r0, #1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %b32() -> b32 {
block0:
v0 = bconst.b32 false
return v0
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: mov r0, #0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %i8() -> i8 {
block0:
v0 = iconst.i8 0xff
return v0
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: mov r0, #255
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %i8() -> i16 {
block0:
v0 = iconst.i16 0xffff
return v0
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: mov r0, #65535
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %f() -> i32 {
block0:
v0 = iconst.i32 0xffff
return v0
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: mov r0, #65535
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %f() -> i32 {
block0:
v0 = iconst.i32 0xffffffff
return v0
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: mov r0, #65535
; nextln: movt r0, #65535
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr

View File

@@ -1,132 +0,0 @@
test compile
target arm
feature "experimental_arm32"
function %brnz(b1) -> i32 {
block0(v0: b1):
brnz v0, block1
jump block2
block1:
v1 = iconst.i32 1
return v1
block2:
v2 = iconst.i32 2
return v2
}
; check: Block 0:
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: and r0, r0, #1
; nextln: cmp r0, #0
; nextln: bne label1 ; b label2
; check: Block 1:
; check: mov r0, #1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
; check: Block 2:
; check: mov r0, #2
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %brz(b1) -> i32 {
block0(v0: b1):
brz v0, block1
jump block2
block1:
v1 = iconst.i32 1
return v1
block2:
v2 = iconst.i32 2
return v2
}
; check: Block 0:
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: and r0, r0, #1
; nextln: cmp r0, #0
; nextln: beq label1 ; b label2
; check: Block 1:
; check: mov r0, #1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
; check: Block 2:
; check: mov r0, #2
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %trap() {
block0:
trap user0
}
; check: udf #0
function %trapif(i32, i32) {
block0(v0: i32, v1: i32):
v2 = ifcmp v0, v1
trapif eq v2, user0
return
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: cmp r0, r1
; nextln: bne 2 ; udf #0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %debugtrap() {
block0:
debugtrap
return
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: bkpt #0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %call(i32) -> i32 {
fn0 = %f(i32) -> i32
block0(v0: i32):
v1 = call fn0(v0)
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: ldr r1, [pc, #4] ; b 4 ; data
; nextln: blx r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %call_indirect(i32, i32) -> i32 {
sig0 = (i32) -> i32
block0(v0: i32, v1: i32):
v2 = call_indirect.i32 sig0, v1(v0)
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: blx r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr

View File

@@ -1,81 +0,0 @@
test compile
target arm
feature "experimental_arm32"
function %uextend_i8_i32(i8) -> i32 {
block0(v0: i8):
v1 = uextend.i32 v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: uxtb r0, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %uextend_i8_i16(i8) -> i16 {
block0(v0: i8):
v1 = uextend.i16 v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: uxtb r0, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %uextend_i16_i32(i16) -> i32 {
block0(v0: i16):
v1 = uextend.i32 v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: uxth r0, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %sextend_i8_i32(i8) -> i32 {
block0(v0: i8):
v1 = sextend.i32 v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: sxtb r0, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %sextend_i8_i16(i8) -> i16 {
block0(v0: i8):
v1 = sextend.i16 v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: sxtb r0, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %sextend_i16_i32(i16) -> i32 {
block0(v0: i16):
v1 = sextend.i32 v0
return v1
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: sxth r0, r0
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr

View File

@@ -1,48 +0,0 @@
test compile
target arm
feature "experimental_arm32"
function %args(i32) -> i32 {
sig0 = (i32, i32, i32, i32) -> i32
block0(v0: i32):
v1 = iconst.i32 1
v2 = iconst.i32 2
v3 = iconst.i32 3
v4 = iconst.i32 4
v5 = call_indirect.i32 sig0, v0(v1, v2, v3, v4)
return v5
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: push {r4, ip}
; nextln: virtual_sp_offset_adjust 8
; nextln: mov r4, r0
; nextln: mov r0, #1
; nextln: mov r1, #2
; nextln: mov r2, #3
; nextln: mov r3, #4
; nextln: blx r4
; nextln: pop {r4, ip}
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %multi_return() -> i32, i32, i32, i32 {
block0:
v0 = iconst.i32 1
v1 = iconst.i32 2
v2 = iconst.i32 3
v3 = iconst.i32 4
return v0, v1, v2, v3
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: mov r0, #1
; nextln: mov r1, #2
; nextln: mov r2, #3
; nextln: mov r3, #4
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr

View File

@@ -1,158 +0,0 @@
test compile
target arm
feature "experimental_arm32"
function %ishl_i8(i8, i8) -> i8 {
block0(v0: i8, v1: i8):
v2 = ishl v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: uxtb r1, r1
; nextln: lsl r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %ishl_i16(i16, i16) -> i16 {
block0(v0: i16, v1: i16):
v2 = ishl v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: uxth r1, r1
; nextln: lsl r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %ishl_i32(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = ishl v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: lsl r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %ushr_i8(i8, i8) -> i8 {
block0(v0: i8, v1: i8):
v2 = ushr v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: uxtb r0, r0
; nextln: uxtb r1, r1
; nextln: lsr r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %ushr_i16(i16, i16) -> i16 {
block0(v0: i16, v1: i16):
v2 = ushr v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: uxth r0, r0
; nextln: uxth r1, r1
; nextln: lsr r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %ushr_i32(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = ushr v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: lsr r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %sshr_i8(i8, i8) -> i8 {
block0(v0: i8, v1: i8):
v2 = sshr v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: sxtb r0, r0
; nextln: uxtb r1, r1
; nextln: asr r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %sshr_i16(i16, i16) -> i16 {
block0(v0: i16, v1: i16):
v2 = sshr v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: sxth r0, r0
; nextln: uxth r1, r1
; nextln: asr r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %sshr_i32(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = sshr v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: asr r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %ror_i32(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = rotr v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: ror r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr
function %rotl_i32(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = rotl v0, v1
return v2
}
; check: push {fp, lr}
; nextln: mov fp, sp
; nextln: and r1, r1, #31
; nextln: rsb r1, r1, #32
; nextln: ror r0, r0, r1
; nextln: mov sp, fp
; nextln: pop {fp, lr}
; nextln: bx lr