[llvm] [WebAssembly] Don't fold non-nuw add/sub in FastISel (PR #111278)

Heejin Ahn via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 5 22:29:57 PDT 2024


================
@@ -0,0 +1,106 @@
+; RUN: llc < %s -asm-verbose=false -fast-isel -verify-machineinstrs | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+; FastISel should not fold one of the add/sub operands into a load/store's
+; offset when 'nuw' (no unsigned wrap) is not present, because the address
+; calculation does not wrap. When there is an add/sub and nuw is not present, we
+; bail out of FastISel.
+
+ at mylabel = external global ptr
+
+; CHECK-LABEL: dont_fold_non_nuw_add_load:
+; CHECK:       local.get  0
+; CHECK-NEXT:  i32.const  2147483644
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  i32.load  0
+define i32 @dont_fold_non_nuw_add_load(ptr %p) {
+  %q = ptrtoint ptr %p to i32
+  %r = add i32 %q, 2147483644
+  %s = inttoptr i32 %r to ptr
+  %t = load i32, ptr %s
+  ret i32 %t
+}
+
+; CHECK-LABEL: dont_fold_non_nuw_add_store:
+; CHECK:       local.get  0
+; CHECK-NEXT:  i32.const  2147483644
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  i32.const  5
+; CHECK-NEXT:  i32.store  0
+define void @dont_fold_non_nuw_add_store(ptr %p) {
+  %q = ptrtoint ptr %p to i32
+  %r = add i32 %q, 2147483644
+  %s = inttoptr i32 %r to ptr
+  store i32 5, ptr %s
+  ret void
+}
+
+; CHECK-LABEL: dont_fold_non_nuw_add_load_2:
+; CHECK:       i32.const  mylabel
+; CHECK-NEXT:  i32.const  -4
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  i32.load  0
+define i32 @dont_fold_non_nuw_add_load_2() {
+  %t = load i32, ptr inttoptr (i32 add (i32 ptrtoint (ptr @mylabel to i32), i32 -4) to ptr), align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: dont_fold_non_nuw_add_store_2:
+; CHECK:       i32.const  mylabel
+; CHECK-NEXT:  i32.const  -4
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  i32.const  5
+; CHECK-NEXT:  i32.store  0
+define void @dont_fold_non_nuw_add_store_2() {
+  store i32 5, ptr inttoptr (i32 add (i32 ptrtoint (ptr @mylabel to i32), i32 -4) to ptr), align 4
+  ret void
+}
+
+; CHECK-LABEL: dont_fold_non_nuw_sub_load:
+; CHECK:       local.get  0
+; CHECK-NEXT:  i32.const  2147483644
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  i32.load  0
+define i32 @dont_fold_non_nuw_sub_load(ptr %p) {
+  %q = ptrtoint ptr %p to i32
+  %r = sub i32 %q, -2147483644
+  %s = inttoptr i32 %r to ptr
+  %t = load i32, ptr %s
+  ret i32 %t
+}
+
+; CHECK-LABEL: dont_fold_non_nuw_sub_store:
+; CHECK:       local.get  0
+; CHECK-NEXT:  i32.const  2147483644
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  i32.const  5
+; CHECK-NEXT:  i32.store  0
+define void @dont_fold_non_nuw_sub_store(ptr %p) {
+  %q = ptrtoint ptr %p to i32
+  %r = sub i32 %q, -2147483644
+  %s = inttoptr i32 %r to ptr
+  store i32 5, ptr %s
+  ret void
+}
+
+; CHECK-LABEL: dont_fold_non_nuw_sub_load_2:
+; CHECK:       i32.const  mylabel
+; CHECK-NEXT:  i32.const  -4
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  i32.load  0
+define i32 @dont_fold_non_nuw_sub_load_2() {
+  %t = load i32, ptr inttoptr (i32 sub (i32 ptrtoint (ptr @mylabel to i32), i32 4) to ptr), align 4
+ ret i32 %t
+}
+
+; CHECK-LABEL: dont_fold_non_nuw_sub_store_2:
+; CHECK:       i32.const  mylabel
+; CHECK-NEXT:  i32.const  -4
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  i32.const  5
+; CHECK-NEXT:  i32.store  0
+define void @dont_fold_non_nuw_sub_store_2() {
+  store i32 5, ptr inttoptr (i32 sub (i32 ptrtoint (ptr @mylabel to i32), i32 4) to ptr), align 4
+  ret void
+}
----------------
aheejin wrote:

Actually these two are correctly compiled even in the current compiler, because in `ISD::ADD`, even if RHS is negative, we try to compute each of LHS and RHS separately to see if they can be combined:
https://github.com/llvm/llvm-project/blob/6de5305b3d7a4a19a29b35d481a8090e2a6d3a7e/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp#L355-L358

But `ISD::SUB` handling doesn't have this part. (Because offset calculation is addition)

But I added these tests for symmetry and ensure if these invariants are well maintained in future.


https://github.com/llvm/llvm-project/pull/111278


More information about the llvm-commits mailing list