Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

O2 regression in optimize-instructions due to coalesceLocals

Đang mở
#7,458 2 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
45/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Đình trệ
Công nghệ
wasm
Lĩnh vực
compilers

Hướng nghiên cứu

Tái hiện ví dụ WebAssembly với wasm-opt -all -O1 và -all -O2, sau đó so sánh đầu ra sau precompute, coalesce-locals và optimize-instructions. Theo dõi cách local.tee 0 so với local.tee 1 ảnh hưởng đến việc suy luận điều kiện. Được xem là hoàn tất khi optimize-instructions nhận ra điều kiện là zero ở O2 và loại bỏ phần thân br_if không thể thực thi mà không thay đổi hành vi.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Given the following code:

(module
  (import "External" "external_function" (func $external_function))
  (func $_start
    (local $0 i32) (local $3 i32) (local $5 i32) (local $6 i32) (local $11 i32) (local $1 i32) (local $2 i32) (local $7 i32)
    loop ;; label = @1
      block ;; label = @2
        i32.const 0
        i32.load
        br_if 0 (;@2;)
        i32.const 0
        local.get $11
        i32.store
        i32.const 0
        local.set $5
        i32.const 1
        local.set $0
        i32.const 0
        local.get $0
        i32.store
        i32.const -346457217
        local.set $6
        block ;; label = @3
          local.get $0
          local.get $6
          i32.ne
          br_if 0 (;@3;)
          call $external_function
        end
        local.get $5
        i32.const 0
        i32.load
        i32.lt_s
        i32.const 0
        local.set $1
        local.get $1
        i32.shl
        drop
        local.get $1
        unreachable
      end
      i32.const 0
      i32.load
      local.set $2
      local.get $2
      local.set $3
      local.get $2
      local.get $3
      i32.store
      br 0 (;@1;)
    end)
  (memory $0 1)
  (export "_start" (func $_start)))

wasm-opt (16dbac1) can eliminate the dead br_if body by -all -O1 but cannot by -all -O2.

Analysis

The direct issue is that optimize-instructions cannot deduce the condition to zero in -all -O2 while it can in -all -O1. (further the dead if statement body will be eliminated by --vacuum)

Before optimize-instructions, that is precompute:

`-all -O1`, after `precompute`, going to `optimize-instructions`
(module
  (type (;0;) (func))
  (import "External" "external_functional" (func (;0;) (type 0)))
  (func (;1;) (type 0)
    (local i32 i32)
    loop  ;; label = @1
      i32.const 0
      i32.load
      i32.eqz
      if  ;; label = @2
        i32.const 0
        local.get 1
        i32.store
        i32.const 0
        i32.const 1
        local.tee 0
        i32.store
        local.get 0
        i32.const -346457217
        i32.eq
        if  ;; label = @3
          call 0
        end
        i32.const 0
        i32.load
        drop
        unreachable
      else
        i32.const 0
        i32.load
        local.tee 1 ;; Note this line: using variable 1, not affects condition
        local.get 1
        i32.store
        br 1 (;@1;)
      end
      unreachable
    end
    unreachable)
  (memory (;0;) 1)
  (export "_start" (func 1)))
`-all -O2`, after `precompute`, going to `optimize-instructions`
(module
  (type (;0;) (func))
  (import "External" "external_function" (func (;0;) (type 0)))
  (func (;1;) (type 0)
    (local i32 i32)
    loop  ;; label = @1
      i32.const 0
      i32.load
      i32.eqz
      if  ;; label = @2
        i32.const 0
        local.get 1
        i32.store
        i32.const 0
        i32.const 1
        local.tee 0
        i32.store
        local.get 0
        i32.const -346457217
        i32.eq
        if  ;; label = @3
          call 0
        end
        i32.const 0
        i32.load
        unreachable
      else
        i32.const 0
        i32.load
        local.tee 0 ;; Note this line: using variable 0 will affect condition deduction
        local.get 0
        i32.store
        br 1 (;@1;)
      end
      unreachable
    end
    unreachable)
  (memory (;0;) 1)
  (export "_start" (func 1)))

As you can see, the condition are the same:

(if
 (i32.eq
  (local.get $0) 
  (i32.const -346457217)
 )
 (then
  (call $external_functional)
 )
)

However, the statements in else statements are slightly different, but critical: -all -O1 uses local variable 1, while -all -O2 uses local variable 0 (local.tee 0), which I thinks maybe affect the deduction of the condition in optimize-instructions .

Continue to trace back and analyze in the optimized pipeline, the slightly but critical difference begins in coalesce-locals, which is the optimizations of Key "register allocation" pass. Does a live range analysis and then reuses locals in order to minimize their number, as well as to remove copies between them.

Although the coalesce-locals performs aggressive optimizations, I think there is missed optimization in the optimize-instructions, for it should have deduced the condition to be 0.

Ngôn ngữ chính
WebAssembly
Star
8.6k
Fork
885
Merge trung bình
2 ngày 4 giờ
Pull request đã merge (30 ngày)
77

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của WebAssembly/binaryen

Tất cả issue của WebAssembly/binaryen

Issue tương tự

Thêm issue về Compilers

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.