From 61f07d79a7a26948b252c8f08bfa6e2843680ee5 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Tue, 8 Jun 2021 12:42:38 +0100 Subject: [PATCH 1/3] aarch64: Add adcs instruction encodings --- .../codegen/src/isa/aarch64/inst/emit.rs | 2 ++ .../src/isa/aarch64/inst/emit_tests.rs | 20 +++++++++++++++++++ cranelift/codegen/src/isa/aarch64/inst/mod.rs | 5 +++++ 3 files changed, 27 insertions(+) diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs index 60fedcd0d3..ccde5e0385 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -599,6 +599,8 @@ impl MachInstEmit for Inst { ALUOp::Add64 => 0b10001011_000, ALUOp::Adc32 => 0b00011010_000, ALUOp::Adc64 => 0b10011010_000, + ALUOp::AdcS32 => 0b00111010_000, + ALUOp::AdcS64 => 0b10111010_000, ALUOp::Sub32 => 0b01001011_000, ALUOp::Sub64 => 0b11001011_000, ALUOp::Sbc32 => 0b01011010_000, diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs index 530269b201..f6735397d1 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs @@ -70,6 +70,26 @@ fn test_aarch64_binemit() { "A400069A", "adc x4, x5, x6", )); + insns.push(( + Inst::AluRRR { + alu_op: ALUOp::AdcS32, + rd: writable_xreg(1), + rn: xreg(2), + rm: xreg(3), + }, + "4100033A", + "adcs w1, w2, w3", + )); + insns.push(( + Inst::AluRRR { + alu_op: ALUOp::AdcS64, + rd: writable_xreg(4), + rn: xreg(5), + rm: xreg(6), + }, + "A40006BA", + "adcs x4, x5, x6", + )); insns.push(( Inst::AluRRR { alu_op: ALUOp::Sub32, diff --git a/cranelift/codegen/src/isa/aarch64/inst/mod.rs b/cranelift/codegen/src/isa/aarch64/inst/mod.rs index ecdf43c6ff..1b6534de31 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/mod.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/mod.rs @@ -87,6 +87,9 @@ pub enum ALUOp { /// Add with carry Adc32, Adc64, + /// Add with carry, settings flags + AdcS32, + AdcS64, /// Subtract with carry Sbc32, Sbc64, @@ -3212,6 +3215,8 @@ impl Inst { ALUOp::Lsl64 => ("lsl", OperandSize::Size64), ALUOp::Adc32 => ("adc", OperandSize::Size32), ALUOp::Adc64 => ("adc", OperandSize::Size64), + ALUOp::AdcS32 => ("adcs", OperandSize::Size32), + ALUOp::AdcS64 => ("adcs", OperandSize::Size64), ALUOp::Sbc32 => ("sbc", OperandSize::Size32), ALUOp::Sbc64 => ("sbc", OperandSize::Size64), } From 4d085d8fbfbc8af835ba14d0569001811db25bc7 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Wed, 9 Jun 2021 09:15:15 +0100 Subject: [PATCH 2/3] aarch64: Add sbcs instruction encodings --- .../codegen/src/isa/aarch64/inst/emit.rs | 2 ++ .../src/isa/aarch64/inst/emit_tests.rs | 20 +++++++++++++++++++ cranelift/codegen/src/isa/aarch64/inst/mod.rs | 5 +++++ 3 files changed, 27 insertions(+) diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs index ccde5e0385..157ea6ebee 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -605,6 +605,8 @@ impl MachInstEmit for Inst { ALUOp::Sub64 => 0b11001011_000, ALUOp::Sbc32 => 0b01011010_000, ALUOp::Sbc64 => 0b11011010_000, + ALUOp::SbcS32 => 0b01111010_000, + ALUOp::SbcS64 => 0b11111010_000, ALUOp::Orr32 => 0b00101010_000, ALUOp::Orr64 => 0b10101010_000, ALUOp::And32 => 0b00001010_000, diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs index f6735397d1..f48a689e13 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs @@ -130,6 +130,26 @@ fn test_aarch64_binemit() { "A40006DA", "sbc x4, x5, x6", )); + insns.push(( + Inst::AluRRR { + alu_op: ALUOp::SbcS32, + rd: writable_xreg(1), + rn: xreg(2), + rm: xreg(3), + }, + "4100037A", + "sbcs w1, w2, w3", + )); + insns.push(( + Inst::AluRRR { + alu_op: ALUOp::SbcS64, + rd: writable_xreg(4), + rn: xreg(5), + rm: xreg(6), + }, + "A40006FA", + "sbcs x4, x5, x6", + )); insns.push(( Inst::AluRRR { diff --git a/cranelift/codegen/src/isa/aarch64/inst/mod.rs b/cranelift/codegen/src/isa/aarch64/inst/mod.rs index 1b6534de31..854e0b603c 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/mod.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/mod.rs @@ -93,6 +93,9 @@ pub enum ALUOp { /// Subtract with carry Sbc32, Sbc64, + /// Subtract with carry, settings flags + SbcS32, + SbcS64, } /// An ALU operation with three arguments. @@ -3219,6 +3222,8 @@ impl Inst { ALUOp::AdcS64 => ("adcs", OperandSize::Size64), ALUOp::Sbc32 => ("sbc", OperandSize::Size32), ALUOp::Sbc64 => ("sbc", OperandSize::Size64), + ALUOp::SbcS32 => ("sbcs", OperandSize::Size32), + ALUOp::SbcS64 => ("sbcs", OperandSize::Size64), } } From 2643d2654cfcfa12305d777ec325b548132d25e2 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Wed, 9 Jun 2021 19:29:44 +0100 Subject: [PATCH 3/3] 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. --- .../codegen/src/isa/aarch64/lower_inst.rs | 104 +++++++- .../filetests/isa/aarch64/condbr.clif | 191 ++++++++++++++ .../runtests/i128-icmp-overflow.clif | 46 ++++ .../filetests/runtests/i128-icmp.clif | 249 +++++++++++++----- 4 files changed, 520 insertions(+), 70 deletions(-) create mode 100644 cranelift/filetests/filetests/runtests/i128-icmp-overflow.clif diff --git a/cranelift/codegen/src/isa/aarch64/lower_inst.rs b/cranelift/codegen/src/isa/aarch64/lower_inst.rs index c4384fa83a..4fdb6942b6 100644 --- a/cranelift/codegen/src/isa/aarch64/lower_inst.rs +++ b/cranelift/codegen/src/isa/aarch64/lower_inst.rs @@ -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>( (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)?; } diff --git a/cranelift/filetests/filetests/isa/aarch64/condbr.clif b/cranelift/filetests/filetests/isa/aarch64/condbr.clif index 9ab5cfb2df..bfa4d04f77 100644 --- a/cranelift/filetests/filetests/isa/aarch64/condbr.clif +++ b/cranelift/filetests/filetests/isa/aarch64/condbr.clif @@ -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 diff --git a/cranelift/filetests/filetests/runtests/i128-icmp-overflow.clif b/cranelift/filetests/filetests/runtests/i128-icmp-overflow.clif new file mode 100644 index 0000000000..e91b21de50 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/i128-icmp-overflow.clif @@ -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 diff --git a/cranelift/filetests/filetests/runtests/i128-icmp.clif b/cranelift/filetests/filetests/runtests/i128-icmp.clif index 5ebf051682..657e6e339d 100644 --- a/cranelift/filetests/filetests/runtests/i128-icmp.clif +++ b/cranelift/filetests/filetests/runtests/i128-icmp.clif @@ -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