Files
wasmtime/cranelift/filetests/filetests/egraph/shifts.clif
Alex Crichton 7ebff82861 Optimize sign extension via shifts (#6220)
* Optimize sign extension via shifts

This commit adds egraph optimization patterns for left-shifting a value
and then right-shifting it as a form of sign extending its lower bits.
This matches the behavior of the WebAssembly `i32.extend8_s`
instruction, for example. Note that the lowering of that WebAssembly
instruction does not use shifts, but historical versions of LLVM that
didn't support the instruction, or versions with the instruction
disabled, will use shifts instead.

A second rule for reduction-of-extend being the same as the original
value was added to keep an existing shift-related test passing as well.

* Add reference assemblies for new opts
2023-04-17 18:48:08 +00:00

318 lines
6.6 KiB
Plaintext

test optimize
set opt_level=speed
target x86_64
function %unsigned_shift_right_shift_left_i8(i8) -> i8 {
block0(v0: i8):
v1 = iconst.i8 5
v2 = ushr v0, v1
v3 = ishl v2, v1
return v3
; check: v4 = iconst.i8 224
; check: v5 = band v0, v4
; check: return v5
}
function %unsigned_shift_right_shift_left_i32(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 5
v2 = ushr v0, v1
v3 = ishl v2, v1
return v3
; check: v4 = iconst.i32 0xffff_ffe0
; check: v5 = band v0, v4
; check: return v5
}
function %unsigned_shift_right_shift_left_i64(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 5
v2 = ushr v0, v1
v3 = ishl v2, v1
return v3
; check: v4 = iconst.i64 -32
; check: v5 = band v0, v4
; check: return v5
}
function %signed_shift_right_shift_left_i8(i8) -> i8 {
block0(v0: i8):
v1 = iconst.i8 5
v2 = sshr v0, v1
v3 = ishl v2, v1
return v3
; check: v4 = iconst.i8 224
; check: v5 = band v0, v4
; check: return v5
}
function %signed_shift_right_shift_left_i32(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 5
v2 = sshr v0, v1
v3 = ishl v2, v1
return v3
; check: v4 = iconst.i32 0xffff_ffe0
; check: v5 = band v0, v4
; check: return v5
}
function %signed_shift_right_shift_left_i64(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 5
v2 = sshr v0, v1
v3 = ishl v2, v1
return v3
; check: v4 = iconst.i64 -32
; check: v5 = band v0, v4
; check: return v5
}
function %signed_shift_right_shift_left_i8_mask_rhs(i8) -> i8 {
block0(v0: i8):
v1 = iconst.i8 0xf5
v2 = sshr v0, v1
v3 = ishl v2, v1
return v3
; check: v4 = iconst.i8 224
; check: v5 = band v0, v4
; check: return v5
}
function %sextend_shift_32_64_unsigned(i32) -> i64 {
block0(v0: i32):
v1 = iconst.i8 32
v2 = sextend.i64 v0
v3 = ishl v2, v1
v4 = ushr v3, v1
return v4
; check: v7 = uextend.i64 v0
; check: return v7
}
function %sextend_shift_32_64_signed(i32) -> i64 {
block0(v0: i32):
v1 = iconst.i8 32
v2 = sextend.i64 v0
v3 = ishl v2, v1
v4 = sshr v3, v1
return v4
; check: return v2
}
function %sextend_undershift_32_64_unsigned(i32) -> i64 {
block0(v0: i32):
v1 = iconst.i8 31
v2 = sextend.i64 v0
v3 = ishl v2, v1
v4 = ushr v3, v1
return v4
; check: v5 = iconst.i64 0x0001_ffff_ffff
; check: v6 = band v2, v5
; check: return v6
}
function %sextend_undershift_32_64_signed(i32) -> i64 {
block0(v0: i32):
v1 = iconst.i8 31
v2 = sextend.i64 v0
v3 = ishl v2, v1
v4 = sshr v3, v1
return v4
; check: return v2
}
function %sextend_shift_8_64_unsigned(i8) -> i64 {
block0(v0: i8):
v1 = iconst.i8 56
v2 = sextend.i64 v0
v3 = ishl v2, v1
v4 = ushr v3, v1
return v4
; check: v7 = uextend.i64 v0
; check: return v7
}
function %sextend_shift_8_64_signed(i8) -> i64 {
block0(v0: i8):
v1 = iconst.i8 56
v2 = sextend.i64 v0
v3 = ishl v2, v1
v4 = sshr v3, v1
return v4
; check: return v2
}
function %uextend_shift_32_64_unsigned(i32) -> i64 {
block0(v0: i32):
v1 = iconst.i8 32
v2 = uextend.i64 v0
v3 = ishl v2, v1
v4 = ushr v3, v1
return v4
; check: return v2
}
function %uextend_shift_32_64_signed(i32) -> i64 {
block0(v0: i32):
v1 = iconst.i8 32
v2 = uextend.i64 v0
v3 = ishl v2, v1
v4 = sshr v3, v1
return v4
; check: v5 = sextend.i64 v0
; check: return v5
}
function %uextend_undershift_32_64_unsigned(i32) -> i64 {
block0(v0: i32):
v1 = iconst.i8 31
v2 = uextend.i64 v0
v3 = ishl v2, v1
v4 = ushr v3, v1
return v4
; check: return v2
}
function %uextend_undershift_32_64_signed(i32) -> i64 {
block0(v0: i32):
v1 = iconst.i8 31
v2 = uextend.i64 v0
v3 = ishl v2, v1
v4 = sshr v3, v1
return v4
; check: return v2
}
function %uextend_shift_8_64_unsigned(i8) -> i64 {
block0(v0: i8):
v1 = iconst.i8 56
v2 = uextend.i64 v0
v3 = ishl v2, v1
v4 = ushr v3, v1
return v4
; check: return v2
}
function %uextend_shift_8_64_signed(i8) -> i64 {
block0(v0: i8):
v1 = iconst.i8 56
v2 = uextend.i64 v0
v3 = ishl v2, v1
v4 = sshr v3, v1
return v4
; check: v5 = sextend.i64 v0
; check: return v5
}
function %ineg_ushr_to_sshr(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 63
v2 = ushr v0, v1
v3 = ineg v2
return v3
; check: v4 = sshr v0, v1
; check: return v4
}
function %i32_shl_sshr_8_to_ireduce(i32) -> i32 {
block0(v0: i32):
v1 = ishl_imm v0, 24
v2 = sshr_imm v1, 24
return v2
; check: v5 = ireduce.i8 v0
; check: v6 = sextend.i32 v5
; check: return v6
}
function %i32_shl_sshr_16_to_ireduce(i32) -> i32 {
block0(v0: i32):
v1 = ishl_imm v0, 16
v2 = sshr_imm v1, 16
return v2
; check: v5 = ireduce.i16 v0
; check: v6 = sextend.i32 v5
; check: return v6
}
function %i64_shl_sshr_8_to_ireduce(i64) -> i64 {
block0(v0: i64):
v1 = ishl_imm v0, 56
v2 = sshr_imm v1, 56
return v2
; check: v5 = ireduce.i8 v0
; check: v6 = sextend.i64 v5
; check: return v6
}
function %i64_shl_sshr_16_to_ireduce(i64) -> i64 {
block0(v0: i64):
v1 = ishl_imm v0, 48
v2 = sshr_imm v1, 48
return v2
; check: v5 = ireduce.i16 v0
; check: v6 = sextend.i64 v5
; check: return v6
}
function %i64_shl_sshr_32_to_ireduce(i64) -> i64 {
block0(v0: i64):
v1 = ishl_imm v0, 32
v2 = sshr_imm v1, 32
return v2
; check: v5 = ireduce.i32 v0
; check: v6 = sextend.i64 v5
; check: return v6
}
function %i32_shl_ushr_8_to_ireduce(i32) -> i32 {
block0(v0: i32):
v1 = ishl_imm v0, 24
v2 = ushr_imm v1, 24
return v2
; check: v7 = ireduce.i8 v0
; check: v8 = uextend.i32 v7
; check: return v8
}
function %i32_shl_ushr_16_to_ireduce(i32) -> i32 {
block0(v0: i32):
v1 = ishl_imm v0, 16
v2 = ushr_imm v1, 16
return v2
; check: v7 = ireduce.i16 v0
; check: v8 = uextend.i32 v7
; check: return v8
}
function %i64_shl_ushr_8_to_ireduce(i64) -> i64 {
block0(v0: i64):
v1 = ishl_imm v0, 56
v2 = ushr_imm v1, 56
return v2
; check: v7 = ireduce.i8 v0
; check: v8 = uextend.i64 v7
; check: return v8
}
function %i64_shl_ushr_16_to_ireduce(i64) -> i64 {
block0(v0: i64):
v1 = ishl_imm v0, 48
v2 = ushr_imm v1, 48
return v2
; check: v7 = ireduce.i16 v0
; check: v8 = uextend.i64 v7
; check: return v8
}
function %i64_shl_ushr_32_to_ireduce(i64) -> i64 {
block0(v0: i64):
v1 = ishl_imm v0, 32
v2 = ushr_imm v1, 32
return v2
; check: v7 = ireduce.i32 v0
; check: v8 = uextend.i64 v7
; check: return v8
}