1; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 -verify-machineinstrs | FileCheck %s 2 3target triple = "wasm32-unknown-unknown" 4 5; FastISel should not fold one of the add/sub operands into a load/store's 6; offset when 'nuw' (no unsigned wrap) is not present, because the address 7; calculation does not wrap. When there is an add/sub and nuw is not present, we 8; bail out of FastISel. 9 10@mylabel = external global ptr 11 12; CHECK-LABEL: dont_fold_non_nuw_add_load: 13; CHECK: local.get 0 14; CHECK-NEXT: i32.const 2147483644 15; CHECK-NEXT: i32.add 16; CHECK-NEXT: i32.load 0 17define i32 @dont_fold_non_nuw_add_load(ptr %p) { 18 %q = ptrtoint ptr %p to i32 19 %r = add i32 %q, 2147483644 20 %s = inttoptr i32 %r to ptr 21 %t = load i32, ptr %s 22 ret i32 %t 23} 24 25; CHECK-LABEL: dont_fold_non_nuw_add_store: 26; CHECK: local.get 0 27; CHECK-NEXT: i32.const 2147483644 28; CHECK-NEXT: i32.add 29; CHECK-NEXT: i32.const 5 30; CHECK-NEXT: i32.store 0 31define void @dont_fold_non_nuw_add_store(ptr %p) { 32 %q = ptrtoint ptr %p to i32 33 %r = add i32 %q, 2147483644 34 %s = inttoptr i32 %r to ptr 35 store i32 5, ptr %s 36 ret void 37} 38 39; CHECK-LABEL: dont_fold_non_nuw_add_load_2: 40; CHECK: i32.const mylabel 41; CHECK-NEXT: i32.const -4 42; CHECK-NEXT: i32.add 43; CHECK-NEXT: i32.load 0 44define i32 @dont_fold_non_nuw_add_load_2() { 45 %t = load i32, ptr inttoptr (i32 add (i32 ptrtoint (ptr @mylabel to i32), i32 -4) to ptr), align 4 46 ret i32 %t 47} 48 49; CHECK-LABEL: dont_fold_non_nuw_add_store_2: 50; CHECK: i32.const mylabel 51; CHECK-NEXT: i32.const -4 52; CHECK-NEXT: i32.add 53; CHECK-NEXT: i32.const 5 54; CHECK-NEXT: i32.store 0 55define void @dont_fold_non_nuw_add_store_2() { 56 store i32 5, ptr inttoptr (i32 add (i32 ptrtoint (ptr @mylabel to i32), i32 -4) to ptr), align 4 57 ret void 58} 59 60; CHECK-LABEL: dont_fold_non_nuw_sub_load: 61; CHECK: local.get 0 62; CHECK-NEXT: i32.const -2147483644 63; CHECK-NEXT: i32.sub 64; CHECK-NEXT: i32.load 0 65define i32 @dont_fold_non_nuw_sub_load(ptr %p) { 66 %q = ptrtoint ptr %p to i32 67 %r = sub i32 %q, -2147483644 68 %s = inttoptr i32 %r to ptr 69 %t = load i32, ptr %s 70 ret i32 %t 71} 72 73; CHECK-LABEL: dont_fold_non_nuw_sub_store: 74; CHECK: local.get 0 75; CHECK-NEXT: i32.const -2147483644 76; CHECK-NEXT: i32.sub 77; CHECK-NEXT: i32.const 5 78; CHECK-NEXT: i32.store 0 79define void @dont_fold_non_nuw_sub_store(ptr %p) { 80 %q = ptrtoint ptr %p to i32 81 %r = sub i32 %q, -2147483644 82 %s = inttoptr i32 %r to ptr 83 store i32 5, ptr %s 84 ret void 85} 86 87; CHECK-LABEL: dont_fold_non_nuw_sub_load_2: 88; CHECK: i32.const mylabel 89; CHECK-NEXT: i32.const 4 90; CHECK-NEXT: i32.sub 91; CHECK-NEXT: i32.load 0 92define i32 @dont_fold_non_nuw_sub_load_2() { 93 %t = load i32, ptr inttoptr (i32 sub (i32 ptrtoint (ptr @mylabel to i32), i32 4) to ptr), align 4 94 ret i32 %t 95} 96 97; CHECK-LABEL: dont_fold_non_nuw_sub_store_2: 98; CHECK: i32.const mylabel 99; CHECK-NEXT: i32.const 4 100; CHECK-NEXT: i32.sub 101; CHECK-NEXT: i32.const 5 102; CHECK-NEXT: i32.store 0 103define void @dont_fold_non_nuw_sub_store_2() { 104 store i32 5, ptr inttoptr (i32 sub (i32 ptrtoint (ptr @mylabel to i32), i32 4) to ptr), align 4 105 ret void 106} 107