diff --git a/.github/workflows/w3c-publish.yml b/.github/workflows/w3c-publish.yml
index d68183abfc..d1b2675921 100644
--- a/.github/workflows/w3c-publish.yml
+++ b/.github/workflows/w3c-publish.yml
@@ -7,6 +7,10 @@ on:
 
   # Allows you to run this workflow manually from the Actions tab
   workflow_dispatch:
+    inputs:
+      w3c-status:
+        required: true
+        type: string
 
 jobs:
   publish-to-w3c-TR:
@@ -30,7 +34,7 @@ jobs:
       - name: Publish all specs to their https://www.w3.org/TR/ URLs
         run: cd document && make -e WD-echidna-CI
         env:
-          STATUS: --md-status=WD
+          W3C_STATUS: ${{ github.event_name == 'push' && 'WD' || inputs.w3c-status }}
           W3C_ECHIDNA_TOKEN_CORE: ${{ secrets.W3C_ECHIDNA_TOKEN_CORE }}
           W3C_ECHIDNA_TOKEN_JSAPI: ${{ secrets.W3C_ECHIDNA_TOKEN_JSAPI }}
           W3C_ECHIDNA_TOKEN_WEBAPI: ${{ secrets.W3C_ECHIDNA_TOKEN_WEBAPI }}
diff --git a/document/LICENSE b/document/LICENSE
new file mode 100644
index 0000000000..726ef38af3
--- /dev/null
+++ b/document/LICENSE
@@ -0,0 +1,2 @@
+This document is licensed under the W3C Software and Document License.
+Its text can be found at https://www.w3.org/copyright/software-license/
diff --git a/document/Makefile b/document/Makefile
index 77a79ee70f..e5b35d6c74 100644
--- a/document/Makefile
+++ b/document/Makefile
@@ -28,21 +28,21 @@ diff: $(DIRS:%=diff-%)
 # macOS: do “brew install tar” & run “make” as: TAR=gtar make -e WD-tar
 .PHONY: WD-tar
 WD-tar:
-	for dir in $(DIRS); \
-		do STATUS=--md-status=WD TAR=$(TAR) $(MAKE) -e -C $$dir $@;\
+	for dir in $(DIRS); do \
+		TAR=$(TAR) $(MAKE) -e -C $$dir $@ || exit 1; \
 	done
 
 # macOS: do “brew install tar” & run “make” as: TAR=gtar make -e WD-echidna
 .PHONY: WD-echidna
 WD-echidna:
-	for dir in $(DIRS); \
-		do $(MAKE) -e -C $$dir $@;\
+	for dir in $(DIRS); do \
+		$(MAKE) -e -C $$dir $@ || exit 1; \
 	done
 
 .PHONY: WD-echidna-CI
 WD-echidna-CI:
-	for dir in $(DIRS); \
-		do $(MAKE) -e -C $$dir $@;\
+	for dir in $(DIRS); do \
+		$(MAKE) -e -C $$dir $@ || exit 1; \
 	done
 
 # Directory-specific targets.
diff --git a/document/core/Makefile b/document/core/Makefile
index 3ac2f1c814..f72ee715ea 100644
--- a/document/core/Makefile
+++ b/document/core/Makefile
@@ -2,6 +2,7 @@
 #
 
 # You can set these variables from the command line.
+W3C_STATUS    = ED
 SPHINXOPTS    =
 SPHINXBUILD   = sphinx-build
 PAPER         = a4
@@ -154,7 +155,7 @@ bikeshed: $(GENERATED)
 	@echo
 	@echo =========================================================================
 	mkdir -p $(BUILDDIR)/bikeshed_mathjax/
-	bikeshed spec $(STATUS) index.bs $(BUILDDIR)/bikeshed_mathjax/index.html
+	bikeshed spec --md-status=$(W3C_STATUS) index.bs $(BUILDDIR)/bikeshed_mathjax/index.html
 	mkdir -p $(BUILDDIR)/html/bikeshed/
 	(cd util/katex/ && yarn && yarn build && npm install --only=prod)
 	python3 util/mathjax2katex.py $(BUILDDIR)/bikeshed_mathjax/index.html \
