; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 -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. @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.sub ; 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.sub ; 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.sub ; 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.sub ; 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 }