1; RUN: llc -mtriple=thumbv8m.main %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V8M 2; RUN: llc -mtriple=armv8 %s -o - | FileCheck %s --check-prefix=CHECK-V8 3 4; CHECK-LABEL: pre_inc_ldr 5; CHECK: ldr{{.*}}, [r0, #4]! 6define i32* @pre_inc_ldr(i32* %base, i32 %a) { 7 %addr = getelementptr i32, i32* %base, i32 1 8 %ld = load i32, i32* %addr 9 %addr.1 = getelementptr i32, i32* %base, i32 2 10 %res = add i32 %ld, %a 11 store i32 %res, i32* %addr.1 12 ret i32* %addr 13} 14 15; CHECK-LABEL: pre_dec_ldr 16; CHECK: ldr{{.*}}, [r0, #-4]! 17define i32* @pre_dec_ldr(i32* %base, i32 %a) { 18 %addr = getelementptr i32, i32* %base, i32 -1 19 %ld = load i32, i32* %addr 20 %addr.1 = getelementptr i32, i32* %base, i32 2 21 %res = add i32 %ld, %a 22 store i32 %res, i32* %addr.1 23 ret i32* %addr 24} 25 26; CHECK-LABEL: post_inc_ldr 27; CHECK: ldr{{.*}}, [r0], #4 28define i32* @post_inc_ldr(i32* %base, i32* %addr.2, i32 %a) { 29 %addr = getelementptr i32, i32* %base, i32 0 30 %ld = load i32, i32* %addr 31 %addr.1 = getelementptr i32, i32* %base, i32 1 32 %res = add i32 %ld, %a 33 store i32 %res, i32* %addr.2 34 ret i32* %addr.1 35} 36 37; CHECK-LABEL: post_dec_ldr 38; CHECK: ldr{{.*}}, [r0], #-4 39define i32* @post_dec_ldr(i32* %base, i32* %addr.2, i32 %a) { 40 %addr = getelementptr i32, i32* %base, i32 0 41 %ld = load i32, i32* %addr 42 %addr.1 = getelementptr i32, i32* %base, i32 -1 43 %res = add i32 %ld, %a 44 store i32 %res, i32* %addr.2 45 ret i32* %addr.1 46} 47 48; CHECK-LABEL: pre_inc_str 49; CHECK: str{{.*}}, [r0, #4]! 50define i32* @pre_inc_str(i32* %base, i32 %a, i32 %b) { 51 %addr.1 = getelementptr i32, i32* %base, i32 1 52 %res = add i32 %a, %b 53 store i32 %res, i32* %addr.1 54 ret i32* %addr.1 55} 56 57; CHECK-LABEL: pre_dec_str 58; CHECK: str{{.*}}, [r0, #-4]! 59define i32* @pre_dec_str(i32* %base, i32 %a, i32 %b) { 60 %res = add i32 %a, %b 61 %addr.1 = getelementptr i32, i32* %base, i32 -1 62 store i32 %res, i32* %addr.1 63 ret i32* %addr.1 64} 65 66; CHECK-LABEL: post_inc_str 67; CHECK: str{{.*}}, [r0], #4 68define i32* @post_inc_str(i32* %base, i32 %a, i32 %b) { 69 %addr.1 = getelementptr i32, i32* %base, i32 1 70 %res = add i32 %a, %b 71 store i32 %res, i32* %base 72 ret i32* %addr.1 73} 74 75; CHECK-LABEL: post_dec_str 76; CHECK: str{{.*}}, [r0], #-4 77define i32* @post_dec_str(i32* %base, i32 %a, i32 %b) { 78 %addr.1 = getelementptr i32, i32* %base, i32 -1 79 %res = add i32 %a, %b 80 store i32 %res, i32* %base 81 ret i32* %addr.1 82} 83 84; TODO: Generate ldrd 85; CHECK-LABEL: pre_inc_ldrd 86; CHECK: ldr{{.*}}, #4]! 87define i32* @pre_inc_ldrd(i32* %base) { 88 %addr = getelementptr i32, i32* %base, i32 1 89 %addr.1 = getelementptr i32, i32* %base, i32 2 90 %addr.2 = getelementptr i32, i32* %base, i32 3 91 %ld = load i32, i32* %addr 92 %ld.1 = load i32, i32* %addr.1 93 %res = add i32 %ld, %ld.1 94 store i32 %res, i32* %addr.2 95 ret i32* %addr 96} 97 98; TODO: Generate ldrd 99; CHECK-LABEL: pre_dec_ldrd 100; CHECK: ldr{{.*}}, #-4]! 101define i32* @pre_dec_ldrd(i32* %base) { 102 %addr = getelementptr i32, i32* %base, i32 -1 103 %addr.1 = getelementptr i32, i32* %base, i32 -2 104 %addr.2 = getelementptr i32, i32* %base, i32 -3 105 %ld = load i32, i32* %addr 106 %ld.1 = load i32, i32* %addr.1 107 %res = add i32 %ld, %ld.1 108 store i32 %res, i32* %addr.2 109 ret i32* %addr 110} 111 112; TODO: Generate post inc 113; CHECK-LABEL: post_inc_ldrd 114; CHECK-V8M: ldrd{{.*}}, [r0] 115; CHECK-V8: ldm 116; CHECK: add{{.*}}, #8 117define i32* @post_inc_ldrd(i32* %base, i32* %addr.3) { 118 %addr = getelementptr i32, i32* %base, i32 0 119 %ld = load i32, i32* %addr 120 %addr.1 = getelementptr i32, i32* %base, i32 1 121 %ld.1 = load i32, i32* %addr.1 122 %addr.2 = getelementptr i32, i32* %base, i32 2 123 %res = add i32 %ld, %ld.1 124 store i32 %res, i32* %addr.3 125 ret i32* %addr.2 126} 127 128; CHECK-LABEL: pre_inc_str_multi 129; CHECK: str{{.*}}, #8]! 130define i32* @pre_inc_str_multi(i32* %base) { 131 %addr = getelementptr i32, i32* %base, i32 0 132 %addr.1 = getelementptr i32, i32* %base, i32 1 133 %ld = load i32, i32* %addr 134 %ld.1 = load i32, i32* %addr.1 135 %res = add i32 %ld, %ld.1 136 %addr.2 = getelementptr i32, i32* %base, i32 2 137 store i32 %res, i32* %addr.2 138 ret i32* %addr.2 139} 140 141; CHECK-LABEL: pre_dec_str_multi 142; CHECK: str{{.*}}, #-4]! 143define i32* @pre_dec_str_multi(i32* %base) { 144 %addr = getelementptr i32, i32* %base, i32 0 145 %addr.1 = getelementptr i32, i32* %base, i32 1 146 %ld = load i32, i32* %addr 147 %ld.1 = load i32, i32* %addr.1 148 %res = add i32 %ld, %ld.1 149 %addr.2 = getelementptr i32, i32* %base, i32 -1 150 store i32 %res, i32* %addr.2 151 ret i32* %addr.2 152} 153 154; CHECK-LABEL: illegal_pre_inc_store_1 155; CHECK-NOT: str{{.*}} ]! 156define i32* @illegal_pre_inc_store_1(i32* %base) { 157entry: 158 %ptr.to.use = getelementptr i32, i32* %base, i32 2 159 %ptr.to.store = ptrtoint i32* %base to i32 160 store i32 %ptr.to.store, i32* %ptr.to.use, align 4 161 ret i32* %ptr.to.use 162} 163 164; TODO: The mov should be unecessary 165; CHECK-LABEL: legal_pre_inc_store_needs_copy_1 166; CHECK: add{{.*}}, #8 167; CHECK-NOT: str{{.*}}]! 168; CHECK: mov 169define i32* @legal_pre_inc_store_needs_copy_1(i32* %base) { 170entry: 171 %ptr.to.use = getelementptr i32, i32* %base, i32 2 172 %ptr.to.store = ptrtoint i32* %ptr.to.use to i32 173 store i32 %ptr.to.store, i32* %ptr.to.use, align 4 174 ret i32* %ptr.to.use 175} 176 177; CHECK-LABEL: legal_pre_inc_store_needs_copy_2 178; CHECK-NOT: mov 179; CHECK-NOT: str{{.*}}]! 180define i32* @legal_pre_inc_store_needs_copy_2(i32 %base) { 181entry: 182 %ptr = inttoptr i32 %base to i32* 183 %ptr.to.use = getelementptr i32, i32* %ptr, i32 2 184 store i32 %base, i32* %ptr.to.use, align 4 185 ret i32* %ptr.to.use 186} 187