@@ -196,7 +197,7 @@ WD-echidna: WD-tar
 		-F "tar=@$(BUILDDIR)/WD.tar" \
 		-F "decision=$(DECISION_URL)" | tee $(BUILDDIR)/WD-echidna-id.txt
 	@echo
-	@echo "Published working draft. Check its status at https://labs.w3.org/echidna/api/status?id=`cat $(BUILDDIR)/WD-echidna-id.txt`"
+	@echo "Published $(W3C_STATUS). Check its status at https://labs.w3.org/echidna/api/status?id=`cat $(BUILDDIR)/WD-echidna-id.txt`"
 
 .PHONY: WD-echidna-CI
 WD-echidna-CI: WD-tar
@@ -210,7 +211,7 @@ WD-echidna-CI: WD-tar
 		-F "token=$(W3C_ECHIDNA_TOKEN_CORE)" \
 		-F "decision=$(DECISION_URL)" | tee $(BUILDDIR)/WD-echidna-id.txt
 	@echo
-	@echo "Published working draft. Check its status at https://labs.w3.org/echidna/api/status?id=`cat $(BUILDDIR)/WD-echidna-id.txt`"
+	@echo "Published $(W3C_STATUS). Check its status at https://labs.w3.org/echidna/api/status?id=`cat $(BUILDDIR)/WD-echidna-id.txt`"
 
 .PHONY: diff
 diff: bikeshed
diff --git a/document/core/index.bs b/document/core/index.bs
index 35fdf277a1..f85b5e2013 100644
--- a/document/core/index.bs
+++ b/document/core/index.bs
@@ -7,6 +7,7 @@ Issue Tracking: GitHub https://github.com/WebAssembly/spec/issues
 Level: 2
 TR: https://www.w3.org/TR/wasm-core-2/
 ED: https://webassembly.github.io/spec/core/bikeshed/
+Implementation Report: https://webassembly.org/features/
 Editor: Andreas Rossberg, w3cid 82328
 Repository: WebAssembly/spec
 Markup Shorthands: css no, markdown no, algorithm no, idl no
diff --git a/document/core/static/custom.css b/document/core/static/custom.css
index 33bb863d42..950236af0f 100644
--- a/document/core/static/custom.css
+++ b/document/core/static/custom.css
@@ -15,10 +15,16 @@ body {
   font-size: 15px;
 }
 
-div.document { width: 1000px; }
+div.document {
+  width: unset;
+  max-width: 1000px;
+}
 div.bodywrapper { margin: 0 0 0 200px; }
 div.body { padding: 0 10px 0 10px; }
-div.footer { width: 1000px; }
+div.footer {
+  width: unset;
+  max-width: 1000px;
+}
 
 div.body h1 { font-size: 200%; }
 div.body h2 { font-size: 150%; }
diff --git a/document/js-api/Makefile b/document/js-api/Makefile
index fcc69f7b39..3880f240fa 100644
--- a/document/js-api/Makefile
+++ b/document/js-api/Makefile
@@ -1,3 +1,4 @@
+W3C_STATUS    = ED
 BUILDDIR      = _build
 STATICDIR     = _static
 DOWNLOADDIR   = _download
@@ -8,7 +9,7 @@ TAR           = tar
 .PHONY: all
 all:
 	mkdir -p $(BUILDDIR)/html
-	bikeshed spec index.bs $(BUILDDIR)/html/index.html
+	bikeshed spec --md-status=$(W3C_STATUS) index.bs $(BUILDDIR)/html/index.html
 	@echo "Build finished. The HTML pages are in `pwd`/$(BUILDDIR)/html."
 
 .PHONY: publish
@@ -33,7 +34,7 @@ diff: all
 # macOS tar has no “--transform” option (only GNU tar does), so on macOS,
 # do “brew install tar” & run “make” like this: “TAR=gtar make -e WD-tar”
 WD-tar: all
-	bikeshed spec --md-status=WD index.bs $(BUILDDIR)/html/index.html
+	bikeshed spec --md-status=$(W3C_STATUS) index.bs $(BUILDDIR)/html/index.html
 	$(TAR) -C $(BUILDDIR)/html --transform="s/index.html/Overview.html/" -cf $(BUILDDIR)/WD.tar index.html
 	@echo "Built $(BUILDDIR)/WD.tar."
 
