| ; 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 |
| } |