Do note code fold ifs with concrete arms

Code folding does not support folding tails that produce concrete
values, but it previously did not check for this condition when deciding
whether to attempt to code fold ifs. As a result, code folding would
proceed on ifs with concretely typed arms. The incorrect block types
produced by the folding logic as a result of the violated assumption
that the folded tails would never produce concrete values were papered
over by later refinalization, so this never caused problems.

However, an upcoming change (#7094) that relaxes the typing of ifs to
allow them to be unreachable whenever their conditions are unreachable
makes it possible for the violated assumptions in code folding to cause
problems that are not fixed by refinalization. Fix code folding to
disallow folding of concretely typed if arms and add a test that would
fail once #7094 lands without this fix.
diff --git a/src/passes/CodeFolding.cpp b/src/passes/CodeFolding.cpp
index 21527da..47e7916 100644
--- a/src/passes/CodeFolding.cpp
+++ b/src/passes/CodeFolding.cpp
@@ -243,6 +243,10 @@
     if (!curr->ifFalse) {
       return;
     }
+    if (curr->ifTrue->type.isConcrete()) {
+      // We don't support folding tails that produce values.
+      return;
+    }
     // if both sides are identical, this is easy to fold
     if (ExpressionAnalyzer::equal(curr->ifTrue, curr->ifFalse)) {
       Builder builder(*getModule());
diff --git a/test/lit/passes/code-folding_enable-threads.wast b/test/lit/passes/code-folding_enable-threads.wast
index b070002..3df2d8c 100644
--- a/test/lit/passes/code-folding_enable-threads.wast
+++ b/test/lit/passes/code-folding_enable-threads.wast
@@ -83,11 +83,18 @@
   )
  )
  ;; CHECK:      (func $negative-zero-b (result f32)
- ;; CHECK-NEXT:  (drop
+ ;; CHECK-NEXT:  (if (result f32)
  ;; CHECK-NEXT:   (i32.const 0)
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT:  (block $label$0 (result f32)
- ;; CHECK-NEXT:   (f32.const -0)
+ ;; CHECK-NEXT:   (then
+ ;; CHECK-NEXT:    (block $label$0 (result f32)
+ ;; CHECK-NEXT:     (f32.const -0)
+ ;; CHECK-NEXT:    )
+ ;; CHECK-NEXT:   )
+ ;; CHECK-NEXT:   (else
+ ;; CHECK-NEXT:    (block $label$1 (result f32)
+ ;; CHECK-NEXT:     (f32.const -0)
+ ;; CHECK-NEXT:    )
+ ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $negative-zero-b (result f32)
@@ -106,11 +113,18 @@
   )
  )
  ;; CHECK:      (func $negative-zero-c (result f32)
- ;; CHECK-NEXT:  (drop
+ ;; CHECK-NEXT:  (if (result f32)
  ;; CHECK-NEXT:   (i32.const 0)
- ;; CHECK-NEXT:  )
- ;; CHECK-NEXT:  (block $label$0 (result f32)
- ;; CHECK-NEXT:   (f32.const 0)
+ ;; CHECK-NEXT:   (then
+ ;; CHECK-NEXT:    (block $label$0 (result f32)
+ ;; CHECK-NEXT:     (f32.const 0)
+ ;; CHECK-NEXT:    )
+ ;; CHECK-NEXT:   )
+ ;; CHECK-NEXT:   (else
+ ;; CHECK-NEXT:    (block $label$1 (result f32)
+ ;; CHECK-NEXT:     (f32.const 0)
+ ;; CHECK-NEXT:    )
+ ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $negative-zero-c (result f32)
@@ -482,3 +496,36 @@
   )
  )
 )
+
+(module
+ ;; CHECK:      (type $0 (func))
+
+ ;; CHECK:      (func $unreachable-if-concrete-arms
+ ;; CHECK-NEXT:  (drop
+ ;; CHECK-NEXT:   (if (result i32)
+ ;; CHECK-NEXT:    (unreachable)
+ ;; CHECK-NEXT:    (then
+ ;; CHECK-NEXT:     (i32.const 1)
+ ;; CHECK-NEXT:    )
+ ;; CHECK-NEXT:    (else
+ ;; CHECK-NEXT:     (nop)
+ ;; CHECK-NEXT:     (i32.const 1)
+ ;; CHECK-NEXT:    )
+ ;; CHECK-NEXT:   )
+ ;; CHECK-NEXT:  )
+ ;; CHECK-NEXT:  (unreachable)
+ ;; CHECK-NEXT: )
+ (func $unreachable-if-concrete-arms
+  (if (result i32)
+   (unreachable)
+   (then
+    (i32.const 1)
+   )
+   (else
+    (nop)
+    (i32.const 1)
+   )
+  )
+  (unreachable)
+ )
+)
diff --git a/test/lit/passes/inlining-optimizing_optimize-level=3.wast b/test/lit/passes/inlining-optimizing_optimize-level=3.wast
index f6df730..9e514cc 100644
--- a/test/lit/passes/inlining-optimizing_optimize-level=3.wast
+++ b/test/lit/passes/inlining-optimizing_optimize-level=3.wast
@@ -5742,42 +5742,43 @@
  ;; CHECK-NEXT:                                   )
  ;; CHECK-NEXT:                                  )
  ;; CHECK-NEXT:                                 )
- ;; CHECK-NEXT:                                 (if
- ;; CHECK-NEXT:                                  (i32.and
- ;; CHECK-NEXT:                                   (local.get $9)
- ;; CHECK-NEXT:                                   (i32.const 8)
- ;; CHECK-NEXT:                                  )
- ;; CHECK-NEXT:                                  (then
- ;; CHECK-NEXT:                                   (local.set $7
+ ;; CHECK-NEXT:                                 (local.set $5
+ ;; CHECK-NEXT:                                  (if (result i32)
+ ;; CHECK-NEXT:                                   (i32.and
  ;; CHECK-NEXT:                                    (local.get $9)
+ ;; CHECK-NEXT:                                    (i32.const 8)
  ;; CHECK-NEXT:                                   )
- ;; CHECK-NEXT:                                   (local.set $6
- ;; CHECK-NEXT:                                    (select
- ;; CHECK-NEXT:                                     (local.tee $5
- ;; CHECK-NEXT:                                      (i32.add
- ;; CHECK-NEXT:                                       (i32.sub
- ;; CHECK-NEXT:                                        (local.get $23)
- ;; CHECK-NEXT:                                        (local.get $8)
+ ;; CHECK-NEXT:                                   (then
+ ;; CHECK-NEXT:                                    (local.set $7
+ ;; CHECK-NEXT:                                     (local.get $9)
+ ;; CHECK-NEXT:                                    )
+ ;; CHECK-NEXT:                                    (local.set $6
+ ;; CHECK-NEXT:                                     (select
+ ;; CHECK-NEXT:                                      (local.tee $5
+ ;; CHECK-NEXT:                                       (i32.add
+ ;; CHECK-NEXT:                                        (i32.sub
+ ;; CHECK-NEXT:                                         (local.get $23)
+ ;; CHECK-NEXT:                                         (local.get $8)
+ ;; CHECK-NEXT:                                        )
+ ;; CHECK-NEXT:                                        (i32.const 1)
  ;; CHECK-NEXT:                                       )
- ;; CHECK-NEXT:                                       (i32.const 1)
+ ;; CHECK-NEXT:                                      )
+ ;; CHECK-NEXT:                                      (local.get $6)
+ ;; CHECK-NEXT:                                      (i32.gt_s
+ ;; CHECK-NEXT:                                       (local.get $5)
+ ;; CHECK-NEXT:                                       (local.get $6)
  ;; CHECK-NEXT:                                      )
  ;; CHECK-NEXT:                                     )
- ;; CHECK-NEXT:                                     (local.get $6)
- ;; CHECK-NEXT:                                     (i32.gt_s
- ;; CHECK-NEXT:                                      (local.get $5)
- ;; CHECK-NEXT:                                      (local.get $6)
- ;; CHECK-NEXT:                                     )
  ;; CHECK-NEXT:                                    )
+ ;; CHECK-NEXT:                                    (local.get $8)
+ ;; CHECK-NEXT:                                   )
+ ;; CHECK-NEXT:                                   (else
+ ;; CHECK-NEXT:                                    (local.set $7
+ ;; CHECK-NEXT:                                     (local.get $9)
+ ;; CHECK-NEXT:                                    )
+ ;; CHECK-NEXT:                                    (local.get $8)
  ;; CHECK-NEXT:                                   )
  ;; CHECK-NEXT:                                  )
- ;; CHECK-NEXT:                                  (else
- ;; CHECK-NEXT:                                   (local.set $7
- ;; CHECK-NEXT:                                    (local.get $9)
- ;; CHECK-NEXT:                                   )
- ;; CHECK-NEXT:                                  )
- ;; CHECK-NEXT:                                 )
- ;; CHECK-NEXT:                                 (local.set $5
- ;; CHECK-NEXT:                                  (local.get $8)
  ;; CHECK-NEXT:                                 )
  ;; CHECK-NEXT:                                 (local.set $8
  ;; CHECK-NEXT:                                  (i32.const 0)
diff --git a/test/passes/remove-unused-names_code-folding.txt b/test/passes/remove-unused-names_code-folding.txt
index d0486b3..4b228bd 100644
--- a/test/passes/remove-unused-names_code-folding.txt
+++ b/test/passes/remove-unused-names_code-folding.txt
@@ -26,13 +26,19 @@
    )
   )
   (drop
-   (block (result i32)
-    (drop
-     (i32.const 0)
+   (if (result i32)
+    (i32.const 0)
+    (then
+     (i32.add
+      (i32.const 1)
+      (i32.const 2)
+     )
     )
-    (i32.add
-     (i32.const 1)
-     (i32.const 2)
+    (else
+     (i32.add
+      (i32.const 1)
+      (i32.const 2)
+     )
     )
    )
   )
@@ -218,54 +224,61 @@
    (unreachable)
   )
   (drop
-   (block (result i32)
-    (if
-     (i32.const 2)
-     (then
-      (drop
-       (i32.const -1234)
-      )
-      (drop
-       (i32.const -1000)
-      )
-     )
-     (else
-      (drop
-       (i32.const 999)
-      )
-     )
-    )
-    (drop
-     (i32.const 1)
-    )
-    (nop)
-    (unreachable)
+   (if (result i32)
     (i32.const 2)
+    (then
+     (drop
+      (i32.const -1234)
+     )
+     (drop
+      (i32.const -1000)
+     )
+     (drop
+      (i32.const 1)
+     )
+     (nop)
+     (unreachable)
+     (i32.const 2)
+    )
+    (else
+     (drop
+      (i32.const 999)
+     )
+     (drop
+      (i32.const 1)
+     )
+     (nop)
+     (unreachable)
+     (i32.const 2)
+    )
    )
   )
   (drop
-   (block (result i32)
-    (if
-     (i32.const 3)
-     (then
-      (drop
-       (i32.const -1234)
-      )
-      (drop
-       (i32.const -1000)
-      )
+   (if (result i32)
+    (i32.const 3)
+    (then
+     (drop
+      (i32.const -1234)
      )
-     (else
-      (drop
-       (i32.const 999)
-      )
+     (drop
+      (i32.const -1000)
      )
+     (drop
+      (i32.const 1)
+     )
+     (nop)
+     (i32.const 2)
     )
-    (drop
-     (i32.const 1)
+    (else
+     (drop
+      (i32.const 999)
+     )
+     (drop
+      (i32.const 1)
+     )
+     (nop)
+     (i32.const 2)
     )
-    (nop)
-    (i32.const 2)
    )
   )
  )
@@ -388,28 +401,28 @@
     )
     (drop
      (block (result i32)
-      (block (result i32)
-       (if
-        (i32.const 9999)
-        (then
-         (drop
-          (i32.const -51234)
-         )
-         (drop
-          (i32.const -51000)
-         )
+      (if (result i32)
+       (i32.const 9999)
+       (then
+        (drop
+         (i32.const -51234)
         )
-        (else
-         (drop
-          (i32.const 5999)
-         )
-         (drop
-          (i32.const 51)
-         )
+        (drop
+         (i32.const -51000)
         )
+        (unreachable)
+        (i32.const 10)
        )
-       (unreachable)
-       (i32.const 10)
+       (else
+        (drop
+         (i32.const 5999)
+        )
+        (drop
+         (i32.const 51)
+        )
+        (unreachable)
+        (i32.const 10)
+       )
       )
      )
     )
@@ -1523,11 +1536,15 @@
   )
   (nop)
   (drop
-   (block (result i32)
-    (drop
-     (unreachable)
+   (if (result i32)
+    (unreachable)
+    (then
+     (i32.add
+      (i32.const 1)
+      (i32.const 2)
+     )
     )
-    (block (result i32)
+    (else
      (i32.add
       (i32.const 1)
       (i32.const 2)
@@ -1874,20 +1891,19 @@
     (i32.const 1)
    )
   )
-  (block (result i32)
-   (if
-    (local.get $x)
-    (then
-    )
-    (else
-     (drop
-      (call $if-suffix
-       (i32.const -2)
-      )
+  (if (result i32)
+   (local.get $x)
+   (then
+    (i32.const 2)
+   )
+   (else
+    (drop
+     (call $if-suffix
+      (i32.const -2)
      )
     )
+    (i32.const 2)
    )
-   (i32.const 2)
   )
  )
 )