@@ -62,4 +63,4 @@ WD-echidna-CI: WD-tar
 		-F "token=$(W3C_ECHIDNA_TOKEN_JSAPI)" \
 		-F "decision=$(DECISION_URL)" | tee $(BUILDDIR)/WD-echidna-id.txt
 	@echo
-	@echo "Published working draft. Check its status at https://labs.w3.org/echidna/api/status?id=`cat $(BUILDDIR)/WD-echidna-id.txt`"
+	@echo "Published w$(W3C_STATUS). Check its status at https://labs.w3.org/echidna/api/status?id=`cat $(BUILDDIR)/WD-echidna-id.txt`"
diff --git a/document/js-api/index.bs b/document/js-api/index.bs
index b32f5b0297..02a1fc2fcb 100644
--- a/document/js-api/index.bs
+++ b/document/js-api/index.bs
@@ -7,6 +7,7 @@ Issue Tracking: GitHub https://github.com/WebAssembly/spec/issues
 Level: 2
 TR: https://www.w3.org/TR/wasm-js-api-2/
 ED: https://webassembly.github.io/spec/js-api/
+Implementation Report: https://webassembly.org/features/
 Editor: Ms2ger, w3cid 46309, Igalia
 Repository: WebAssembly/spec
 Markup Shorthands: css no, markdown yes
diff --git a/document/web-api/Makefile b/document/web-api/Makefile
index 675593d865..3e8f0632a2 100644
--- a/document/web-api/Makefile
+++ b/document/web-api/Makefile
@@ -1,3 +1,4 @@
+W3C_STATUS    = ED
 BUILDDIR      = _build
 STATICDIR     = _static
 DOWNLOADDIR   = _download
@@ -8,7 +9,7 @@ TAR           = tar
 .PHONY: all
 all:
 	mkdir -p $(BUILDDIR)/html
-	bikeshed spec index.bs $(BUILDDIR)/html/index.html
+	bikeshed spec --md-status=$(W3C_STATUS) index.bs $(BUILDDIR)/html/index.html
 	@echo "Build finished. The HTML pages are in `pwd`/$(BUILDDIR)/html."
 
 .PHONY: publish
@@ -33,7 +34,7 @@ diff: all
 # macOS tar has no “--transform” option (only GNU tar does), so on macOS,
 # do “brew install tar” & run “make” like this: “TAR=gtar make -e WD-tar”
 WD-tar: all
-	bikeshed spec --md-status=WD index.bs $(BUILDDIR)/html/index.html
+	bikeshed spec --md-status=$(W3C_STATUS) index.bs $(BUILDDIR)/html/index.html
 	$(TAR) -C $(BUILDDIR)/html --transform="s/index.html/Overview.html/" -cf $(BUILDDIR)/WD.tar index.html
 	@echo "Built $(BUILDDIR)/WD.tar."
 
@@ -62,4 +63,4 @@ WD-echidna-CI: WD-tar
 		-F "token=$(W3C_ECHIDNA_TOKEN_WEBAPI)" \
 		-F "decision=$(DECISION_URL)" | tee $(BUILDDIR)/WD-echidna-id.txt
 	@echo
-	@echo "Published working draft. Check its status at https://labs.w3.org/echidna/api/status?id=`cat $(BUILDDIR)/WD-echidna-id.txt`"
+	@echo "Published $(W3C_STATUS). Check its status at https://labs.w3.org/echidna/api/status?id=`cat $(BUILDDIR)/WD-echidna-id.txt`"
diff --git a/document/web-api/index.bs b/document/web-api/index.bs
index efc6a66635..db58b4495b 100644
--- a/document/web-api/index.bs
+++ b/document/web-api/index.bs
@@ -7,6 +7,7 @@ Issue Tracking: GitHub https://github.com/WebAssembly/spec/issues
 Level: 2
 TR: https://www.w3.org/TR/wasm-web-api-2/
 ED: https://webassembly.github.io/spec/web-api/
+Implementation Report: https://webassembly.org/features/
 Editor: Ms2ger, w3cid 46309, Igalia
 Repository: WebAssembly/spec
 Abstract: This document describes the integration of WebAssembly with the broader web platform.
