From 2b68abed6a63011b856e12d528c0e9528b967c99 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Thu, 16 Apr 2020 13:43:52 -0700 Subject: [PATCH] Add vcode test for floating-point, and fix two FP bugs. - Added a filetest for the vcode output of lowering every handled FP opcode. - Fixed two bugs that were discovered while going through the lowerings: - Saturating FP->int operators would return `u{32,64}::MIN` rather than `0` for a NaN input. - `fcopysign` did not mask off the sign bit of the value whose sign is overwritten. These probably would have been caught by Wasm conformance tests soon (and the validity of these lowerings will ultimately be tested this way) but let's get them right by inspection, too! --- cranelift/codegen/src/isa/aarch64/lower.rs | 22 + .../vcode/aarch64/floating-point.clif | 790 ++++++++++++++++++ 2 files changed, 812 insertions(+) create mode 100644 cranelift/filetests/filetests/vcode/aarch64/floating-point.clif diff --git a/cranelift/codegen/src/isa/aarch64/lower.rs b/cranelift/codegen/src/isa/aarch64/lower.rs index 07a8e896e6..5a09d8eb4a 100644 --- a/cranelift/codegen/src/isa/aarch64/lower.rs +++ b/cranelift/codegen/src/isa/aarch64/lower.rs @@ -2019,6 +2019,7 @@ fn lower_insn_to_regs>(ctx: &mut C, insn: IRInst) { // MOV Xtmp1, Dinput0 // MOV Xtmp2, Dinput1 // AND Xtmp2, 0x8000_0000_0000_0000 + // BIC Xtmp1, 0x8000_0000_0000_0000 // ORR Xtmp1, Xtmp1, Xtmp2 // MOV Doutput, Xtmp1 @@ -2052,6 +2053,13 @@ fn lower_insn_to_regs>(ctx: &mut C, insn: IRInst) { alu_op, rd: tmp2, rn: tmp2.to_reg(), + imml: imml.clone(), + }); + let alu_op = choose_32_64(ty, ALUOp::AndNot32, ALUOp::AndNot64); + ctx.emit(Inst::AluRRImmLogic { + alu_op, + rd: tmp1, + rn: tmp1.to_reg(), imml, }); let alu_op = choose_32_64(ty, ALUOp::Orr32, ALUOp::Orr64); @@ -2127,6 +2135,7 @@ fn lower_insn_to_regs>(ctx: &mut C, insn: IRInst) { // FMIN Vtmp2, Vin, Vtmp1 // FIMM Vtmp1, 0 or 0 or i32::MIN or i64::MIN // FMAX Vtmp2, Vtmp2, Vtmp + // (if signed) FIMM Vtmp1, 0 // FCMP Vin, Vin // FCSEL Vtmp2, Vtmp1, Vtmp2, NE // on NaN, select 0 // convert Rout, Vtmp2 @@ -2187,6 +2196,19 @@ fn lower_insn_to_regs>(ctx: &mut C, insn: IRInst) { rn: rtmp2.to_reg(), rm: rtmp1.to_reg(), }); + if out_signed { + if in_bits == 32 { + ctx.emit(Inst::LoadFpuConst32 { + rd: rtmp1, + const_data: 0.0, + }); + } else { + ctx.emit(Inst::LoadFpuConst64 { + rd: rtmp1, + const_data: 0.0, + }); + } + } if in_bits == 32 { ctx.emit(Inst::FpuCmp32 { rn: rn, rm: rn }); ctx.emit(Inst::FpuCSel32 { diff --git a/cranelift/filetests/filetests/vcode/aarch64/floating-point.clif b/cranelift/filetests/filetests/vcode/aarch64/floating-point.clif new file mode 100644 index 0000000000..f55738b155 --- /dev/null +++ b/cranelift/filetests/filetests/vcode/aarch64/floating-point.clif @@ -0,0 +1,790 @@ +test vcode +target aarch64 + +function %f1(f32, f32) -> f32 { +block0(v0: f32, v1: f32): + v2 = fadd v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fadd s0, s0, s1 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f2(f64, f64) -> f64 { +block0(v0: f64, v1: f64): + v2 = fadd v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fadd d0, d0, d1 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f3(f32, f32) -> f32 { +block0(v0: f32, v1: f32): + v2 = fsub v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fsub s0, s0, s1 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f4(f64, f64) -> f64 { +block0(v0: f64, v1: f64): + v2 = fsub v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fsub d0, d0, d1 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f5(f32, f32) -> f32 { +block0(v0: f32, v1: f32): + v2 = fmul v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fmul s0, s0, s1 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f6(f64, f64) -> f64 { +block0(v0: f64, v1: f64): + v2 = fmul v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fmul d0, d0, d1 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f7(f32, f32) -> f32 { +block0(v0: f32, v1: f32): + v2 = fdiv v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fdiv s0, s0, s1 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f8(f64, f64) -> f64 { +block0(v0: f64, v1: f64): + v2 = fdiv v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fdiv d0, d0, d1 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f9(f32, f32) -> f32 { +block0(v0: f32, v1: f32): + v2 = fmin v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fmin s0, s0, s1 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f10(f64, f64) -> f64 { +block0(v0: f64, v1: f64): + v2 = fmin v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fmin d0, d0, d1 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f11(f32, f32) -> f32 { +block0(v0: f32, v1: f32): + v2 = fmax v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fmax s0, s0, s1 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f12(f64, f64) -> f64 { +block0(v0: f64, v1: f64): + v2 = fmax v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fmax d0, d0, d1 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f13(f32) -> f32 { +block0(v0: f32): + v1 = sqrt v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fsqrt s0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f15(f64) -> f64 { +block0(v0: f64): + v1 = sqrt v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fsqrt d0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f16(f32) -> f32 { +block0(v0: f32): + v1 = fabs v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fabs s0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f17(f64) -> f64 { +block0(v0: f64): + v1 = fabs v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fabs d0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f18(f32) -> f32 { +block0(v0: f32): + v1 = fneg v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fneg s0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f19(f64) -> f64 { +block0(v0: f64): + v1 = fneg v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fneg d0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f20(f32) -> f64 { +block0(v0: f32): + v1 = fpromote.f64 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fcvt d0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f21(f64) -> f32 { +block0(v0: f64): + v1 = fdemote.f32 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fcvt s0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f22(f32) -> f32 { +block0(v0: f32): + v1 = ceil v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: frintp s0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f22(f64) -> f64 { +block0(v0: f64): + v1 = ceil v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: frintp d0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f23(f32) -> f32 { +block0(v0: f32): + v1 = floor v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: frintm s0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f24(f64) -> f64 { +block0(v0: f64): + v1 = floor v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: frintm d0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f25(f32) -> f32 { +block0(v0: f32): + v1 = trunc v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: frintz s0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f26(f64) -> f64 { +block0(v0: f64): + v1 = trunc v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: frintz d0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f27(f32) -> f32 { +block0(v0: f32): + v1 = nearest v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: frintn s0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f28(f64) -> f64 { +block0(v0: f64): + v1 = nearest v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: frintn d0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f29(f32, f32, f32) -> f32 { +block0(v0: f32, v1: f32, v2: f32): + v3 = fma v0, v1, v2 + return v3 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fmadd s0, s0, s1, s2 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f30(f64, f64, f64) -> f64 { +block0(v0: f64, v1: f64, v2: f64): + v3 = fma v0, v1, v2 + return v3 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fmadd d0, d0, d1, d2 +; nextln: mov sp, fp + +function %f31(f32, f32) -> f32 { +block0(v0: f32, v1: f32): + v2 = fcopysign v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: mov x0, v0.d[0] +; nextln: mov x1, v1.d[0] +; nextln: and w1, w1, #2147483648 +; nextln: bic w0, w0, #2147483648 +; nextln: orr w0, w0, w1 +; nextln: mov v0.d[0], x0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f32(f64, f64) -> f64 { +block0(v0: f64, v1: f64): + v2 = fcopysign v0, v1 + return v2 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: mov x0, v0.d[0] +; nextln: mov x1, v1.d[0] +; nextln: and x1, x1, #9223372036854775808 +; nextln: bic x0, x0, #9223372036854775808 +; nextln: orr x0, x0, x1 +; nextln: mov v0.d[0], x0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f33(f32) -> i32 { +block0(v0: f32): + v1 = fcvt_to_uint.i32 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fcvtzu w0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f34(f32) -> i32 { +block0(v0: f32): + v1 = fcvt_to_sint.i32 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fcvtzs w0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f35(f32) -> i64 { +block0(v0: f32): + v1 = fcvt_to_uint.i64 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fcvtzu x0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f36(f32) -> i64 { +block0(v0: f32): + v1 = fcvt_to_sint.i64 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fcvtzs x0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f37(f64) -> i32 { +block0(v0: f64): + v1 = fcvt_to_uint.i32 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fcvtzu w0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f38(f64) -> i32 { +block0(v0: f64): + v1 = fcvt_to_sint.i32 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fcvtzs w0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f39(f64) -> i64 { +block0(v0: f64): + v1 = fcvt_to_uint.i64 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fcvtzu x0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f40(f64) -> i64 { +block0(v0: f64): + v1 = fcvt_to_sint.i64 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: fcvtzs x0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f41(i32) -> f32 { +block0(v0: i32): + v1 = fcvt_from_uint.f32 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: ucvtf s0, w0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f42(i32) -> f32 { +block0(v0: i32): + v1 = fcvt_from_sint.f32 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: scvtf s0, w0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f43(i64) -> f32 { +block0(v0: i64): + v1 = fcvt_from_uint.f32 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: ucvtf s0, x0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f44(i64) -> f32 { +block0(v0: i64): + v1 = fcvt_from_sint.f32 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: scvtf s0, x0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f45(i32) -> f64 { +block0(v0: i32): + v1 = fcvt_from_uint.f64 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: ucvtf d0, w0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f46(i32) -> f64 { +block0(v0: i32): + v1 = fcvt_from_sint.f64 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: scvtf d0, w0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f47(i64) -> f64 { +block0(v0: i64): + v1 = fcvt_from_uint.f64 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: ucvtf d0, x0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f48(i64) -> f64 { +block0(v0: i64): + v1 = fcvt_from_sint.f64 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: scvtf d0, x0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f49(f32) -> i32 { +block0(v0: f32): + v1 = fcvt_to_uint_sat.i32 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: ldr s1, pc+8 ; b 8 ; data.f32 4294967300 +; nextln: fmin s2, s0, s1 +; nextln: ldr s1, pc+8 ; b 8 ; data.f32 0 +; nextln: fmax s2, s2, s1 +; nextln: fcmp s0, s0 +; nextln: fcsel s0, s1, s2, ne +; nextln: fcvtzu w0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f50(f32) -> i32 { +block0(v0: f32): + v1 = fcvt_to_sint_sat.i32 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: ldr s1, pc+8 ; b 8 ; data.f32 2147483600 +; nextln: fmin s1, s0, s1 +; nextln: ldr s2, pc+8 ; b 8 ; data.f32 -2147483600 +; nextln: fmax s1, s1, s2 +; nextln: ldr s2, pc+8 ; b 8 ; data.f32 0 +; nextln: fcmp s0, s0 +; nextln: fcsel s0, s2, s1, ne +; nextln: fcvtzs w0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f51(f32) -> i64 { +block0(v0: f32): + v1 = fcvt_to_uint_sat.i64 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: ldr s1, pc+8 ; b 8 ; data.f32 18446744000000000000 +; nextln: fmin s2, s0, s1 +; nextln: ldr s1, pc+8 ; b 8 ; data.f32 0 +; nextln: fmax s2, s2, s1 +; nextln: fcmp s0, s0 +; nextln: fcsel s0, s1, s2, ne +; nextln: fcvtzu x0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f52(f32) -> i64 { +block0(v0: f32): + v1 = fcvt_to_sint_sat.i64 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: ldr s1, pc+8 ; b 8 ; data.f32 9223372000000000000 +; nextln: fmin s1, s0, s1 +; nextln: ldr s2, pc+8 ; b 8 ; data.f32 -9223372000000000000 +; nextln: fmax s1, s1, s2 +; nextln: ldr s2, pc+8 ; b 8 ; data.f32 0 +; nextln: fcmp s0, s0 +; nextln: fcsel s0, s2, s1, ne +; nextln: fcvtzs x0, s0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f53(f64) -> i32 { +block0(v0: f64): + v1 = fcvt_to_uint_sat.i32 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: ldr d1, pc+8 ; b 12 ; data.f64 4294967295 +; nextln: fmin d2, d0, d1 +; nextln: ldr d1, pc+8 ; b 12 ; data.f64 0 +; nextln: fmax d2, d2, d1 +; nextln: fcmp d0, d0 +; nextln: fcsel d0, d1, d2, ne +; nextln: fcvtzu w0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f54(f64) -> i32 { +block0(v0: f64): + v1 = fcvt_to_sint_sat.i32 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: ldr d1, pc+8 ; b 12 ; data.f64 2147483647 +; nextln: fmin d1, d0, d1 +; nextln: ldr d2, pc+8 ; b 12 ; data.f64 -2147483648 +; nextln: fmax d1, d1, d2 +; nextln: ldr d2, pc+8 ; b 12 ; data.f64 0 +; nextln: fcmp d0, d0 +; nextln: fcsel d0, d2, d1, ne +; nextln: fcvtzs w0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f55(f64) -> i64 { +block0(v0: f64): + v1 = fcvt_to_uint_sat.i64 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: ldr d1, pc+8 ; b 12 ; data.f64 18446744073709552000 +; nextln: fmin d2, d0, d1 +; nextln: ldr d1, pc+8 ; b 12 ; data.f64 0 +; nextln: fmax d2, d2, d1 +; nextln: fcmp d0, d0 +; nextln: fcsel d0, d1, d2, ne +; nextln: fcvtzu x0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret + +function %f56(f64) -> i64 { +block0(v0: f64): + v1 = fcvt_to_sint_sat.i64 v0 + return v1 +} + +; check: stp fp, lr, [sp, #-16]! +; nextln: mov fp, sp +; nextln: ldr d1, pc+8 ; b 12 ; data.f64 9223372036854776000 +; nextln: fmin d1, d0, d1 +; nextln: ldr d2, pc+8 ; b 12 ; data.f64 -9223372036854776000 +; nextln: fmax d1, d1, d2 +; nextln: ldr d2, pc+8 ; b 12 ; data.f64 0 +; nextln: fcmp d0, d0 +; nextln: fcsel d0, d2, d1, ne +; nextln: fcvtzs x0, d0 +; nextln: mov sp, fp +; nextln: ldp fp, lr, [sp], #16 +; nextln: ret