Implement ireduce, sextend, and uextend between i8/i16 and i32/i64.

This commit is contained in:
Dan Gohman
2018-03-05 15:13:59 -08:00
parent b1697dd1dc
commit 136d6f5c4b
3 changed files with 191 additions and 1 deletions

View File

@@ -552,3 +552,35 @@ ebb1:
return
}
; Tests for i32/i8 conversion instructions.
function %I32_I8() {
ebb0:
[-,%rcx] v1 = iconst.i32 1
[-,%rcx] v11 = ireduce.i8 v1 ; bin:
; asm: movsbl %cl, %esi
[-,%rsi] v20 = sextend.i32 v11 ; bin: 0f be f1
; asm: movzbl %cl, %esi
[-,%rsi] v30 = uextend.i32 v11 ; bin: 0f b6 f1
trap user0 ; bin: 0f 0b
}
; Tests for i32/i16 conversion instructions.
function %I32_I16() {
ebb0:
[-,%rcx] v1 = iconst.i32 1
[-,%rcx] v11 = ireduce.i16 v1 ; bin:
; asm: movswl %cx, %esi
[-,%rsi] v20 = sextend.i32 v11 ; bin: 0f bf f1
; asm: movzwl %cx, %esi
[-,%rsi] v30 = uextend.i32 v11 ; bin: 0f b7 f1
trap user0 ; bin: 0f 0b
}

View File