diff --git a/test/core/binary.wast b/test/core/binary.wast
index cf47ddbb01..0e158c1f81 100644
--- a/test/core/binary.wast
+++ b/test/core/binary.wast
@@ -1067,3 +1067,116 @@
   )
   "unexpected content after last section"
 )
+
+;; Type section out of order
+(assert_malformed
+  (module binary
+      "\00asm" "\01\00\00\00"
+      "\02\01\00"                 ;; Import section with zero entries
+      "\01\01\00"                 ;; Type section with zero entries
+  )
+  "unexpected content after last section"
+)
+
+;; Import section out of order
+(assert_malformed
+  (module binary
+      "\00asm" "\01\00\00\00"
+      "\03\01\00"                 ;; Function section with zero entries
+      "\02\01\00"                 ;; Import section with zero entries
+  )
+  "unexpected content after last section"
+)
+
+;; Function section out of order
+(assert_malformed
+  (module binary
+      "\00asm" "\01\00\00\00"
+      "\04\01\00"                 ;; Table section with zero entries
+      "\03\01\00"                 ;; Function section with zero entries
+  )
+  "unexpected content after last section"
+)
+
+;; Table section out of order
+(assert_malformed
+  (module binary
+      "\00asm" "\01\00\00\00"
+      "\05\01\00"                 ;; Memory section with zero entries
+      "\04\01\00"                 ;; Table section with zero entries
+  )
+  "unexpected content after last section"
+)
+
+;; Memory section out of order
+(assert_malformed
+  (module binary
+      "\00asm" "\01\00\00\00"
+      "\06\01\00"                 ;; Global section with zero entries
+      "\05\01\00"                 ;; Memory section with zero entries
+  )
+  "unexpected content after last section"
+)
+
+;; Global section out of order
+(assert_malformed
+  (module binary
+      "\00asm" "\01\00\00\00"
+      "\07\01\00"                 ;; Export section with zero entries
+      "\06\01\00"                 ;; Global section with zero entries
+  )
+  "unexpected content after last section"
+)
+
+;; Export section out of order
+(assert_malformed
+  (module binary
+      "\00asm" "\01\00\00\00"
+      "\03\02\01\00"              ;; Function section
+      "\08\01\00"                 ;; Start section: function 0
+      "\07\01\00"                 ;; Export section with zero entries
+  )
+  "unexpected content after last section"
+)
+
+;; Start section out of order
+(assert_malformed
+  (module binary
+      "\00asm" "\01\00\00\00"
+      "\03\02\01\00"              ;; Function section
+      "\09\01\00"                 ;; Element section with zero entries
+      "\08\01\00"                 ;; Start section: function 0
+  )
+  "unexpected content after last section"
+)
+
+;; Element section out of order
+(assert_malformed
+  (module binary
+      "\00asm" "\01\00\00\00"
+      "\0c\01\01"                 ;; Datacount section with value "1"
+      "\09\01\00"                 ;; Element section with zero entries
+  )
+  "unexpected content after last section"
+)
+
+;; Datacount section out of order
+(assert_malformed
+  (module binary
+      "\00asm" "\01\00\00\00"
+      "\0a\01\00"                 ;; Code section with zero entries
+      "\0c\01\01"                 ;; Datacount section with value "1"
+  )
+  "unexpected content after last section"
+)
+
+;; Code section out of order
+(assert_malformed
+  (module binary
+      "\00asm" "\01\00\00\00"
+      "\0b\01\00"                 ;; Data section with zero entries
+      "\0a\01\00"                 ;; Code section with zero entries
+  )
+  "unexpected content after last section"
+)
+
diff --git a/test/core/float_exprs.wast b/test/core/float_exprs.wast
index e6d4f10e91..274c996652 100644
--- a/test/core/float_exprs.wast
+++ b/test/core/float_exprs.wast
@@ -649,7 +649,8 @@
 (assert_return (invoke "no_fold_promote_demote" (f32.const inf)) (f32.const inf))
 (assert_return (invoke "no_fold_promote_demote" (f32.const -inf)) (f32.const -inf))
 
