1 ; RUN: llc -march=arc < %s | FileCheck %s 2 3 ; CHECK-LABEL: load32 4 ; CHECK: ld %r0, [%r0,16000] 5 6 define i32 @load32(i32* %bp) nounwind { 7 entry: 8 %gep = getelementptr i32, i32* %bp, i32 4000 9 %v = load i32, i32* %gep, align 4 10 ret i32 %v 11 } 12 13 ; CHECK-LABEL: load16 14 ; CHECK: ldh %r0, [%r0,8000] 15 16 define i16 @load16(i16* %bp) nounwind { 17 entry: 18 %gep = getelementptr i16, i16* %bp, i32 4000 19 %v = load i16, i16* %gep, align 2 20 ret i16 %v 21 } 22 23 ; CHECK-LABEL: load8 24 ; CHECK: ldb %r0, [%r0,4000] 25 26 define i8 @load8(i8* %bp) nounwind { 27 entry: 28 %gep = getelementptr i8, i8* %bp, i32 4000 29 %v = load i8, i8* %gep, align 1 30 ret i8 %v 31 } 32 33 ; CHECK-LABEL: sextload16 34 ; CHECK: ldh.x %r0, [%r0,8000] 35 36 define i32 @sextload16(i16* %bp) nounwind { 37 entry: 38 %gep = getelementptr i16, i16* %bp, i32 4000 39 %vl = load i16, i16* %gep, align 2 40 %v = sext i16 %vl to i32 41 ret i32 %v 42 } 43 44 ; CHECK-LABEL: sextload8 45 ; CHECK: ldb.x %r0, [%r0,4000] 46 47 define i32 @sextload8(i8* %bp) nounwind { 48 entry: 49 %gep = getelementptr i8, i8* %bp, i32 4000 50 %vl = load i8, i8* %gep, align 1 51 %v = sext i8 %vl to i32 52 ret i32 %v 53 } 54 55 ; CHECK-LABEL: s_sextload16 56 ; CHECK: ldh.x %r0, [%r0,32] 57 58 define i32 @s_sextload16(i16* %bp) nounwind { 59 entry: 60 %gep = getelementptr i16, i16* %bp, i32 16 61 %vl = load i16, i16* %gep, align 2 62 %v = sext i16 %vl to i32 63 ret i32 %v 64 } 65 66 ; CHECK-LABEL: s_sextload8 67 ; CHECK: ldb.x %r0, [%r0,16] 68 69 define i32 @s_sextload8(i8* %bp) nounwind { 70 entry: 71 %gep = getelementptr i8, i8* %bp, i32 16 72 %vl = load i8, i8* %gep, align 1 73 %v = sext i8 %vl to i32 74 ret i32 %v 75 } 76 77 ; CHECK-LABEL: store32 78 ; CHECK: add %r[[REG:[0-9]+]], %r1, 16000 79 ; CHECK: st %r0, [%r[[REG]],0] 80 81 ; Long range stores (offset does not fit in s9) must be add followed by st. 82 define void @store32(i32 %val, i32* %bp) nounwind { 83 entry: 84 %gep = getelementptr i32, i32* %bp, i32 4000 85 store i32 %val, i32* %gep, align 4 86 ret void 87 } 88 89 ; CHECK-LABEL: store16 90 ; CHECK: add %r[[REG:[0-9]+]], %r1, 8000 91 ; CHECK: sth %r0, [%r[[REG]],0] 92 93 define void @store16(i16 zeroext %val, i16* %bp) nounwind { 94 entry: 95 %gep = getelementptr i16, i16* %bp, i32 4000 96 store i16 %val, i16* %gep, align 2 97 ret void 98 } 99 100 ; CHECK-LABEL: store8 101 ; CHECK: add %r[[REG:[0-9]+]], %r1, 4000 102 ; CHECK: stb %r0, [%r[[REG]],0] 103 104 define void @store8(i8 zeroext %val, i8* %bp) nounwind { 105 entry: 106 %gep = getelementptr i8, i8* %bp, i32 4000 107 store i8 %val, i8* %gep, align 1 108 ret void 109 } 110 111 ; Short range stores can be done with [reg, s9]. 112 ; CHECK-LABEL: s_store32 113 ; CHECK-NOT: add 114 ; CHECK: st %r0, [%r1,64] 115 define void @s_store32(i32 %val, i32* %bp) nounwind { 116 entry: 117 %gep = getelementptr i32, i32* %bp, i32 16 118 store i32 %val, i32* %gep, align 4 119 ret void 120 } 121 122 ; CHECK-LABEL: s_store16 123 ; CHECK-NOT: add 124 ; CHECK: sth %r0, [%r1,32] 125 define void @s_store16(i16 zeroext %val, i16* %bp) nounwind { 126 entry: 127 %gep = getelementptr i16, i16* %bp, i32 16 128 store i16 %val, i16* %gep, align 2 129 ret void 130 } 131 132 ; CHECK-LABEL: s_store8 133 ; CHECK-NOT: add 134 ; CHECK: stb %r0, [%r1,16] 135 define void @s_store8(i8 zeroext %val, i8* %bp) nounwind { 136 entry: 137 %gep = getelementptr i8, i8* %bp, i32 16 138 store i8 %val, i8* %gep, align 1 139 ret void 140 } 141 142 143 @aaaa = internal global [128 x i32] zeroinitializer 144 @bbbb = internal global [128 x i16] zeroinitializer 145 @cccc = internal global [128 x i8] zeroinitializer 146 147 ; CHECK-LABEL: g_store32 148 ; CHECK-NOT: add 149 ; CHECK: st %r0, [@aaaa+64] 150 define void @g_store32(i32 %val) nounwind { 151 entry: 152 store i32 %val, i32* getelementptr inbounds ([128 x i32], [128 x i32]* @aaaa, i32 0, i32 16), align 4 153 ret void 154 } 155 156 ; CHECK-LABEL: g_load32 157 ; CHECK-NOT: add 158 ; CHECK: ld %r0, [@aaaa+64] 159 define i32 @g_load32() nounwind { 160 %gep = getelementptr inbounds [128 x i32], [128 x i32]* @aaaa, i32 0, i32 16 161 %v = load i32, i32* %gep, align 4 162 ret i32 %v 163 } 164 165 ; CHECK-LABEL: g_store16 166 ; CHECK-NOT: add 167 ; CHECK: sth %r0, [@bbbb+32] 168 define void @g_store16(i16 %val) nounwind { 169 entry: 170 store i16 %val, i16* getelementptr inbounds ([128 x i16], [128 x i16]* @bbbb, i16 0, i16 16), align 2 171 ret void 172 } 173 174 ; CHECK-LABEL: g_load16 175 ; CHECK-NOT: add 176 ; CHECK: ldh %r0, [@bbbb+32] 177 define i16 @g_load16() nounwind { 178 %gep = getelementptr inbounds [128 x i16], [128 x i16]* @bbbb, i16 0, i16 16 179 %v = load i16, i16* %gep, align 2 180 ret i16 %v 181 } 182 183 ; CHECK-LABEL: g_store8 184 ; CHECK-NOT: add 185 ; CHECK: stb %r0, [@cccc+16] 186 define void @g_store8(i8 %val) nounwind { 187 entry: 188 store i8 %val, i8* getelementptr inbounds ([128 x i8], [128 x i8]* @cccc, i8 0, i8 16), align 1 189 ret void 190 } 191 192 ; CHECK-LABEL: g_load8 193 ; CHECK-NOT: add 194 ; CHECK: ldb %r0, [@cccc+16] 195 define i8 @g_load8() nounwind { 196 %gep = getelementptr inbounds [128 x i8], [128 x i8]* @cccc, i8 0, i8 16 197 %v = load i8, i8* %gep, align 1 198 ret i8 %v 199 } 200 201 ; CHECK-LABEL: align2_load32 202 ; CHECK-DAG: ldh %r[[REG0:[0-9]+]], [%r0,0] 203 ; CHECK-DAG: ldh %r[[REG1:[0-9]+]], [%r0,2] 204 ; CHECK-DAG: asl %r[[REG2:[0-9]+]], %r[[REG1]], 16 205 define i32 @align2_load32(i8* %p) nounwind { 206 entry: 207 %bp = bitcast i8* %p to i32* 208 %v = load i32, i32* %bp, align 2 209 ret i32 %v 210 } 211 212 ; CHECK-LABEL: align1_load32 213 ; CHECK-DAG: ldb %r[[REG0:[0-9]+]], [%r0,0] 214 ; CHECK-DAG: ldb %r[[REG1:[0-9]+]], [%r0,1] 215 ; CHECK-DAG: ldb %r[[REG2:[0-9]+]], [%r0,2] 216 ; CHECK-DAG: ldb %r[[REG3:[0-9]+]], [%r0,3] 217 ; CHECK-DAG: asl %r[[AREG1:[0-9]+]], %r[[REG1]], 8 218 ; CHECK-DAG: asl %r[[AREG3:[0-9]+]], %r[[REG3]], 8 219 define i32 @align1_load32(i8* %p) nounwind { 220 entry: 221 %bp = bitcast i8* %p to i32* 222 %v = load i32, i32* %bp, align 1 223 ret i32 %v 224 } 225 226 ; CHECK-LABEL: align1_load16 227 ; CHECK-DAG: ldb %r[[REG0:[0-9]+]], [%r0,0] 228 ; CHECK-DAG: ldb %r[[REG1:[0-9]+]], [%r0,1] 229 ; CHECK-DAG: asl %r[[REG2:[0-9]+]], %r[[REG1]], 8 230 define i16 @align1_load16(i8* %p) nounwind { 231 entry: 232 %bp = bitcast i8* %p to i16* 233 %v = load i16, i16* %bp, align 1 234 ret i16 %v 235 } 236 237 ; CHECK-LABEL: align2_store32 238 ; CHECK-DAG: lsr %r[[REG:[0-9]+]], %r1, 16 239 ; CHECK-DAG: sth %r1, [%r0,0] 240 ; CHECK-DAG: sth %r[[REG:[0-9]+]], [%r0,2] 241 define void @align2_store32(i8* %p, i32 %v) nounwind { 242 entry: 243 %bp = bitcast i8* %p to i32* 244 store i32 %v, i32* %bp, align 2 245 ret void 246 } 247 248 ; CHECK-LABEL: align1_store16 249 ; CHECK-DAG: lsr %r[[REG:[0-9]+]], %r1, 8 250 ; CHECK-DAG: stb %r1, [%r0,0] 251 ; CHECK-DAG: stb %r[[REG:[0-9]+]], [%r0,1] 252 define void @align1_store16(i8* %p, i16 %v) nounwind { 253 entry: 254 %bp = bitcast i8* %p to i16* 255 store i16 %v, i16* %bp, align 1 256 ret void 257 } 258 259 ; CHECK-LABEL: align1_store32 260 ; CHECK-DAG: lsr %r[[REG0:[0-9]+]], %r1, 8 261 ; CHECK-DAG: lsr %r[[REG1:[0-9]+]], %r1, 16 262 ; CHECK-DAG: lsr %r[[REG2:[0-9]+]], %r1, 24 263 ; CHECK-DAG: stb %r1, [%r0,0] 264 ; CHECK-DAG: stb %r[[REG0]], [%r0,1] 265 ; CHECK-DAG: stb %r[[REG1]], [%r0,2] 266 ; CHECK-DAG: stb %r[[REG2]], [%r0,3] 267 define void @align1_store32(i8* %p, i32 %v) nounwind { 268 entry: 269 %bp = bitcast i8* %p to i32* 270 store i32 %v, i32* %bp, align 1 271 ret void 272 } 273