Просмотр исходного кода

Fix AOT shift operations for indirect constants (#2627)

When doing more investigations related to this PR:
  https://github.com/bytecodealliance/wasm-micro-runtime/pull/2619
We found that in some scenarios the constant might not be directly
available to the LLVM IR builder, e.g.:
```
  (func $const_ret (result i32)
    i32.const -5
  )
  (func $foo
    (i32.shr_u (i32.const -1) (call $const_ret))
    (i32.const 31)
  )
```
In that case, the right parameter to `i32.shr_u` is not constant, therefore
the `SHIFT_COUNT_MASK` isn't applied. However, when the optimization
is enabled (`--opt-level` is 2 or 3), the optimization passes resolve the
call into constant, and that constant is poisoned, causing the compiler to
resolve the whole function to an exception.
Marcin Kolny 2 лет назад
Родитель
Сommit
72b34eaf30

+ 3 - 15
core/iwasm/compilation/aot_emit_numberic.c

@@ -171,15 +171,6 @@
         right = shift_count_mask;                                      \
     } while (0)
 
-static bool
-is_shift_count_mask_needed(AOTCompContext *comp_ctx, LLVMValueRef left,
-                           LLVMValueRef right)
-{
-    return (strcmp(comp_ctx->target_arch, "x86_64") != 0
-            && strcmp(comp_ctx->target_arch, "i386") != 0)
-           || (LLVMIsEfficientConstInt(left) && LLVMIsEfficientConstInt(right));
-}
-
 /* Call llvm constrained floating-point intrinsic */
 static LLVMValueRef
 call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
@@ -737,8 +728,7 @@ compile_int_shl(AOTCompContext *comp_ctx, LLVMValueRef left, LLVMValueRef right,
 {
     LLVMValueRef res;
 
-    if (is_shift_count_mask_needed(comp_ctx, left, right))
-        SHIFT_COUNT_MASK;
+    SHIFT_COUNT_MASK;
 
     /* Build shl */
     LLVM_BUILD_OP(Shl, left, right, res, "shl", NULL);
@@ -752,8 +742,7 @@ compile_int_shr_s(AOTCompContext *comp_ctx, LLVMValueRef left,
 {
     LLVMValueRef res;
 
-    if (is_shift_count_mask_needed(comp_ctx, left, right))
-        SHIFT_COUNT_MASK;
+    SHIFT_COUNT_MASK;
 
     /* Build shl */
     LLVM_BUILD_OP(AShr, left, right, res, "shr_s", NULL);
@@ -767,8 +756,7 @@ compile_int_shr_u(AOTCompContext *comp_ctx, LLVMValueRef left,
 {
     LLVMValueRef res;
 
-    if (is_shift_count_mask_needed(comp_ctx, left, right))
-        SHIFT_COUNT_MASK;
+    SHIFT_COUNT_MASK;
 
     /* Build shl */
     LLVM_BUILD_OP(LShr, left, right, res, "shr_u", NULL);

+ 36 - 1
tests/wamr-compiler/test_shift_negative_constants.wat

@@ -7,6 +7,7 @@
 ;; any problems. See: https://github.com/bytecodealliance/wasm-micro-runtime/pull/2619
 (module
   (memory (export "memory") 1 1)
+
   (func $assert_eq (param i32 i32)
     (i32.ne (local.get 0) (local.get 1))
     if
@@ -23,7 +24,7 @@
 
   (func $i32_shr_s
     (call $assert_eq
-      (i32.shr_u (i32.const 32) (i32.const -30))
+      (i32.shr_s (i32.const 32) (i32.const -30))
       (i32.const 8)
     )
   )
@@ -35,9 +36,43 @@
     )
   )
 
+  (func $const_ret (result i32)
+    i32.const -5
+  )
+
+  ;; *_func_call tests validate the potential LLVM optimizations
+  ;; where the right parameter of the shift operation is an
+  ;; indirect constant value.
+  (func $i32_shr_u_func_call
+    (call $assert_eq
+      (i32.shr_u (i32.const -1) (call $const_ret))
+      (i32.const 31)
+    )
+  )
+
+  (func $i32_shr_s_func_call
+    (call $assert_eq
+      (i32.shr_s
+        (i32.const 1073741824) ;; 2^30
+        (call $const_ret)
+      )
+      (i32.const 8)
+    )
+  )
+
+  (func $i32_shl_func_call
+    (call $assert_eq
+      (i32.shl (i32.const -1) (call $const_ret))
+      (i32.const -134217728)
+    )
+  )
+
   (func (export "_start")
     call $i32_shr_u
     call $i32_shr_s
     call $i32_shl
+    call $i32_shr_u_func_call
+    call $i32_shr_s_func_call
+    call $i32_shl_func_call
   )
 )