-;; Test that demote(x+promote(y)) is not folded to demote(x)+y.
+;; Test that demote(x+promote(y)) is not folded to demote(x)+y, and that
+;; demote(promote(y)+x) is not folded to y+demote(x).
 
 (module
   (func (export "no_demote_mixed_add") (param $x f64) (param $y f32) (result f32)
@@ -670,11 +671,14 @@
 (assert_return (invoke "no_demote_mixed_add_commuted" (f32.const 0x1.096f4ap-29) (f64.const -0x1.0d5110e3385bbp-20)) (f32.const -0x1.0ccc5ap-20))
 (assert_return (invoke "no_demote_mixed_add_commuted" (f32.const -0x1.24e474p-41) (f64.const -0x1.73852db4e5075p-20)) (f32.const -0x1.738536p-20))
 
-;; Test that demote(x-promote(y)) is not folded to demote(x)-y.
+;; Test that demote(x-promote(y)) is not folded to demote(x)-y, and that
+;; demote(promote(y)-x) is not folded to y-demote(x).
 
 (module
   (func (export "no_demote_mixed_sub") (param $x f64) (param $y f32) (result f32)
     (f32.demote_f64 (f64.sub (local.get $x) (f64.promote_f32 (local.get $y)))))
+  (func (export "no_demote_mixed_sub_commuted") (param $y f32) (param $x f64) (result f32)
+    (f32.demote_f64 (f64.sub (f64.promote_f32 (local.get $y)) (local.get $x))))
 )
 
 (assert_return (invoke "no_demote_mixed_sub" (f64.const 0x1.a0a183220e9b1p+82) (f32.const 0x1.c5acf8p+61)) (f32.const 0x1.a0a174p+82))
@@ -683,6 +687,56 @@
 (assert_return (invoke "no_demote_mixed_sub" (f64.const 0x1.0459f34091dbfp-54) (f32.const 0x1.61ad08p-71)) (f32.const 0x1.045942p-54))
 (assert_return (invoke "no_demote_mixed_sub" (f64.const 0x1.a7498dca3fdb7p+14) (f32.const 0x1.ed21c8p+15)) (f32.const -0x1.197d02p+15))
 
+(assert_return (invoke "no_demote_mixed_sub_commuted" (f32.const 0x1.c5acf8p+61) (f64.const 0x1.a0a183220e9b1p+82)) (f32.const -0x1.a0a174p+82))
+(assert_return (invoke "no_demote_mixed_sub_commuted" (f32.const 0x1.d48ca4p+17) (f64.const -0x1.6e2c5ac39f63ep+30)) (f32.const 0x1.6e3bp+30))
+(assert_return (invoke "no_demote_mixed_sub_commuted" (f32.const 0x1.9d69bcp-12) (f64.const -0x1.98c74350dde6ap+6)) (f32.const 0x1.98c7aap+6))
+(assert_return (invoke "no_demote_mixed_sub_commuted" (f32.const 0x1.61ad08p-71) (f64.const 0x1.0459f34091dbfp-54)) (f32.const -0x1.045942p-54))
+(assert_return (invoke "no_demote_mixed_sub_commuted" (f32.const 0x1.ed21c8p+15) (f64.const 0x1.a7498dca3fdb7p+14)) (f32.const 0x1.197d02p+15))
+
+;; Test that demote(x*promote(y)) is not folded to demote(x)*y, and that
+;; demote(promote(y)*x) is not folded to y*demote(x).
+
+(module
+  (func (export "no_demote_mixed_mul") (param $x f64) (param $y f32) (result f32)
+    (f32.demote_f64 (f64.mul (local.get $x) (f64.promote_f32 (local.get $y)))))
+  (func (export "no_demote_mixed_mul_commuted") (param $y f32) (param $x f64) (result f32)
+    (f32.demote_f64 (f64.mul (f64.promote_f32 (local.get $y)) (local.get $x))))
+)
+
+(assert_return (invoke "no_demote_mixed_mul" (f64.const 0x1.a19789e5aa475p-202) (f32.const 0x1.858cbep+113)) (f32.const 0x1.3db86cp-88))
+(assert_return (invoke "no_demote_mixed_mul" (f64.const 0x1.8f0e6a5a53f15p+140) (f32.const 0x1.2ef826p-107)) (f32.const 0x1.d845d2p+33))
+(assert_return (invoke "no_demote_mixed_mul" (f64.const 0x1.f03aa769e296cp+176) (f32.const 0x1.a9255p-57)) (f32.const 0x1.9c0cdap+120))
+(assert_return (invoke "no_demote_mixed_mul" (f64.const 0x1.9cd70b636bc52p+221) (f32.const 0x1.3f3ac6p-122)) (f32.const 0x1.01676p+100))
+(assert_return (invoke "no_demote_mixed_mul" (f64.const 0x1.c56b4c2991a3cp-170) (f32.const 0x1.1ad242p+48)) (f32.const 0x1.f4ec98p-122))
+
+(assert_return (invoke "no_demote_mixed_mul_commuted" (f32.const 0x1.858cbep+113) (f64.const 0x1.a19789e5aa475p-202)) (f32.const 0x1.3db86cp-88))
+(assert_return (invoke "no_demote_mixed_mul_commuted" (f32.const 0x1.2ef826p-107) (f64.const 0x1.8f0e6a5a53f15p+140)) (f32.const 0x1.d845d2p+33))
+(assert_return (invoke "no_demote_mixed_mul_commuted" (f32.const 0x1.a9255p-57) (f64.const 0x1.f03aa769e296cp+176)) (f32.const 0x1.9c0cdap+120))
+(assert_return (invoke "no_demote_mixed_mul_commuted" (f32.const 0x1.3f3ac6p-122) (f64.const 0x1.9cd70b636bc52p+221)) (f32.const 0x1.01676p+100))
+(assert_return (invoke "no_demote_mixed_mul_commuted" (f32.const 0x1.1ad242p+48) (f64.const 0x1.c56b4c2991a3cp-170)) (f32.const 0x1.f4ec98p-122))
+
+;; Test that demote(x/promote(y)) is not folded to demote(x)/y, and that
+;; demote(promote(y)/x) is not folded to y/demote(x).
+
+(module
+  (func (export "no_demote_mixed_div") (param $x f64) (param $y f32) (result f32)
+    (f32.demote_f64 (f64.div (local.get $x) (f64.promote_f32 (local.get $y)))))
+  (func (export "no_demote_mixed_div_commuted") (param $y f32) (param $x f64) (result f32)
+    (f32.demote_f64 (f64.div (f64.promote_f32 (local.get $y)) (local.get $x))))
+)
+
+(assert_return (invoke "no_demote_mixed_div" (f64.const 0x1.40d0b55d4cee1p+150) (f32.const 0x1.6c7496p+103)) (f32.const 0x1.c2b158p+46))
+(assert_return (invoke "no_demote_mixed_div" (f64.const 0x1.402750f34cd98p-153) (f32.const 0x1.3db8ep-82)) (f32.const 0x1.01f586p-71))
+(assert_return (invoke "no_demote_mixed_div" (f64.const 0x1.3f7ece1a790a7p-37) (f32.const 0x1.a5652p-128)) (f32.const 0x1.8430dp+90))
+(assert_return (invoke "no_demote_mixed_div" (f64.const 0x1.5171328e16885p-138) (f32.const 0x1.10636ap-88)) (f32.const 0x1.3d23cep-50))
+(assert_return (invoke "no_demote_mixed_div" (f64.const 0x1.d3a380fc986ccp+74) (f32.const 0x1.f095b6p+88)) (f32.const 0x1.e227c4p-15))
+
+(assert_return (invoke "no_demote_mixed_div_commuted" (f32.const 0x1.d78ddcp-74) (f64.const 0x1.2c57e125069e2p-42)) (f32.const 0x1.91eed6p-32))
+(assert_return (invoke "no_demote_mixed_div_commuted" (f32.const 0x1.7db224p+26) (f64.const 0x1.1c291ec609ed4p+159)) (f32.const 0x1.57dfp-133))
+(assert_return (invoke "no_demote_mixed_div_commuted" (f32.const 0x1.e7a824p-40) (f64.const 0x1.f4bdb25ff00fcp-137)) (f32.const 0x1.f29f22p+96))
+(assert_return (invoke "no_demote_mixed_div_commuted" (f32.const 0x1.730b8p+80) (f64.const 0x1.880fb331a64cap+210)) (f32.const 0x1.e48ep-131))
+(assert_return (invoke "no_demote_mixed_div_commuted" (f32.const 0x1.7715fcp-73) (f64.const 0x1.6feb1fa66f11bp-198)) (f32.const 0x1.04fcb6p+125))
+
 ;; Test that converting between integer and float and back isn't folded away.
 
 (module
diff --git a/test/core/float_misc.wast b/test/core/float_misc.wast
index 3d83281d77..a2153cfabd 100644
--- a/test/core/float_misc.wast
+++ b/test/core/float_misc.wast
@@ -587,6 +587,50 @@
 (assert_return (invoke "f64.sqrt" (f64.const 0x1.ffffffffffffep-1)) (f64.const 0x1.fffffffffffffp-1))
 (assert_return (invoke "f64.sqrt" (f64.const 0x1.ffffffffffffdp-1)) (f64.const 0x1.ffffffffffffep-1))
 
+;; Test the values of sqrt around ¼, where `sqrt(x) - x` is greatest.
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.fffffep-3)) (f32.const 0x1.fffffep-2))
+(assert_return (invoke "f32.sqrt" (f32.const 0x1p-2)) (f32.const 0x1p-1))
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.000002p-2)) (f32.const 0x1p-1))
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.000004p-2)) (f32.const 0x1.000002p-1))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.fffffffffffffp-3)) (f64.const 0x1.fffffffffffffp-2))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1p-2)) (f64.const 0x1p-1))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.0000000000001p-2)) (f64.const 0x1p-1))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.0000000000002p-2)) (f64.const 0x1.0000000000001p-1))
+
+;; Test some values that in some systems differ between CPU and DSP.
+;; https://e2e.ti.com/support/processors-group/processors/f/processors-forum/30725/sqrt-function-gives-slightly-different-results---may-be-rounding-problem
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.fb41d4p+37)) (f32.const 0x1.fd9f8p+18))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.fb41d442eeb1bp+37)) (f64.const 0x1.fd9f808a0b68dp+18))
+
+;; Test some values that in some systems differ between CPU and GPU.
+;; https://forums.developer.nvidia.com/t/sqrt-precision/18597
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.3c61b2p+33)) (f32.const 0x1.927ap+16))
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.56bd4ep+51)) (f32.const 0x1.a2e80cp+25))
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.65f02cp+44)) (f32.const 0x1.2eb544p+22))
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.26580cp+30)) (f32.const 0x1.1280d6p+15))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.3c61b112p+33)) (f64.const 0x1.927ap+16))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.56bd4e65c8548p+51)) (f64.const 0x1.a2e80dp+25))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.65f02cc93a1p+44)) (f64.const 0x1.2eb544p+22))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.26580b4cp+30)) (f64.const 0x1.1280d62b818cfp+15))
+
+;; Test some values that in some systems differ between CPU and GPU.
+;; https://github.com/pytorch/pytorch/issues/31250
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.0817fcp-1)) (f32.const 0x1.6fb79ep-1))
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.017b98p-1)) (f32.const 0x1.6b15eep-1))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.0817fcp-1)) (f64.const 0x1.6fb79d0dfaffap-1))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.017b98p-1)) (f64.const 0x1.6b15ed0071b95p-1))
+
+;; Test that sqrt is not a "good enough" approximation.
+;; https://sicp.sourceacademy.org/chapters/1.1.7.html
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.2p+3)) (f32.const 0x1.8p+1))
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.12p+7)) (f32.const 0x1.768ce6p+3))
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.c615dep+0)) (f32.const 0x1.54f2dp+0))
+(assert_return (invoke "f32.sqrt" (f32.const 0x1.f4p+9)) (f32.const 0x1.f9f6e4p+4))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.2p+3)) (f64.const 0x1.8p+1))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.12p+7)) (f64.const 0x1.768ce6d3c11ep+3))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.c615df07a57d3p+0)) (f64.const 0x1.54f2d015acf09p+0))
+(assert_return (invoke "f64.sqrt" (f64.const 0x1.f4p+9)) (f64.const 0x1.f9f6e4990f227p+4))
+
 ;; Test that the bitwise floating point operators are bitwise on NaN.
 
 (assert_return (invoke "f32.abs" (f32.const nan:0x0f1e2)) (f32.const nan:0x0f1e2))