Repository: bytecodealliance/wasmtime
Pull request #8887 (2024-06-29 00:41:01)

cranelift/riscv: refactor rv_fma pattern
replace `if-let` with `let`


Patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 83f915183..42ba5f770 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -369,8 +369,10 @@ jobs:
           - name: wasmtime-cli
             checks: |
               -p wasmtime-cli --no-default-features
+              -p wasmtime-cli --no-default-features --features pooling-allocator
               -p wasmtime-cli --no-default-features --features run
               -p wasmtime-cli --no-default-features --features run,component-model
+              -p wasmtime-cli --no-default-features --features run,pooling-allocator
               -p wasmtime-cli --no-default-features --features compile
               -p wasmtime-cli --no-default-features --features compile,cranelift
               -p wasmtime-cli --no-default-features --features compile,cranelift,component-model
diff --git a/ci/docker/x86_64-linux/Dockerfile b/ci/docker/x86_64-linux/Dockerfile
index 3c1530745..a1bcdd23d 100644
--- a/ci/docker/x86_64-linux/Dockerfile
+++ b/ci/docker/x86_64-linux/Dockerfile
@@ -1,10 +1,5 @@
-FROM centos:7
+FROM almalinux:8
 
-RUN yum install -y git gcc make
-
-# The CMake in Centos 7 was a bit too old for us to use so download one from
-# CMake's own releases and use that instead.
-RUN curl -L https://github.com/Kitware/CMake/releases/download/v3.29.3/cmake-3.29.3-linux-x86_64.tar.gz | tar xzf -
-ENV PATH=$PATH:/cmake-3.29.3-linux-x86_64/bin
+RUN dnf install -y git gcc make cmake
 
 ENV PATH=$PATH:/rust/bin
diff --git a/cranelift/codegen/src/ir/globalvalue.rs b/cranelift/codegen/src/ir/globalvalue.rs
index 438a13e50..7c6ade00c 100644
--- a/cranelift/codegen/src/ir/globalvalue.rs
+++ b/cranelift/codegen/src/ir/globalvalue.rs
@@ -9,7 +9,7 @@ use core::fmt;
 use serde_derive::{Deserialize, Serialize};
 
 /// Information about a global value declaration.
