aarch64: Implement lowering i128 icmp instructions

We have 3 different aproaches depending on the type of comparision requested:
* For eq/ne we compare the high bits and low bits and check
  if they are equal
* For overflow checks, we perform a i128 add and check the
  resulting overflow flag
* For the remaining comparisions (gt/lt/sgt/etc...)
  We compare both the low bits and high bits, and if the high bits are
  equal we return the result of the unsigned comparision on the low bits

As with other i128 ops, we are still missing immlogic support.
This commit is contained in:
Afonso Bordado
2021-06-09 19:29:44 +01:00
parent 4d085d8fbf
commit 2643d2654c
4 changed files with 520 additions and 70 deletions

View File

@@ -1,7 +1,7 @@
//! Lower a single Cranelift instruction into vcode.
use crate::binemit::CodeOffset;
use crate::ir::condcodes::FloatCC;
use crate::ir::condcodes::{FloatCC, IntCC};
use crate::ir::types::*;
use crate::ir::Inst as IRInst;
use crate::ir::{InstructionData, Opcode, TrapCode};
@@ -1673,14 +1673,112 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
(false, true) => NarrowValueMode::SignExtend64,
(false, false) => NarrowValueMode::ZeroExtend64,
};
let rn = put_input_in_reg(ctx, inputs[0], narrow_mode);
if !ty.is_vector() {
if ty == I128 {
let lhs = put_input_in_regs(ctx, inputs[0]);
let rhs = put_input_in_regs(ctx, inputs[1]);
let tmp1 = ctx.alloc_tmp(I64).only_reg().unwrap();
let tmp2 = ctx.alloc_tmp(I64).only_reg().unwrap();
match condcode {
IntCC::Equal | IntCC::NotEqual => {
// eor tmp1, lhs_lo, rhs_lo
// eor tmp2, lhs_hi, rhs_hi
// adds xzr, tmp1, tmp2
// cset dst, {eq, ne}
ctx.emit(Inst::AluRRR {
alu_op: ALUOp::Eor64,
rd: tmp1,
rn: lhs.regs()[0],
rm: rhs.regs()[0],
});
ctx.emit(Inst::AluRRR {
alu_op: ALUOp::Eor64,
rd: tmp2,
rn: lhs.regs()[1],
rm: rhs.regs()[1],
});
ctx.emit(Inst::AluRRR {
alu_op: ALUOp::AddS64,
rd: writable_zero_reg(),
rn: tmp1.to_reg(),
rm: tmp2.to_reg(),
});
materialize_bool_result(ctx, insn, rd, cond);
}
IntCC::Overflow | IntCC::NotOverflow => {
// We can do an 128bit add while throwing away the results
// and check the overflow flags at the end.
//
// adds xzr, lhs_lo, rhs_lo
// adcs xzr, lhs_hi, rhs_hi
// cset dst, {vs, vc}
ctx.emit(Inst::AluRRR {
alu_op: ALUOp::AddS64,
rd: writable_zero_reg(),
rn: lhs.regs()[0],
rm: rhs.regs()[0],
});
ctx.emit(Inst::AluRRR {
alu_op: ALUOp::AdcS64,
rd: writable_zero_reg(),
rn: lhs.regs()[1],
rm: rhs.regs()[1],
});
materialize_bool_result(ctx, insn, rd, cond);
}
_ => {
// cmp lhs_lo, rhs_lo
// cset tmp1, low_cc
// cmp lhs_hi, rhs_hi
// cset tmp2, cond
// csel dst, tmp1, tmp2, eq
let low_cc = match condcode {
IntCC::SignedGreaterThanOrEqual | IntCC::UnsignedGreaterThanOrEqual => {
Cond::Hs
}
IntCC::SignedGreaterThan | IntCC::UnsignedGreaterThan => Cond::Hi,
IntCC::SignedLessThanOrEqual | IntCC::UnsignedLessThanOrEqual => {
Cond::Ls
}
IntCC::SignedLessThan | IntCC::UnsignedLessThan => Cond::Lo,
_ => unreachable!(),
};
ctx.emit(Inst::AluRRR {
alu_op: ALUOp::SubS64,
rd: writable_zero_reg(),
rn: lhs.regs()[0],
rm: rhs.regs()[0],
});
materialize_bool_result(ctx, insn, tmp1, low_cc);
ctx.emit(Inst::AluRRR {
alu_op: ALUOp::SubS64,
rd: writable_zero_reg(),
rn: lhs.regs()[1],
rm: rhs.regs()[1],
});
materialize_bool_result(ctx, insn, tmp2, cond);
ctx.emit(Inst::CSel {
cond: Cond::Eq,
rd,
rn: tmp1.to_reg(),
rm: tmp2.to_reg(),
});
}
}
} else if !ty.is_vector() {
let alu_op = choose_32_64(ty, ALUOp::SubS32, ALUOp::SubS64);
let rn = put_input_in_reg(ctx, inputs[0], narrow_mode);
let rm = put_input_in_rse_imm12(ctx, inputs[1], narrow_mode);
ctx.emit(alu_inst_imm12(alu_op, writable_zero_reg(), rn, rm));
materialize_bool_result(ctx, insn, rd, cond);
} else {
let rn = put_input_in_reg(ctx, inputs[0], narrow_mode);
let rm = put_input_in_reg(ctx, inputs[1], narrow_mode);
lower_vector_compare(ctx, rd, rn, rm, ty, cond)?;
}

View File

@@ -15,6 +15,197 @@ block0(v0: i64, v1: i64):
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %icmp_eq_i128(i128, i128) -> b1 {
block0(v0: i128, v1: i128):
v2 = icmp eq v0, v1
return v2
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: eor x0, x0, x2
; nextln: eor x1, x1, x3
; nextln: adds xzr, x0, x1
; nextln: cset x0, eq
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %icmp_ne_i128(i128, i128) -> b1 {
block0(v0: i128, v1: i128):
v2 = icmp ne v0, v1
return v2
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: eor x0, x0, x2
; nextln: eor x1, x1, x3
; nextln: adds xzr, x0, x1
; nextln: cset x0, ne
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %icmp_slt_i128(i128, i128) -> b1 {
block0(v0: i128, v1: i128):
v2 = icmp slt v0, v1
return v2
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: subs xzr, x0, x2
; nextln: cset x0, lo
; nextln: subs xzr, x1, x3
; nextln: cset x1, lt
; nextln: csel x0, x0, x1, eq
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %icmp_ult_i128(i128, i128) -> b1 {
block0(v0: i128, v1: i128):
v2 = icmp ult v0, v1
return v2
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: subs xzr, x0, x2
; nextln: cset x0, lo
; nextln: subs xzr, x1, x3
; nextln: cset x1, lo
; nextln: csel x0, x0, x1, eq
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %icmp_sle_i128(i128, i128) -> b1 {
block0(v0: i128, v1: i128):
v2 = icmp sle v0, v1
return v2
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: subs xzr, x0, x2
; nextln: cset x0, ls
; nextln: subs xzr, x1, x3
; nextln: cset x1, le
; nextln: csel x0, x0, x1, eq
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %icmp_ule_i128(i128, i128) -> b1 {
block0(v0: i128, v1: i128):
v2 = icmp ule v0, v1
return v2
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: subs xzr, x0, x2
; nextln: cset x0, ls
; nextln: subs xzr, x1, x3
; nextln: cset x1, ls
; nextln: csel x0, x0, x1, eq
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %icmp_sgt_i128(i128, i128) -> b1 {
block0(v0: i128, v1: i128):
v2 = icmp sgt v0, v1
return v2
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: subs xzr, x0, x2
; nextln: cset x0, hi
; nextln: subs xzr, x1, x3
; nextln: cset x1, gt
; nextln: csel x0, x0, x1, eq
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %icmp_ugt_i128(i128, i128) -> b1 {
block0(v0: i128, v1: i128):
v2 = icmp ugt v0, v1
return v2
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: subs xzr, x0, x2
; nextln: cset x0, hi
; nextln: subs xzr, x1, x3
; nextln: cset x1, hi
; nextln: csel x0, x0, x1, eq
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %icmp_sge_i128(i128, i128) -> b1 {
block0(v0: i128, v1: i128):
v2 = icmp sge v0, v1
return v2
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: subs xzr, x0, x2
; nextln: cset x0, hs
; nextln: subs xzr, x1, x3
; nextln: cset x1, ge
; nextln: csel x0, x0, x1, eq
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %icmp_uge_i128(i128, i128) -> b1 {
block0(v0: i128, v1: i128):
v2 = icmp uge v0, v1
return v2
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: subs xzr, x0, x2
; nextln: cset x0, hs
; nextln: subs xzr, x1, x3
; nextln: cset x1, hs
; nextln: csel x0, x0, x1, eq
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %icmp_of_i128(i128, i128) -> b1 {
block0(v0: i128, v1: i128):
v2 = icmp of v0, v1
return v2
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: adds xzr, x0, x2
; nextln: adcs xzr, x1, x3
; nextln: cset x0, vs
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %icmp_nof_i128(i128, i128) -> b1 {
block0(v0: i128, v1: i128):
v2 = icmp nof v0, v1
return v2
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: adds xzr, x0, x2
; nextln: adcs xzr, x1, x3
; nextln: cset x0, vc
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %f(i64, i64) -> i64 {
block0(v0: i64, v1: i64):
v2 = ifcmp v0, v1

View File

@@ -0,0 +1,46 @@
test run
target aarch64
; target x86_64 machinst TODO: X86_64 does not implement i128 icmp overflow
; TODO: Cleanup these tests when we have native support for i128 immediates in CLIF's parser
function %icmp_of_i128(i64, i64, i64, i64) -> b1 {
block0(v0: i64,v1: i64,v2: i64,v3: i64):
v4 = iconcat v0, v1
v5 = iconcat v2, v3
v6 = icmp.i128 of v4, v5
return v6
}
; run: %icmp_of_i128(0, 0, 0, 0) == false
; run: %icmp_of_i128(0, 0, 1, 0) == false
; run: %icmp_of_i128(0, 0, -1, -1) == false
; run: %icmp_of_i128(-1, -1, -1, -1) == false
; run: %icmp_of_i128(0x00000000_00000000, 0x80000000_00000000, 0, 0) == false
; run: %icmp_of_i128(0xFFFFFFFF_FFFFFFFF, 0x7FFFFFFF_FFFFFFFF, 0, 0) == false
; run: %icmp_of_i128(1, 0, 0xFFFFFFFF_FFFFFFFF, 0x7FFFFFFF_FFFFFFFF) == true
; run: %icmp_of_i128(0xFFFFFFFF_FFFFFFFF, 0x7FFFFFFF_FFFFFFFF, 1, 0) == true
; run: %icmp_of_i128(0xFFFFFFFF_FFFFFFFF, 0x7FFFFFFF_FFFFFFFF, 0x00000000_00000000, 0x80000000_00000000) == false
; run: %icmp_of_i128(0x00000000_00000000, 0x80000000_00000000, 0xFFFFFFFF_FFFFFFFF, 0x7FFFFFFF_FFFFFFFF) == false
; run: %icmp_of_i128(0xFFFFFFFF_FFFFFFFF, 0x4FFFFFFF_FFFFFFFF, 0x00000000_00000000, 0x30000000_00000000) == false
; run: %icmp_of_i128(0xFFFFFFFF_FFFFFFFF, 0x4FFFFFFF_FFFFFFFF, 0x00000000_00000001, 0x30000000_00000000) == true
function %icmp_nof_i128(i64, i64, i64, i64) -> b1 {
block0(v0: i64,v1: i64,v2: i64,v3: i64):
v4 = iconcat v0, v1
v5 = iconcat v2, v3
v6 = icmp.i128 nof v4, v5
return v6
}
; run: %icmp_nof_i128(0, 0, 0, 0) == true
; run: %icmp_nof_i128(0, 0, 1, 0) == true
; run: %icmp_nof_i128(0, 0, -1, -1) == true
; run: %icmp_nof_i128(-1, -1, -1, -1) == true
; run: %icmp_nof_i128(0x00000000_00000000, 0x80000000_00000000, 0, 0) == true
; run: %icmp_nof_i128(0xFFFFFFFF_FFFFFFFF, 0x7FFFFFFF_FFFFFFFF, 0, 0) == true
; run: %icmp_nof_i128(1, 0, 0xFFFFFFFF_FFFFFFFF, 0x7FFFFFFF_FFFFFFFF) == false
; run: %icmp_nof_i128(0xFFFFFFFF_FFFFFFFF, 0x7FFFFFFF_FFFFFFFF, 1, 0) == false
; run: %icmp_nof_i128(0xFFFFFFFF_FFFFFFFF, 0x7FFFFFFF_FFFFFFFF, 0x00000000_00000000, 0x80000000_00000000) == true
; run: %icmp_nof_i128(0x00000000_00000000, 0x80000000_00000000, 0xFFFFFFFF_FFFFFFFF, 0x7FFFFFFF_FFFFFFFF) == true
; run: %icmp_nof_i128(0xFFFFFFFF_FFFFFFFF, 0x4FFFFFFF_FFFFFFFF, 0x00000000_00000000, 0x30000000_00000000) == true
; run: %icmp_nof_i128(0xFFFFFFFF_FFFFFFFF, 0x4FFFFFFF_FFFFFFFF, 0x00000000_00000001, 0x30000000_00000000) == false

View File

@@ -1,20 +1,191 @@
test run
target aarch64
target x86_64 machinst
function %test_icmp_eq_i128() -> b1 {
block0:
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
; TODO: Cleanup these tests when we have native support for i128 immediates in CLIF's parser
function %icmp_eq_i128(i64, i64, i64, i64) -> b1 {
block0(v0: i64,v1: i64,v2: i64,v3: i64):
v4 = iconcat v0, v1
v5 = iconcat v2, v3
v6 = icmp.i128 eq v4, v5
return v6
}
; run: %icmp_eq_i128(0, 0, 0, 0) == true
; run: %icmp_eq_i128(-1, -1, -1, -1) == true
; run: %icmp_eq_i128(-1, -1, 0, 0) == false
; run: %icmp_eq_i128(-1, -1, 0, -1) == false
; run: %icmp_eq_i128(-1, 0, -1, -1) == false
; run: %icmp_eq_i128(0, -1, -1, -1) == false
; run: %icmp_eq_i128(0xC0FFEEEE_DECAFFFF, 0xDECAFFFF_C0FFEEEE, 0xC0FFEEEE_DECAFFFF, 0xDECAFFFF_C0FFEEEE) == true
; run: %icmp_eq_i128(0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF, 0x00000000_00000001, 0x00000000_00000001) == false
; run: %icmp_eq_i128(0xFFFFFFFF_FFFFFFFF, 0x00000000_00000001, 0x00000000_00000001, 0x00000000_00000001) == false
; run
function %icmp_ne_i128(i64, i64, i64, i64) -> b1 {
block0(v0: i64,v1: i64,v2: i64,v3: i64):
v4 = iconcat v0, v1
v5 = iconcat v2, v3
v6 = icmp.i128 ne v4, v5
return v6
}
; run: %icmp_ne_i128(0, 0, 0, 0) == false
; run: %icmp_ne_i128(-1, -1, -1, -1) == false
; run: %icmp_ne_i128(-1, -1, 0, 0) == true
; run: %icmp_ne_i128(-1, -1, 0, -1) == true
; run: %icmp_ne_i128(-1, 0, -1, -1) == true
; run: %icmp_ne_i128(0, -1, -1, -1) == true
; run: %icmp_ne_i128(0xC0FFEEEE_DECAFFFF, 0xDECAFFFF_C0FFEEEE, 0xC0FFEEEE_DECAFFFF, 0xDECAFFFF_C0FFEEEE) == false
; run: %icmp_ne_i128(0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF, 0x00000000_00000001, 0x00000000_00000001) == true
; run: %icmp_ne_i128(0xFFFFFFFF_FFFFFFFF, 0x00000000_00000001, 0x00000000_00000001, 0x00000000_00000001) == true
function %icmp_slt_i128(i64, i64, i64, i64) -> b1 {
block0(v0: i64,v1: i64,v2: i64,v3: i64):
v4 = iconcat v0, v1
v5 = iconcat v2, v3
v6 = icmp.i128 slt v4, v5
return v6
}
; run: %icmp_slt_i128(0, 0, 0, 0) == false
; run: %icmp_slt_i128(1, 0, 1, 0) == false
; run: %icmp_slt_i128(0, 0, 1, 0) == true
; run: %icmp_slt_i128(-1, -1, 0, 0) == true
; run: %icmp_slt_i128(0, 0, -1, -1) == false
; run: %icmp_slt_i128(-1, -1, -1, -1) == false
; run: %icmp_slt_i128(0xFFFFFFFF_FFFFFFFD, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF) == true
; run: %icmp_slt_i128(0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE, 0x00000000_00000000, 0xDECAFFFF_DECAFFFF) == true
; run: %icmp_slt_i128(0x00000000_00000000, 0xDECAFFFF_DECAFFFF, 0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE) == false
function %icmp_ult_i128(i64, i64, i64, i64) -> b1 {
block0(v0: i64,v1: i64,v2: i64,v3: i64):
v4 = iconcat v0, v1
v5 = iconcat v2, v3
v6 = icmp.i128 ult v4, v5
return v6
}
; run: %icmp_ult_i128(0, 0, 0, 0) == false
; run: %icmp_ult_i128(1, 0, 1, 0) == false
; run: %icmp_ult_i128(0, 0, 1, 0) == true
; run: %icmp_ult_i128(-1, -1, 0, 0) == false
; run: %icmp_ult_i128(0, 0, -1, -1) == true
; run: %icmp_ult_i128(-1, -1, -1, -1) == false
; run: %icmp_ult_i128(0xFFFFFFFF_FFFFFFFD, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF) == true
; run: %icmp_ult_i128(0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE, 0x00000000_00000000, 0xDECAFFFF_DECAFFFF) == true
; run: %icmp_ult_i128(0x00000000_00000000, 0xDECAFFFF_DECAFFFF, 0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE) == false
function %icmp_sle_i128(i64, i64, i64, i64) -> b1 {
block0(v0: i64,v1: i64,v2: i64,v3: i64):
v4 = iconcat v0, v1
v5 = iconcat v2, v3
v6 = icmp.i128 sle v4, v5
return v6
}
; run: %icmp_sle_i128(0, 0, 0, 0) == true
; run: %icmp_sle_i128(1, 0, 1, 0) == true
; run: %icmp_sle_i128(0, 0, 1, 0) == true
; run: %icmp_sle_i128(-1, -1, 0, 0) == true
; run: %icmp_sle_i128(0, 0, -1, -1) == false
; run: %icmp_sle_i128(-1, -1, -1, -1) == true
; run: %icmp_sle_i128(0xFFFFFFFF_FFFFFFFD, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF) == true
; run: %icmp_sle_i128(0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE, 0x00000000_00000000, 0xDECAFFFF_DECAFFFF) == true
; run: %icmp_sle_i128(0x00000000_00000000, 0xDECAFFFF_DECAFFFF, 0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE) == false
function %icmp_ule_i128(i64, i64, i64, i64) -> b1 {
block0(v0: i64,v1: i64,v2: i64,v3: i64):
v4 = iconcat v0, v1
v5 = iconcat v2, v3
v6 = icmp.i128 ule v4, v5
return v6
}
; run: %icmp_ule_i128(0, 0, 0, 0) == true
; run: %icmp_ule_i128(1, 0, 1, 0) == true
; run: %icmp_ule_i128(0, 0, 1, 0) == true
; run: %icmp_ule_i128(-1, -1, 0, 0) == false
; run: %icmp_ule_i128(0, 0, -1, -1) == true
; run: %icmp_ule_i128(-1, -1, -1, -1) == true
; run: %icmp_ule_i128(0xFFFFFFFF_FFFFFFFD, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF) == true
; run: %icmp_ule_i128(0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE, 0x00000000_00000000, 0xDECAFFFF_DECAFFFF) == true
; run: %icmp_ule_i128(0x00000000_00000000, 0xDECAFFFF_DECAFFFF, 0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE) == false
function %icmp_sgt_i128(i64, i64, i64, i64) -> b1 {
block0(v0: i64,v1: i64,v2: i64,v3: i64):
v4 = iconcat v0, v1
v5 = iconcat v2, v3
v6 = icmp.i128 sgt v4, v5
return v6
}
; run: %icmp_sgt_i128(0, 0, 0, 0) == false
; run: %icmp_sgt_i128(1, 0, 1, 0) == false
; run: %icmp_sgt_i128(0, 0, 1, 0) == false
; run: %icmp_sgt_i128(-1, -1, 0, 0) == false
; run: %icmp_sgt_i128(0, 0, -1, -1) == true
; run: %icmp_sgt_i128(-1, -1, -1, -1) == false
; run: %icmp_sgt_i128(0xFFFFFFFF_FFFFFFFD, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF) == false
; run: %icmp_sgt_i128(0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE, 0x00000000_00000000, 0xDECAFFFF_DECAFFFF) == false
; run: %icmp_sgt_i128(0x00000000_00000000, 0xDECAFFFF_DECAFFFF, 0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE) == true
function %icmp_ugt_i128(i64, i64, i64, i64) -> b1 {
block0(v0: i64,v1: i64,v2: i64,v3: i64):
v4 = iconcat v0, v1
v5 = iconcat v2, v3
v6 = icmp.i128 ugt v4, v5
return v6
}
; run: %icmp_ugt_i128(0, 0, 0, 0) == false
; run: %icmp_ugt_i128(1, 0, 1, 0) == false
; run: %icmp_ugt_i128(0, 0, 1, 0) == false
; run: %icmp_ugt_i128(-1, -1, 0, 0) == true
; run: %icmp_ugt_i128(0, 0, -1, -1) == false
; run: %icmp_ugt_i128(-1, -1, -1, -1) == false
; run: %icmp_ugt_i128(0xFFFFFFFF_FFFFFFFD, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF) == false
; run: %icmp_ugt_i128(0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE, 0x00000000_00000000, 0xDECAFFFF_DECAFFFF) == false
; run: %icmp_ugt_i128(0x00000000_00000000, 0xDECAFFFF_DECAFFFF, 0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE) == true
function %icmp_sge_i128(i64, i64, i64, i64) -> b1 {
block0(v0: i64,v1: i64,v2: i64,v3: i64):
v4 = iconcat v0, v1
v5 = iconcat v2, v3
v6 = icmp.i128 sge v4, v5
return v6
}
; run: %icmp_sge_i128(0, 0, 0, 0) == true
; run: %icmp_sge_i128(1, 0, 1, 0) == true
; run: %icmp_sge_i128(0, 0, 1, 0) == false
; run: %icmp_sge_i128(-1, -1, 0, 0) == false
; run: %icmp_sge_i128(0, 0, -1, -1) == true
; run: %icmp_sge_i128(-1, -1, -1, -1) == true
; run: %icmp_sge_i128(0xFFFFFFFF_FFFFFFFD, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF) == false
; run: %icmp_sge_i128(0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE, 0x00000000_00000000, 0xDECAFFFF_DECAFFFF) == false
; run: %icmp_sge_i128(0x00000000_00000000, 0xDECAFFFF_DECAFFFF, 0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE) == true
function %icmp_uge_i128(i64, i64, i64, i64) -> b1 {
block0(v0: i64,v1: i64,v2: i64,v3: i64):
v4 = iconcat v0, v1
v5 = iconcat v2, v3
v6 = icmp.i128 uge v4, v5
return v6
}
; run: %icmp_uge_i128(0, 0, 0, 0) == true
; run: %icmp_uge_i128(1, 0, 1, 0) == true
; run: %icmp_uge_i128(0, 0, 1, 0) == false
; run: %icmp_uge_i128(-1, -1, 0, 0) == true
; run: %icmp_uge_i128(0, 0, -1, -1) == false
; run: %icmp_uge_i128(-1, -1, -1, -1) == true
; run: %icmp_uge_i128(0xFFFFFFFF_FFFFFFFD, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF) == false
; run: %icmp_uge_i128(0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE, 0x00000000_00000000, 0xDECAFFFF_DECAFFFF) == false
; run: %icmp_uge_i128(0x00000000_00000000, 0xDECAFFFF_DECAFFFF, 0x00000000_00000000, 0xC0FFEEEE_C0FFEEEE) == true
; Icmp Imm Tests
function %test_icmp_imm_eq_i128() -> b1 {
block0:
v11 = iconst.i64 0x0
@@ -26,20 +197,6 @@ block0:
; run
function %test_icmp_ne_i128() -> b1 {
block0:
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 {
block0:
v11 = iconst.i64 0x0
@@ -50,45 +207,3 @@ block0:
}
; run
function %test_icmp_nz_eq_i128() -> b1 {
block0:
v11 = iconst.i64 0x1
v12 = iconst.i64 0x1
v1 = iconcat v11, v12
v21 = iconst.i64 0x1
v22 = iconst.i64 0x1
v2 = iconcat v21, v22
v10 = icmp.i128 eq v1, v2
return v10
}
; run
function %test_icmp_nz_gt_i128() -> b1 {
block0:
v11 = iconst.i64 0x1
v12 = iconst.i64 0x1
v1 = iconcat v11, v12
v21 = iconst.i64 0x1
v22 = iconst.i64 0x2
v2 = iconcat v21, v22
v10 = icmp.i128 ugt v2, v1
return v10
}
; run
function %test_icmp_nz_ge_i128() -> b1 {
block0:
v11 = iconst.i64 0x1
v12 = iconst.i64 0x1
v1 = iconcat v11, v12
v21 = iconst.i64 0x1
v22 = iconst.i64 0x1
v2 = iconcat v21, v22
v10 = icmp.i128 uge v1, v2
return v10
}
; run