[codegen] legalize icmp for 64 and 128 bit operands
Add legalizations for icmp and icmp_imm for i64 and i128 operands for the narrow legalization set, allowing 32-bit ISAs (like x86-32) to compare 64-bit integers and all ISAs to compare 128-bit integers. Fixes: https://github.com/bnjbvr/cranelift-x86/issues/2
This commit is contained in:
committed by
Benjamin Bouvier
parent
19444649e7
commit
c062f12d7c
@@ -5,6 +5,7 @@ use crate::cdsl::xform::{TransformGroupBuilder, TransformGroups};
|
||||
use crate::shared::immediates::Immediates;
|
||||
use crate::shared::types::Float::{F32, F64};
|
||||
use crate::shared::types::Int::{I128, I16, I32, I64, I8};
|
||||
use cranelift_codegen_shared::condcodes::{CondCode, IntCC};
|
||||
|
||||
pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGroups {
|
||||
let mut narrow = TransformGroupBuilder::new(
|
||||
@@ -272,6 +273,69 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro
|
||||
],
|
||||
);
|
||||
|
||||
// TODO(ryzokuken): benchmark this and decide if branching is a faster
|
||||
// approach than evaluating boolean expressions.
|
||||
|
||||
narrow.custom_legalize(icmp_imm, "narrow_icmp_imm");
|
||||
|
||||
let intcc_eq = Literal::enumerator_for(&imm.intcc, "eq");
|
||||
let intcc_ne = Literal::enumerator_for(&imm.intcc, "ne");
|
||||
for &(int_ty, int_ty_half) in &[(I64, I32), (I128, I64)] {
|
||||
narrow.legalize(
|
||||
def!(b = icmp.int_ty(intcc_eq, x, y)),
|
||||
vec![
|
||||
def!((xl, xh) = isplit(x)),
|
||||
def!((yl, yh) = isplit(y)),
|
||||
def!(b1 = icmp.int_ty_half(intcc_eq, xl, yl)),
|
||||
def!(b2 = icmp.int_ty_half(intcc_eq, xh, yh)),
|
||||
def!(b = band(b1, b2)),
|
||||
],
|
||||
);
|
||||
|
||||
narrow.legalize(
|
||||
def!(b = icmp.int_ty(intcc_ne, x, y)),
|
||||
vec![
|
||||
def!((xl, xh) = isplit(x)),
|
||||
def!((yl, yh) = isplit(y)),
|
||||
def!(b1 = icmp.int_ty_half(intcc_ne, xl, yl)),
|
||||
def!(b2 = icmp.int_ty_half(intcc_ne, xh, yh)),
|
||||
def!(b = bor(b1, b2)),
|
||||
],
|
||||
);
|
||||
|
||||
use IntCC::*;
|
||||
for cc in &[
|
||||
SignedGreaterThan,
|
||||
SignedGreaterThanOrEqual,
|
||||
SignedLessThan,
|
||||
SignedLessThanOrEqual,
|
||||
UnsignedGreaterThan,
|
||||
UnsignedGreaterThanOrEqual,
|
||||
UnsignedLessThan,
|
||||
UnsignedLessThanOrEqual,
|
||||
] {
|
||||
let intcc_cc = Literal::enumerator_for(&imm.intcc, cc.to_static_str());
|
||||
let cc1 = Literal::enumerator_for(&imm.intcc, cc.without_equal().to_static_str());
|
||||
let cc2 =
|
||||
Literal::enumerator_for(&imm.intcc, cc.inverse().without_equal().to_static_str());
|
||||
let cc3 = Literal::enumerator_for(&imm.intcc, cc.unsigned().to_static_str());
|
||||
narrow.legalize(
|
||||
def!(b = icmp.int_ty(intcc_cc, x, y)),
|
||||
vec![
|
||||
def!((xl, xh) = isplit(x)),
|
||||
def!((yl, yh) = isplit(y)),
|
||||
// X = cc1 || (!cc2 && cc3)
|
||||
def!(b1 = icmp.int_ty_half(cc1, xh, yh)),
|
||||
def!(b2 = icmp.int_ty_half(cc2, xh, yh)),
|
||||
def!(b3 = icmp.int_ty_half(cc3, xl, yl)),
|
||||
def!(c1 = bnot(b2)),
|
||||
def!(c2 = band(c1, b3)),
|
||||
def!(b = bor(b1, c2)),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Widen instructions with one input operand.
|
||||
for &op in &[bnot, popcnt] {
|
||||
for &int_ty in &[I8, I16] {
|
||||
|
||||
@@ -96,6 +96,32 @@ impl CondCode for IntCC {
|
||||
}
|
||||
|
||||
impl IntCC {
|
||||
/// Get the corresponding IntCC with the equal component removed.
|
||||
/// For conditions without a zero component, this is a no-op.
|
||||
pub fn without_equal(self) -> Self {
|
||||
use self::IntCC::*;
|
||||
match self {
|
||||
SignedGreaterThan | SignedGreaterThanOrEqual => SignedGreaterThan,
|
||||
SignedLessThan | SignedLessThanOrEqual => SignedLessThan,
|
||||
UnsignedGreaterThan | UnsignedGreaterThanOrEqual => UnsignedGreaterThan,
|
||||
UnsignedLessThan | UnsignedLessThanOrEqual => UnsignedLessThan,
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the corresponding IntCC with the signed component removed.
|
||||
/// For conditions without a signed component, this is a no-op.
|
||||
pub fn unsigned(self) -> Self {
|
||||
use self::IntCC::*;
|
||||
match self {
|
||||
SignedGreaterThan | UnsignedGreaterThan => UnsignedGreaterThan,
|
||||
SignedGreaterThanOrEqual | UnsignedGreaterThanOrEqual => UnsignedGreaterThanOrEqual,
|
||||
SignedLessThan | UnsignedLessThan => UnsignedLessThan,
|
||||
SignedLessThanOrEqual | UnsignedLessThanOrEqual => UnsignedLessThanOrEqual,
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the corresponding string condition code for the IntCC object.
|
||||
pub fn to_static_str(self) -> &'static str {
|
||||
use self::IntCC::*;
|
||||
|
||||
@@ -672,3 +672,67 @@ fn narrow_iconst(
|
||||
|
||||
unimplemented!("missing encoding or legalization for iconst.{:?}", ty);
|
||||
}
|
||||
|
||||
fn narrow_icmp_imm(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
_cfg: &mut ControlFlowGraph,
|
||||
_isa: &dyn TargetIsa,
|
||||
) {
|
||||
use crate::ir::condcodes::{CondCode, IntCC};
|
||||
|
||||
let (arg, cond, imm): (ir::Value, IntCC, i64) = match func.dfg[inst] {
|
||||
ir::InstructionData::IntCompareImm {
|
||||
opcode: ir::Opcode::IcmpImm,
|
||||
arg,
|
||||
cond,
|
||||
imm,
|
||||
} => (arg, cond, imm.into()),
|
||||
_ => panic!("unexpected instruction in narrow_icmp_imm"),
|
||||
};
|
||||
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
let ty = pos.func.dfg.ctrl_typevar(inst);
|
||||
let ty_half = ty.half_width().unwrap();
|
||||
|
||||
let imm_low = pos
|
||||
.ins()
|
||||
.iconst(ty_half, imm & (1u128 << ty_half.bits() - 1) as i64);
|
||||
let imm_high = pos
|
||||
.ins()
|
||||
.iconst(ty_half, imm.wrapping_shr(ty_half.bits().into()));
|
||||
let (arg_low, arg_high) = pos.ins().isplit(arg);
|
||||
|
||||
match cond {
|
||||
IntCC::Equal => {
|
||||
let res_low = pos.ins().icmp(cond, arg_low, imm_low);
|
||||
let res_high = pos.ins().icmp(cond, arg_high, imm_high);
|
||||
pos.func.dfg.replace(inst).band(res_low, res_high);
|
||||
}
|
||||
IntCC::NotEqual => {
|
||||
let res_low = pos.ins().icmp(cond, arg_low, imm_low);
|
||||
let res_high = pos.ins().icmp(cond, arg_high, imm_high);
|
||||
pos.func.dfg.replace(inst).bor(res_low, res_high);
|
||||
}
|
||||
IntCC::SignedGreaterThan
|
||||
| IntCC::SignedGreaterThanOrEqual
|
||||
| IntCC::SignedLessThan
|
||||
| IntCC::SignedLessThanOrEqual
|
||||
| IntCC::UnsignedGreaterThan
|
||||
| IntCC::UnsignedGreaterThanOrEqual
|
||||
| IntCC::UnsignedLessThan
|
||||
| IntCC::UnsignedLessThanOrEqual => {
|
||||
let b1 = pos.ins().icmp(cond.without_equal(), arg_high, imm_high);
|
||||
let b2 = pos
|
||||
.ins()
|
||||
.icmp(cond.inverse().without_equal(), arg_high, imm_high);
|
||||
let b3 = pos.ins().icmp(cond.unsigned(), arg_low, imm_low);
|
||||
let c1 = pos.ins().bnot(b2);
|
||||
let c2 = pos.ins().band(c1, b3);
|
||||
pos.func.dfg.replace(inst).bor(b1, c2);
|
||||
}
|
||||
_ => unimplemented!("missing legalization for condition {:?}", cond),
|
||||
}
|
||||
}
|
||||
|
||||
52
cranelift/filetests/filetests/isa/x86/icmp-i128.clif
Normal file
52
cranelift/filetests/filetests/isa/x86/icmp-i128.clif
Normal file
@@ -0,0 +1,52 @@
|
||||
test run
|
||||
target x86_64 haswell
|
||||
|
||||
function %test_icmp_eq_i128() -> b1 {
|
||||
ebb0:
|
||||
v11 = iconst.i64 0x0
|
||||
v12 = iconst.i64 0x0
|
||||
v1 = iconcat v11, v12
|
||||
v21 = iconst.i64 0x0
|
||||
v22 = iconst.i64 0x0
|
||||
v2 = iconcat v21, v22
|
||||
v10 = icmp.i128 eq v1, v2
|
||||
return v10
|
||||
}
|
||||
|
||||
; run
|
||||
|
||||
function %test_icmp_imm_eq_i128() -> b1 {
|
||||
ebb0:
|
||||
v11 = iconst.i64 0x0
|
||||
v12 = iconst.i64 0x0
|
||||
v1 = iconcat v11, v12
|
||||
v10 = icmp_imm.i128 eq v1, 0x0
|
||||
return v10
|
||||
}
|
||||
|
||||
; run
|
||||
|
||||
function %test_icmp_ne_i128() -> b1 {
|
||||
ebb0:
|
||||
v11 = iconst.i64 0x0
|
||||
v12 = iconst.i64 0x0
|
||||
v1 = iconcat v11, v12
|
||||
v21 = iconst.i64 0x0
|
||||
v22 = iconst.i64 0x1
|
||||
v2 = iconcat v21, v22
|
||||
v10 = icmp.i128 ne v1, v2
|
||||
return v10
|
||||
}
|
||||
|
||||
; run
|
||||
|
||||
function %test_icmp_imm_ne_i128() -> b1 {
|
||||
ebb0:
|
||||
v11 = iconst.i64 0x0
|
||||
v12 = iconst.i64 0x0
|
||||
v1 = iconcat v11, v12
|
||||
v10 = icmp_imm.i128 ne v1, 0x1
|
||||
return v10
|
||||
}
|
||||
|
||||
; run
|
||||
@@ -25,3 +25,301 @@ ebb0(v1: i64, v2: i64):
|
||||
; nextln: v10 = iconcat $v10_lsb, $v10_msb
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_eq(i64, i64) -> b1 {
|
||||
ebb0(v1: i64, v2: i64):
|
||||
v10 = icmp eq v1, v2
|
||||
; check: v1 = iconcat $(v1_lsb=$V), $(v1_msb=$V)
|
||||
; nextln: v2 = iconcat $(v2_lsb=$V), $(v2_msb=$V)
|
||||
; nextln: $(v10_lsb=$V) = icmp eq $v1_lsb, $v2_lsb
|
||||
; nextln: $(v10_msb=$V) = icmp eq $v1_msb, $v2_msb
|
||||
; nextln: v10 = band $v10_lsb, $v10_msb
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_imm_eq(i64) -> b1 {
|
||||
ebb0(v1: i64):
|
||||
v10 = icmp_imm eq v1, 0
|
||||
; check: $(v1_lsb=$V) -> $(v1_lsb_a=$V)
|
||||
; nextln: $(v1_msb=$V) -> $(v1_msb_a=$V)
|
||||
; nextln: v1 = iconcat $(v1_lsb_a=$V), $(v1_msb_a=$V)
|
||||
; nextln: $(v2_lsb=$V) = iconst.i32 0
|
||||
; nextln: $(v2_msb=$V) = iconst.i32 0
|
||||
; nextln: $(v10_lsb=$V) = icmp eq $v1_lsb, $v2_lsb
|
||||
; nextln: $(v10_msb=$V) = icmp eq $v1_msb, $v2_msb
|
||||
; nextln: v10 = band $v10_lsb, $v10_msb
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_ne(i64, i64) -> b1 {
|
||||
ebb0(v1: i64, v2: i64):
|
||||
v10 = icmp ne v1, v2
|
||||
; check: v1 = iconcat $(v1_lsb=$V), $(v1_msb=$V)
|
||||
; nextln: v2 = iconcat $(v2_lsb=$V), $(v2_msb=$V)
|
||||
; nextln: $(v10_lsb=$V) = icmp ne $v1_lsb, $v2_lsb
|
||||
; nextln: $(v10_msb=$V) = icmp ne $v1_msb, $v2_msb
|
||||
; nextln: v10 = bor $v10_lsb, $v10_msb
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_imm_ne(i64) -> b1 {
|
||||
ebb0(v1: i64):
|
||||
v10 = icmp_imm ne v1, 0
|
||||
; check: $(v1_lsb=$V) -> $(v1_lsb_a=$V)
|
||||
; nextln: $(v1_msb=$V) -> $(v1_msb_a=$V)
|
||||
; nextln: v1 = iconcat $(v1_lsb_a=$V), $(v1_msb_a=$V)
|
||||
; nextln: $(v2_lsb=$V) = iconst.i32 0
|
||||
; nextln: $(v2_msb=$V) = iconst.i32 0
|
||||
; nextln: $(v10_lsb=$V) = icmp ne $v1_lsb, $v2_lsb
|
||||
; nextln: $(v10_msb=$V) = icmp ne $v1_msb, $v2_msb
|
||||
; nextln: v10 = bor $v10_lsb, $v10_msb
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_sgt(i64, i64) -> b1 {
|
||||
ebb0(v1: i64, v2: i64):
|
||||
v10 = icmp sgt v1, v2
|
||||
; check: v1 = iconcat $(v1_lsb=$V), $(v1_msb=$V)
|
||||
; nextln: v2 = iconcat $(v2_lsb=$V), $(v2_msb=$V)
|
||||
; nextln: $(b1=$V) = icmp sgt $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp slt $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp ugt $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_imm_sgt(i64) -> b1 {
|
||||
ebb0(v1: i64):
|
||||
v10 = icmp_imm sgt v1, 0
|
||||
; check: $(v1_lsb=$V) -> $(v1_lsb_a=$V)
|
||||
; nextln: $(v1_msb=$V) -> $(v1_msb_a=$V)
|
||||
; nextln: v1 = iconcat $(v1_lsb_a=$V), $(v1_msb_a=$V)
|
||||
; nextln: $(v2_lsb=$V) = iconst.i32 0
|
||||
; nextln: $(v2_msb=$V) = iconst.i32 0
|
||||
; nextln: $(b1=$V) = icmp sgt $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp slt $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp ugt $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_sge(i64, i64) -> b1 {
|
||||
ebb0(v1: i64, v2: i64):
|
||||
v10 = icmp sge v1, v2
|
||||
; check: v1 = iconcat $(v1_lsb=$V), $(v1_msb=$V)
|
||||
; nextln: v2 = iconcat $(v2_lsb=$V), $(v2_msb=$V)
|
||||
; nextln: $(b1=$V) = icmp sgt $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp slt $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp uge $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_imm_sge(i64) -> b1 {
|
||||
ebb0(v1: i64):
|
||||
v10 = icmp_imm sge v1, 0
|
||||
; check: $(v1_lsb=$V) -> $(v1_lsb_a=$V)
|
||||
; nextln: $(v1_msb=$V) -> $(v1_msb_a=$V)
|
||||
; nextln: v1 = iconcat $(v1_lsb_a=$V), $(v1_msb_a=$V)
|
||||
; nextln: $(v2_lsb=$V) = iconst.i32 0
|
||||
; nextln: $(v2_msb=$V) = iconst.i32 0
|
||||
; nextln: $(b1=$V) = icmp sgt $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp slt $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp uge $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_slt(i64, i64) -> b1 {
|
||||
ebb0(v1: i64, v2: i64):
|
||||
v10 = icmp slt v1, v2
|
||||
; check: v1 = iconcat $(v1_lsb=$V), $(v1_msb=$V)
|
||||
; nextln: v2 = iconcat $(v2_lsb=$V), $(v2_msb=$V)
|
||||
; nextln: $(b1=$V) = icmp slt $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp sgt $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp ult $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_imm_slt(i64) -> b1 {
|
||||
ebb0(v1: i64):
|
||||
v10 = icmp_imm slt v1, 0
|
||||
; check: $(v1_lsb=$V) -> $(v1_lsb_a=$V)
|
||||
; nextln: $(v1_msb=$V) -> $(v1_msb_a=$V)
|
||||
; nextln: v1 = iconcat $(v1_lsb_a=$V), $(v1_msb_a=$V)
|
||||
; nextln: $(v2_lsb=$V) = iconst.i32 0
|
||||
; nextln: $(v2_msb=$V) = iconst.i32 0
|
||||
; nextln: $(b1=$V) = icmp slt $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp sgt $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp ult $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_sle(i64, i64) -> b1 {
|
||||
ebb0(v1: i64, v2: i64):
|
||||
v10 = icmp sle v1, v2
|
||||
; check: v1 = iconcat $(v1_lsb=$V), $(v1_msb=$V)
|
||||
; nextln: v2 = iconcat $(v2_lsb=$V), $(v2_msb=$V)
|
||||
; nextln: $(b1=$V) = icmp slt $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp sgt $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp ule $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_imm_sle(i64) -> b1 {
|
||||
ebb0(v1: i64):
|
||||
v10 = icmp_imm sle v1, 0
|
||||
; check: $(v1_lsb=$V) -> $(v1_lsb_a=$V)
|
||||
; nextln: $(v1_msb=$V) -> $(v1_msb_a=$V)
|
||||
; nextln: v1 = iconcat $(v1_lsb_a=$V), $(v1_msb_a=$V)
|
||||
; nextln: $(v2_lsb=$V) = iconst.i32 0
|
||||
; nextln: $(v2_msb=$V) = iconst.i32 0
|
||||
; nextln: $(b1=$V) = icmp slt $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp sgt $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp ule $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_ugt(i64, i64) -> b1 {
|
||||
ebb0(v1: i64, v2: i64):
|
||||
v10 = icmp ugt v1, v2
|
||||
; check: v1 = iconcat $(v1_lsb=$V), $(v1_msb=$V)
|
||||
; nextln: v2 = iconcat $(v2_lsb=$V), $(v2_msb=$V)
|
||||
; nextln: $(b1=$V) = icmp ugt $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp ult $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp ugt $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_imm_ugt(i64) -> b1 {
|
||||
ebb0(v1: i64):
|
||||
v10 = icmp_imm ugt v1, 0
|
||||
; check: $(v1_lsb=$V) -> $(v1_lsb_a=$V)
|
||||
; nextln: $(v1_msb=$V) -> $(v1_msb_a=$V)
|
||||
; nextln: v1 = iconcat $(v1_lsb_a=$V), $(v1_msb_a=$V)
|
||||
; nextln: $(v2_lsb=$V) = iconst.i32 0
|
||||
; nextln: $(v2_msb=$V) = iconst.i32 0
|
||||
; nextln: $(b1=$V) = icmp ugt $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp ult $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp ugt $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_uge(i64, i64) -> b1 {
|
||||
ebb0(v1: i64, v2: i64):
|
||||
v10 = icmp uge v1, v2
|
||||
; check: v1 = iconcat $(v1_lsb=$V), $(v1_msb=$V)
|
||||
; nextln: v2 = iconcat $(v2_lsb=$V), $(v2_msb=$V)
|
||||
; nextln: $(b1=$V) = icmp ugt $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp ult $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp uge $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_imm_uge(i64) -> b1 {
|
||||
ebb0(v1: i64):
|
||||
v10 = icmp_imm uge v1, 0
|
||||
; check: $(v1_lsb=$V) -> $(v1_lsb_a=$V)
|
||||
; nextln: $(v1_msb=$V) -> $(v1_msb_a=$V)
|
||||
; nextln: v1 = iconcat $(v1_lsb_a=$V), $(v1_msb_a=$V)
|
||||
; nextln: $(v2_lsb=$V) = iconst.i32 0
|
||||
; nextln: $(v2_msb=$V) = iconst.i32 0
|
||||
; nextln: $(b1=$V) = icmp ugt $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp ult $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp uge $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_ult(i64, i64) -> b1 {
|
||||
ebb0(v1: i64, v2: i64):
|
||||
v10 = icmp ult v1, v2
|
||||
; check: v1 = iconcat $(v1_lsb=$V), $(v1_msb=$V)
|
||||
; nextln: v2 = iconcat $(v2_lsb=$V), $(v2_msb=$V)
|
||||
; nextln: $(b1=$V) = icmp ult $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp ugt $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp ult $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_imm_ult(i64) -> b1 {
|
||||
ebb0(v1: i64):
|
||||
v10 = icmp_imm ult v1, 0
|
||||
; check: $(v1_lsb=$V) -> $(v1_lsb_a=$V)
|
||||
; nextln: $(v1_msb=$V) -> $(v1_msb_a=$V)
|
||||
; nextln: v1 = iconcat $(v1_lsb_a=$V), $(v1_msb_a=$V)
|
||||
; nextln: $(v2_lsb=$V) = iconst.i32 0
|
||||
; nextln: $(v2_msb=$V) = iconst.i32 0
|
||||
; nextln: $(b1=$V) = icmp ult $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp ugt $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp ult $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_ule(i64, i64) -> b1 {
|
||||
ebb0(v1: i64, v2: i64):
|
||||
v10 = icmp ule v1, v2
|
||||
; check: v1 = iconcat $(v1_lsb=$V), $(v1_msb=$V)
|
||||
; nextln: v2 = iconcat $(v2_lsb=$V), $(v2_msb=$V)
|
||||
; nextln: $(b1=$V) = icmp ult $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp ugt $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp ule $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
function %icmp_imm_ule(i64) -> b1 {
|
||||
ebb0(v1: i64):
|
||||
v10 = icmp_imm ule v1, 0
|
||||
; check: $(v1_lsb=$V) -> $(v1_lsb_a=$V)
|
||||
; nextln: $(v1_msb=$V) -> $(v1_msb_a=$V)
|
||||
; nextln: v1 = iconcat $(v1_lsb_a=$V), $(v1_msb_a=$V)
|
||||
; nextln: $(v2_lsb=$V) = iconst.i32 0
|
||||
; nextln: $(v2_msb=$V) = iconst.i32 0
|
||||
; nextln: $(b1=$V) = icmp ult $v1_msb, $v2_msb
|
||||
; nextln: $(b2=$V) = icmp ugt $v1_msb, $v2_msb
|
||||
; nextln: $(b3=$V) = icmp ule $v1_lsb, $v2_lsb
|
||||
; nextln: $(c1=$V) = bnot $b2
|
||||
; nextln: $(c2=$V) = band $c1, $b3
|
||||
; nextln: v10 = bor $b1, $c2
|
||||
return v10
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user