-#[derive(Clone, PartialEq, Hash)]
+#[derive(Debug, Clone, PartialEq, Hash)]
 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
 pub enum GlobalValueData {
     /// Value is the address of the VM context struct.
diff --git a/cranelift/codegen/src/ir/jumptable.rs b/cranelift/codegen/src/ir/jumptable.rs
index dce347048..8e1e15c7d 100644
--- a/cranelift/codegen/src/ir/jumptable.rs
+++ b/cranelift/codegen/src/ir/jumptable.rs
@@ -20,7 +20,7 @@ use serde_derive::{Deserialize, Serialize};
 /// It can be accessed through the `default_block` and `default_block_mut` functions. All blocks
 /// may be iterated using the `all_branches` and `all_branches_mut` functions, which will both
 /// iterate over the default block first.
-#[derive(Clone, PartialEq, Hash)]
+#[derive(Debug, Clone, PartialEq, Hash)]
 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
 pub struct JumpTableData {
     // Table entries.
diff --git a/cranelift/codegen/src/isa/aarch64/inst.isle b/cranelift/codegen/src/isa/aarch64/inst.isle
index a6aaadace..8821f50f5 100644
--- a/cranelift/codegen/src/isa/aarch64/inst.isle
+++ b/cranelift/codegen/src/isa/aarch64/inst.isle
@@ -1331,7 +1331,10 @@
 ;; A floating-point unit (FPU) operation with three args.
 (type FPUOp3
   (enum
+    ;; Multiply-add
     (MAdd)
+    ;; Multiply-sub
+    (MSub)
 ))
 
 ;; A conversion from an FP to an integer value.
diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs
index c1f91b07a..d231a3280 100644
--- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs
+++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs
@@ -1873,6 +1873,7 @@ impl MachInstEmit for Inst {
             } => {
                 let top17 = match fpu_op {
                     FPUOp3::MAdd => 0b000_11111_00_0_00000_0,
+                    FPUOp3::MSub => 0b000_11111_00_0_00000_1,
                 };
                 let top17 = top17 | size.ftype() << 7;
                 sink.put4(enc_fpurrrr(top17, rd, rn, rm, ra));
diff --git a/cranelift/codegen/src/isa/aarch64/inst/mod.rs b/cranelift/codegen/src/isa/aarch64/inst/mod.rs
index 54e2a4f77..3098c4c98 100644
--- a/cranelift/codegen/src/isa/aarch64/inst/mod.rs
+++ b/cranelift/codegen/src/isa/aarch64/inst/mod.rs
@@ -1803,6 +1803,7 @@ impl Inst {
             } => {
                 let op = match fpu_op {
                     FPUOp3::MAdd => "fmadd",
+                    FPUOp3::MSub => "fmsub",
                 };
                 let rd = pretty_print_vreg_scalar(rd.to_reg(), size);
                 let rn = pretty_print_vreg_scalar(rn, size);
diff --git a/cranelift/codegen/src/isa/aarch64/lower.isle b/cranelift/codegen/src/isa/aarch64/lower.isle
index 5fd9bf67e..05946021e 100644
--- a/cranelift/codegen/src/isa/aarch64/lower.isle
+++ b/cranelift/codegen/src/isa/aarch64/lower.isle
@@ -513,8 +513,27 @@
 
 ;;;; Rules for `fma` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(rule (lower (has_type (ty_scalar_float ty) (fma x y z)))
-       (fpu_rrrr (FPUOp3.MAdd) (scalar_size ty) x y z))
+(type IsFneg (enum (Result (negate u64) (value Value))))
+
+(decl pure is_fneg (Value) IsFneg)
+(rule 1 (is_fneg (fneg n)) (IsFneg.Result 1 n))
+(rule 0 (is_fneg n) (IsFneg.Result 0 n))
+
+(decl pure is_fneg_neg (IsFneg) u64)
+(rule (is_fneg_neg (IsFneg.Result n _)) n)
+
+(decl pure get_fneg_value (IsFneg) Value)
+(rule (get_fneg_value (IsFneg.Result _ v)) v)
+
+(decl fmadd_series (Type u64 Value Value Value) InstOutput)
+(rule 0 (fmadd_series (ty_scalar_float ty) 0 x y z) (fpu_rrrr (FPUOp3.MAdd) (scalar_size ty) x y z))
+(rule 0 (fmadd_series (ty_scalar_float ty) 1 x y z) (fpu_rrrr (FPUOp3.MSub) (scalar_size ty) x y z))
+
+(rule (lower (has_type (ty_scalar_float ty) (fma x_src y_src z)))
+  (let
+      ((x_res IsFneg (is_fneg x_src))
+       (y_res IsFneg (is_fneg y_src)))
+      (fmadd_series ty (u64_xor (is_fneg_neg x_res) (is_fneg_neg y_res)) (get_fneg_value x_res) (get_fneg_value y_res) z)))
 
 ;; Delegate vector-based lowerings to helpers below
 (rule 1 (lower (has_type ty @ (multi_lane _ _) (fma x y z)))
diff --git a/cranelift/codegen/src/isa/riscv64/lower.isle b/cranelift/codegen/src/isa/riscv64/lower.isle
index 04de11d1f..3019d4739 100644
--- a/cranelift/codegen/src/isa/riscv64/lower.isle
+++ b/cranelift/codegen/src/isa/riscv64/lower.isle
@@ -1554,11 +1554,21 @@
 (rule 1 (is_fneg (fneg x)) (IsFneg.Result 1 x))
 (rule 0 (is_fneg x) (IsFneg.Result 0 x))
 
+(decl pure is_fneg_neg (IsFneg) u64)
+(rule (is_fneg_neg (IsFneg.Result n _)) n)
+
+(decl pure get_fneg_value (IsFneg) Value)
+(rule (get_fneg_value (IsFneg.Result _ v)) v)
+
 (rule (lower (has_type ty (fma x_src y_src z_src)))
-  (if-let (IsFneg.Result neg_x x) (is_fneg x_src))
-  (if-let (IsFneg.Result neg_y y) (is_fneg y_src))
-  (if-let (IsFneg.Result neg_z z) (is_fneg z_src))
-  (rv_fma ty (u64_xor neg_x neg_y) neg_z x y z))
+  (let
+    ((x_res IsFneg (is_fneg x_src))
+     (y_res IsFneg (is_fneg y_src))
+     (z_res IsFneg (is_fneg z_src))
+     (x Value (get_fneg_value x_res))
+     (y Value (get_fneg_value y_res))
+     (z Value (get_fneg_value z_res)))
+    (rv_fma ty (u64_xor (is_fneg_neg x_res) (is_fneg_neg y_res)) (is_fneg_neg z_res) x y z)))
 
 ; parity arguments indicate whether to negate the x*y term or the z term, respectively
 (decl rv_fma (Type u64 u64 Value Value Value) InstOutput)
diff --git a/cranelift/codegen/src/machinst/vcode.rs b/cranelift/codegen/src/machinst/vcode.rs
index 48a45c90e..b723c9621 100644
--- a/cranelift/codegen/src/machinst/vcode.rs
+++ b/cranelift/codegen/src/machinst/vcode.rs
@@ -1448,12 +1448,22 @@ impl<I: VCodeInst> fmt::Debug for VCode<I> {
 
         for block in 0..self.num_blocks() {
             let block = BlockIndex::new(block);
-            writeln!(f, "Block {}:", block.index())?;
+            writeln!(
+                f,
+                "Block {}({:?}):",
+                block.index(),
+                self.block_params(block)
+            )?;
             if let Some(bb) = self.bindex_to_bb(block) {
                 writeln!(f, "    (original IR block: {})", bb)?;
             }
-            for succ in self.block_succs(block) {
-                writeln!(f, "    (successor: Block {})", succ.index())?;
+            for (succ_idx, succ) in self.block_succs(block).iter().enumerate() {
+                writeln!(
+                    f,
+                    "    (successor: Block {}({:?}))",
+                    succ.index(),
+                    self.branch_blockparams(block, InsnIndex::new(0) /* dummy */, succ_idx)
+                )?;
             }
             for inst in self.block_ranges.get(block.index()) {
                 writeln!(
diff --git a/crates/cli-flags/Cargo.toml b/crates/cli-flags/Cargo.toml
index 12ef9fb05..705e0012a 100644
--- a/crates/cli-flags/Cargo.toml
+++ b/crates/cli-flags/Cargo.toml
@@ -21,6 +21,7 @@ wasmtime = { workspace = true, features = ["gc"] }
 humantime = { workspace = true }
 
 [features]
+async = ["wasmtime/async"]
 pooling-allocator = ["wasmtime/pooling-allocator"]
 component-model = ["wasmtime/component-model"]
 cache = ["wasmtime/cache"]
diff --git a/crates/cli-flags/src/lib.rs b/crates/cli-flags/src/lib.rs
index a45e3fffa..8aafa447b 100644
--- a/crates/cli-flags/src/lib.rs
+++ b/crates/cli-flags/src/lib.rs
@@ -589,8 +589,10 @@ impl CommonOptions {
                     if let Some(limit) = self.opts.pooling_total_tables {
                         cfg.total_tables(limit);
                     }
-                    if let Some(limit) = self.opts.pooling_total_stacks {
-                        cfg.total_stacks(limit);
+                    match_feature! {
+                        ["async" : self.opts.pooling_total_stacks]
+                        limit => cfg.total_stacks(limit),
+                        _ => err,
                     }
                     if let Some(limit) = self.opts.pooling_max_memory_size {
                         cfg.max_memory_size(limit);


Test patch:
diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs
index ffb3f73de..f4448b64b 100644
--- a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs
+++ b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs
@@ -6440,6 +6440,19 @@ fn test_aarch64_binemit() {
         "fmadd s15, s30, s31, s1",
     ));
 
+    insns.push((
+        Inst::FpuRRRR {
+            fpu_op: FPUOp3::MSub,
+            size: ScalarSize::Size32,
+            rd: writable_vreg(15),
+            rn: vreg(30),
+            rm: vreg(31),
+            ra: vreg(1),
+        },
+        "CF871F1F",
+        "fmsub s15, s30, s31, s1",
+    ));
+
     insns.push((
         Inst::FpuRRRR {
             fpu_op: FPUOp3::MAdd,
@@ -6453,6 +6466,19 @@ fn test_aarch64_binemit() {
         "fmadd d15, d30, d31, d1",
     ));
 
+    insns.push((
+        Inst::FpuRRRR {
+            fpu_op: FPUOp3::MSub,
+            size: ScalarSize::Size64,
+            rd: writable_vreg(15),
+            rn: vreg(30),
+            rm: vreg(31),
+            ra: vreg(1),
+        },
+        "CF875F1F",
+        "fmsub d15, d30, d31, d1",
+    ));
+
     insns.push((
         Inst::FpuRRI {
             fpu_op: FPUOpRI::UShr32(FPURightShiftImm::maybe_from_u8(32, 32).unwrap()),
diff --git a/cranelift/filetests/filetests/isa/aarch64/fma.clif b/cranelift/filetests/filetests/isa/aarch64/fma.clif
index 247e67a03..12e0f081a 100644
--- a/cranelift/filetests/filetests/isa/aarch64/fma.clif
+++ b/cranelift/filetests/filetests/isa/aarch64/fma.clif
@@ -33,6 +33,40 @@ block0(v0: f64, v1: f64, v2: f64):
 ;   fmadd d0, d0, d1, d2
 ;   ret
 
+function %fmsub_f32(f32, f32, f32) -> f32 {
+block0(v0: f32, v1: f32, v2: f32):
+    v3 = fneg v1
+    v4 = fma v0, v3, v2
+    return v4
+}
+
+; VCode:
+; block0:
+;   fmsub s0, s0, s1, s2
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   fmsub s0, s0, s1, s2
+;   ret
+
+function %fmsub_f64(f64, f64, f64) -> f64 {
+block0(v0: f64, v1: f64, v2: f64):
+    v3 = fneg v1
+    v4 = fma v0, v3, v2
+    return v4
+}
+
+; VCode:
+; block0:
+;   fmsub d0, d0, d1, d2
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   fmsub d0, d0, d1, d2
+;   ret
+
 function %fma_f32x4(f32x4, f32x4, f32x4) -> f32x4 {
 block0(v0: f32x4, v1: f32x4, v2: f32x4):
     v3 = fma v0, v1, v2