@@ -1084,6 +1084,118 @@ ebb2:
jump ebb1 ; bin: eb fd
}
; Tests for i32/i8 conversion instructions.
function %I32_I8() {
ebb0:
[-,%rcx] v1 = iconst.i32 1
[-,%rsi] v2 = iconst.i32 2
[-,%r10] v3 = iconst.i32 3
[-,%rcx] v11 = ireduce.i8 v1 ; bin:
[-,%rsi] v12 = ireduce.i8 v2 ; bin:
[-,%r10] v13 = ireduce.i8 v3 ; bin:
; asm: movsbl %cl, %esi
[-,%rsi] v20 = sextend.i32 v11 ; bin: 0f be f1
; asm: movsbl %sil, %r10d
[-,%r10] v21 = sextend.i32 v12 ; bin: 44 0f be d6
; asm: movsbl %r10b, %ecx
[-,%rcx] v22 = sextend.i32 v13 ; bin: 41 0f be ca
; asm: movzbl %cl, %esi
[-,%rsi] v30 = uextend.i32 v11 ; bin: 0f b6 f1
; asm: movzbl %sil, %r10d
[-,%r10] v31 = uextend.i32 v12 ; bin: 44 0f b6 d6
; asm: movzbl %r10b, %ecx
[-,%rcx] v32 = uextend.i32 v13 ; bin: 41 0f b6 ca
trap user0 ; bin: 0f 0b
}
; Tests for i32/i16 conversion instructions.
function %I32_I16() {
ebb0:
[-,%rcx] v1 = iconst.i32 1
[-,%rsi] v2 = iconst.i32 2
[-,%r10] v3 = iconst.i32 3
[-,%rcx] v11 = ireduce.i16 v1 ; bin:
[-,%rsi] v12 = ireduce.i16 v2 ; bin:
[-,%r10] v13 = ireduce.i16 v3 ; bin:
; asm: movswl %cx, %esi
[-,%rsi] v20 = sextend.i32 v11 ; bin: 0f bf f1
; asm: movswl %si, %r10d
[-,%r10] v21 = sextend.i32 v12 ; bin: 44 0f bf d6
; asm: movswl %r10w, %ecx
[-,%rcx] v22 = sextend.i32 v13 ; bin: 41 0f bf ca
; asm: movzwl %cx, %esi
[-,%rsi] v30 = uextend.i32 v11 ; bin: 0f b7 f1
; asm: movzwl %si, %r10d
[-,%r10] v31 = uextend.i32 v12 ; bin: 44 0f b7 d6
; asm: movzwl %r10w, %ecx
[-,%rcx] v32 = uextend.i32 v13 ; bin: 41 0f b7 ca
trap user0 ; bin: 0f 0b
}
; Tests for i64/i8 conversion instructions.
function %I64_I8() {
ebb0:
[-,%rcx] v1 = iconst.i64 1
[-,%rsi] v2 = iconst.i64 2
[-,%r10] v3 = iconst.i64 3
[-,%rcx] v11 = ireduce.i8 v1 ; bin:
[-,%rsi] v12 = ireduce.i8 v2 ; bin:
[-,%r10] v13 = ireduce.i8 v3 ; bin:
; asm: movsbq %cl, %rsi
[-,%rsi] v20 = sextend.i64 v11 ; bin: 48 0f be f1
; asm: movsbq %sil, %r10
[-,%r10] v21 = sextend.i64 v12 ; bin: 4c 0f be d6
; asm: movsbq %r10b, %rcx
[-,%rcx] v22 = sextend.i64 v13 ; bin: 49 0f be ca
; asm: movzbl %cl, %esi
[-,%rsi] v30 = uextend.i64 v11 ; bin: 0f b6 f1
; asm: movzbl %sil, %r10d
[-,%r10] v31 = uextend.i64 v12 ; bin: 44 0f b6 d6
; asm: movzbl %r10b, %ecx
[-,%rcx] v32 = uextend.i64 v13 ; bin: 41 0f b6 ca
trap user0 ; bin: 0f 0b
}
; Tests for i64/i16 conversion instructions.
function %I64_I16() {
ebb0:
[-,%rcx] v1 = iconst.i64 1
[-,%rsi] v2 = iconst.i64 2
[-,%r10] v3 = iconst.i64 3
[-,%rcx] v11 = ireduce.i16 v1 ; bin:
[-,%rsi] v12 = ireduce.i16 v2 ; bin:
[-,%r10] v13 = ireduce.i16 v3 ; bin:
; asm: movswq %cx, %rsi
[-,%rsi] v20 = sextend.i64 v11 ; bin: 48 0f bf f1
; asm: movswq %si, %r10
[-,%r10] v21 = sextend.i64 v12 ; bin: 4c 0f bf d6
; asm: movswq %r10w, %rcx
[-,%rcx] v22 = sextend.i64 v13 ; bin: 49 0f bf ca
; asm: movzwl %cx, %esi
[-,%rsi] v30 = uextend.i64 v11 ; bin: 0f b7 f1
; asm: movzwl %si, %r10d
[-,%r10] v31 = uextend.i64 v12 ; bin: 44 0f b7 d6
; asm: movzwl %r10w, %ecx
[-,%rcx] v32 = uextend.i64 v13 ; bin: 41 0f b7 ca
trap user0 ; bin: 0f 0b
}
; Tests for i64/i32 conversion instructions.
function %I64_I32() {
ebb0:

View File

@@ -406,9 +406,55 @@ I64.enc(base.bint.i32.b1, *r.urm_abcd(0x0f, 0xb6))
# Numerical conversions.
# Converting i64 to i32 is a no-op in 64-bit mode.
# Reducing an integer is a no-op.
I32.enc(base.ireduce.i8.i32, r.null, 0)
I32.enc(base.ireduce.i16.i32, r.null, 0)
I64.enc(base.ireduce.i8.i32, r.null, 0)
I64.enc(base.ireduce.i16.i32, r.null, 0)
I64.enc(base.ireduce.i8.i64, r.null, 0)
I64.enc(base.ireduce.i16.i64, r.null, 0)
I64.enc(base.ireduce.i32.i64, r.null, 0)
# TODO: Add encodings for cbw, cwde, cdqe, which are sign-extending
# instructions for %al/%ax/%eax to %ax/%eax/%rax.
# movsbl
I32.enc(base.sextend.i32.i8, *r.urm(0x0f, 0xbe))
I64.enc(base.sextend.i32.i8, *r.urm.rex(0x0f, 0xbe))
I64.enc(base.sextend.i32.i8, *r.urm(0x0f, 0xbe))
# movswl
I32.enc(base.sextend.i32.i16, *r.urm(0x0f, 0xbf))
I64.enc(base.sextend.i32.i16, *r.urm.rex(0x0f, 0xbf))
I64.enc(base.sextend.i32.i16, *r.urm(0x0f, 0xbf))
# movsbq
I64.enc(base.sextend.i64.i8, *r.urm.rex(0x0f, 0xbe, w=1))
# movswq
I64.enc(base.sextend.i64.i16, *r.urm.rex(0x0f, 0xbf, w=1))
# movslq
I64.enc(base.sextend.i64.i32, *r.urm.rex(0x63, w=1))
# movzbl
I32.enc(base.uextend.i32.i8, *r.urm(0x0f, 0xb6))
I64.enc(base.uextend.i32.i8, *r.urm.rex(0x0f, 0xb6))
I64.enc(base.uextend.i32.i8, *r.urm(0x0f, 0xb6))
# movzwl
I32.enc(base.uextend.i32.i16, *r.urm(0x0f, 0xb7))
I64.enc(base.uextend.i32.i16, *r.urm.rex(0x0f, 0xb7))
I64.enc(base.uextend.i32.i16, *r.urm(0x0f, 0xb7))
# movzbq, encoded as movzbl because it's equivalent and shorter
I64.enc(base.uextend.i64.i8, *r.urm.rex(0x0f, 0xb6))
I64.enc(base.uextend.i64.i8, *r.urm(0x0f, 0xb6))
# movzwq, encoded as movzwl because it's equivalent and shorter
I64.enc(base.uextend.i64.i16, *r.urm.rex(0x0f, 0xb7))
I64.enc(base.uextend.i64.i16, *r.urm(0x0f, 0xb7))
# A 32-bit register copy clears the high 32 bits.
I64.enc(base.uextend.i64.i32, *r.umr.rex(0x89))
I64.enc(base.uextend.i64.i32, *r.umr(0x89))