Constant-fold icmp instructions (#5666)
We found examples of icmp instructions with both operands constant in spidermonkey.wasm.
This commit is contained in:
@@ -134,6 +134,28 @@ macro_rules! isle_common_prelude_methods {
|
|||||||
x & 0xffff_ffff
|
x & 0xffff_ffff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn imm64_icmp(&mut self, ty: Type, cc: &IntCC, x: Imm64, y: Imm64) -> Imm64 {
|
||||||
|
let shift = u32::checked_sub(64, ty.bits()).unwrap_or(0);
|
||||||
|
let mask = u64::MAX >> shift;
|
||||||
|
let x = (x.bits() as u64) & mask;
|
||||||
|
let y = (y.bits() as u64) & mask;
|
||||||
|
let sext = |v| ((v << shift) as i64) >> shift;
|
||||||
|
let result = match cc {
|
||||||
|
IntCC::Equal => x == y,
|
||||||
|
IntCC::NotEqual => x != y,
|
||||||
|
IntCC::UnsignedGreaterThanOrEqual => x >= y,
|
||||||
|
IntCC::UnsignedGreaterThan => x > y,
|
||||||
|
IntCC::UnsignedLessThanOrEqual => x <= y,
|
||||||
|
IntCC::UnsignedLessThan => x < y,
|
||||||
|
IntCC::SignedGreaterThanOrEqual => sext(x) >= sext(y),
|
||||||
|
IntCC::SignedGreaterThan => sext(x) > sext(y),
|
||||||
|
IntCC::SignedLessThanOrEqual => sext(x) <= sext(y),
|
||||||
|
IntCC::SignedLessThan => sext(x) < sext(y),
|
||||||
|
};
|
||||||
|
Imm64::new(result.into())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ty_bits(&mut self, ty: Type) -> u8 {
|
fn ty_bits(&mut self, ty: Type) -> u8 {
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|||||||
@@ -70,6 +70,14 @@
|
|||||||
(iconst ty k2)))
|
(iconst ty k2)))
|
||||||
(subsume (iconst ty (imm64_sshr ty k1 k2))))
|
(subsume (iconst ty (imm64_sshr ty k1 k2))))
|
||||||
|
|
||||||
|
(rule (simplify
|
||||||
|
(icmp result_ty
|
||||||
|
cc
|
||||||
|
(iconst ty k1)
|
||||||
|
(iconst ty k2)))
|
||||||
|
(subsume (iconst result_ty (imm64_icmp ty cc k1 k2))))
|
||||||
|
|
||||||
|
|
||||||
;; Canonicalize via commutativity: push immediates to the right.
|
;; Canonicalize via commutativity: push immediates to the right.
|
||||||
;;
|
;;
|
||||||
;; (op k x) --> (op x k)
|
;; (op k x) --> (op x k)
|
||||||
|
|||||||
@@ -150,6 +150,9 @@
|
|||||||
(decl pure u64_uextend_u32 (u64) u64)
|
(decl pure u64_uextend_u32 (u64) u64)
|
||||||
(extern constructor u64_uextend_u32 u64_uextend_u32)
|
(extern constructor u64_uextend_u32 u64_uextend_u32)
|
||||||
|
|
||||||
|
(decl pure imm64_icmp (Type IntCC Imm64 Imm64) Imm64)
|
||||||
|
(extern constructor imm64_icmp imm64_icmp)
|
||||||
|
|
||||||
(decl u64_is_zero (bool) u64)
|
(decl u64_is_zero (bool) u64)
|
||||||
(extern extractor infallible u64_is_zero u64_is_zero)
|
(extern extractor infallible u64_is_zero u64_is_zero)
|
||||||
|
|
||||||
|
|||||||
@@ -192,3 +192,21 @@ block0(v0: i64):
|
|||||||
return v4
|
return v4
|
||||||
; check: return v4
|
; check: return v4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function %f2(i8) -> i8 {
|
||||||
|
block0(v1: i8):
|
||||||
|
v2 = icmp eq v1, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: v3 = iconst.i8 1
|
||||||
|
; check: return v3
|
||||||
|
|
||||||
|
function %f3(i8) -> i8 {
|
||||||
|
block0(v1: i8):
|
||||||
|
v2 = icmp ne v1, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: v3 = iconst.i8 0
|
||||||
|
; check: return v3
|
||||||
|
|||||||
@@ -23,24 +23,6 @@ block0:
|
|||||||
; check: v3 = iconst.i16 0xfffe
|
; check: v3 = iconst.i16 0xfffe
|
||||||
; nextln: return v3
|
; nextln: return v3
|
||||||
|
|
||||||
function %f2(i8) -> i8 {
|
|
||||||
block0(v1: i8):
|
|
||||||
v2 = icmp eq v1, v1
|
|
||||||
return v2
|
|
||||||
}
|
|
||||||
|
|
||||||
; check: v3 = iconst.i8 1
|
|
||||||
; check: return v3
|
|
||||||
|
|
||||||
function %f3(i8) -> i8 {
|
|
||||||
block0(v1: i8):
|
|
||||||
v2 = icmp ne v1, v1
|
|
||||||
return v2
|
|
||||||
}
|
|
||||||
|
|
||||||
; check: v3 = iconst.i8 0
|
|
||||||
; check: return v3
|
|
||||||
|
|
||||||
function %ishl() -> i8 {
|
function %ishl() -> i8 {
|
||||||
block0:
|
block0:
|
||||||
v0 = iconst.i8 1
|
v0 = iconst.i8 1
|
||||||
@@ -73,3 +55,113 @@ block0:
|
|||||||
|
|
||||||
; check: v3 = iconst.i8 -4
|
; check: v3 = iconst.i8 -4
|
||||||
; check: return v3
|
; check: return v3
|
||||||
|
|
||||||
|
function %icmp_eq_i32() -> i8 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i32 1
|
||||||
|
v1 = iconst.i32 2
|
||||||
|
v2 = icmp eq v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: v3 = iconst.i8 0
|
||||||
|
; nextln: return v3
|
||||||
|
|
||||||
|
function %icmp_ne_i32() -> i8 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i32 1
|
||||||
|
v1 = iconst.i32 2
|
||||||
|
v2 = icmp ne v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: v3 = iconst.i8 1
|
||||||
|
; nextln: return v3
|
||||||
|
|
||||||
|
function %icmp_ult_i32() -> i8 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i32 1
|
||||||
|
v1 = iconst.i32 2
|
||||||
|
v2 = icmp ult v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: v3 = iconst.i8 1
|
||||||
|
; nextln: return v3
|
||||||
|
|
||||||
|
function %icmp_ule_i32() -> i8 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i32 1
|
||||||
|
v1 = iconst.i32 2
|
||||||
|
v2 = icmp ule v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: v3 = iconst.i8 1
|
||||||
|
; nextln: return v3
|
||||||
|
|
||||||
|
function %icmp_uge_i32() -> i8 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i32 1
|
||||||
|
v1 = iconst.i32 2
|
||||||
|
v2 = icmp uge v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: v3 = iconst.i8 0
|
||||||
|
; nextln: return v3
|
||||||
|
|
||||||
|
function %icmp_ugt_i32() -> i8 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i32 1
|
||||||
|
v1 = iconst.i32 2
|
||||||
|
v2 = icmp ugt v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: v3 = iconst.i8 0
|
||||||
|
; nextln: return v3
|
||||||
|
|
||||||
|
function %icmp_slt_i32() -> i8 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i32 -1
|
||||||
|
v1 = iconst.i32 2
|
||||||
|
v2 = icmp slt v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: v3 = iconst.i8 1
|
||||||
|
; nextln: return v3
|
||||||
|
|
||||||
|
function %icmp_sle_i32() -> i8 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i32 -1
|
||||||
|
v1 = iconst.i32 2
|
||||||
|
v2 = icmp sle v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: v3 = iconst.i8 1
|
||||||
|
; nextln: return v3
|
||||||
|
|
||||||
|
function %icmp_sge_i32() -> i8 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i32 -1
|
||||||
|
v1 = iconst.i32 2
|
||||||
|
v2 = icmp sge v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: v3 = iconst.i8 0
|
||||||
|
; nextln: return v3
|
||||||
|
|
||||||
|
function %icmp_sgt_i32() -> i8 {
|
||||||
|
block0:
|
||||||
|
v0 = iconst.i32 -1
|
||||||
|
v1 = iconst.i32 2
|
||||||
|
v2 = icmp sgt v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: v3 = iconst.i8 0
|
||||||
|
; nextln: return v3
|
||||||
|
|||||||
Reference in New Issue
Block a user