| ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. | |
| ;; RUN: wasm-opt %s --optimize-instructions -S -o - | filecheck %s | |
| (module | |
| ;; CHECK: (func $duplicate-elimination (param $x i32) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i32.extend8_s | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i32.extend16_s | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $duplicate-elimination (param $x i32) | |
| (drop (i32.extend8_s (i32.extend8_s (local.get $x)))) | |
| (drop (i32.extend16_s (i32.extend16_s (local.get $x)))) | |
| ) | |
| ;; i64(x) << 56 >> 56 ==> i64.extend8_s(x) | |
| ;; i64(x) << 48 >> 48 ==> i64.extend16_s(x) | |
| ;; i64(x) << 32 >> 32 ==> i64.extend32_s(x) | |
| ;; i64.extend_i32_s(i32.wrap_i64(x)) ==> i64.extend32_s(x) | |
| ;; CHECK: (func $i64-sign-extentions (param $x i64) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i64.extend8_s | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i64.extend16_s | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i64.extend32_s | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i64.shr_s | |
| ;; CHECK-NEXT: (i64.shl | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (i64.const 16) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (i64.const 16) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i64.extend32_s | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $i64-sign-extentions (param $x i64) | |
| (drop (i64.shr_s (i64.shl (local.get $x) (i64.const 56)) (i64.const 56))) | |
| (drop (i64.shr_s (i64.shl (local.get $x) (i64.const 48)) (i64.const 48))) | |
| (drop (i64.shr_s (i64.shl (local.get $x) (i64.const 32)) (i64.const 32))) | |
| (drop (i64.shr_s (i64.shl (local.get $x) (i64.const 16)) (i64.const 16))) ;; skip | |
| (drop (i64.extend_i32_s (i32.wrap_i64 (local.get $x)))) | |
| ) | |
| ;; i32(x) << 24 >> 24 ==> i32.extend8_s(x) | |
| ;; i32(x) << 16 >> 16 ==> i32.extend16_s(x) | |
| ;; CHECK: (func $i32-sign-extentions (param $x i32) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i32.extend8_s | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i32.extend16_s | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i32.shr_s | |
| ;; CHECK-NEXT: (i32.shl | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (i32.const 8) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (i32.const 8) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i32.and | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (i32.const 255) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i32.and | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (i32.const 65535) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i32.shr_s | |
| ;; CHECK-NEXT: (i32.shl | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (i32.const 16) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (i32.const 24) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (i32.shr_s | |
| ;; CHECK-NEXT: (i32.shl | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: (i32.const 24) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (i32.const 16) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $i32-sign-extentions (param $x i32) | |
| (drop (i32.shr_s (i32.shl (local.get $x) (i32.const 24)) (i32.const 24))) | |
| (drop (i32.shr_s (i32.shl (local.get $x) (i32.const 16)) (i32.const 16))) | |
| (drop (i32.shr_s (i32.shl (local.get $x) (i32.const 8)) (i32.const 8))) ;; skip | |
| (drop (i32.shr_u (i32.shl (local.get $x) (i32.const 24)) (i32.const 24))) ;; skip | |
| (drop (i32.shr_u (i32.shl (local.get $x) (i32.const 16)) (i32.const 16))) ;; skip | |
| (drop (i32.shr_s (i32.shl (local.get $x) (i32.const 16)) (i32.const 24))) ;; skip | |
| (drop (i32.shr_s (i32.shl (local.get $x) (i32.const 24)) (i32.const 16))) ;; skip | |
| ) | |
| ;; CHECK: (func $no-reorder-may-not-return (param $x i32) (param $y i32) (result i32) | |
| ;; CHECK-NEXT: (i32.add | |
| ;; CHECK-NEXT: (i32.sub | |
| ;; CHECK-NEXT: (i32.const 0) | |
| ;; CHECK-NEXT: (loop $loop (result i32) | |
| ;; CHECK-NEXT: (br_if $loop | |
| ;; CHECK-NEXT: (local.get $x) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (i32.div_s | |
| ;; CHECK-NEXT: (i32.const 3) | |
| ;; CHECK-NEXT: (local.get $y) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $no-reorder-may-not-return (param $x i32) (param $y i32) (result i32) | |
| ;; OptimizeInstructions normally rewrites (0 - X) + Y => Y - X when X and Y | |
| ;; can be reordered. That rewrite cannot happen here because X is a loop | |
| ;; that may not return and Y may trap. | |
| (i32.add | |
| (i32.sub | |
| (i32.const 0) | |
| (loop $loop (result i32) | |
| (br_if $loop | |
| (local.get $x) | |
| ) | |
| (i32.const 1) | |
| ) | |
| ) | |
| (i32.div_s | |
| (i32.const 3) | |
| (local.get $y) | |
| ) | |
| ) | |
| ) | |
| ) |