1; RUN: llc -mtriple=arc < %s | FileCheck %s 2 3; CHECK-LABEL: load32 4; CHECK: ld %r0, [%r0,16000] 5 6define i32 @load32(ptr %bp) nounwind { 7entry: 8 %gep = getelementptr i32, ptr %bp, i32 4000 9 %v = load i32, ptr %gep, align 4 10 ret i32 %v 11} 12 13; CHECK-LABEL: load16 14; CHECK: ldh %r0, [%r0,8000] 15 16define i16 @load16(ptr %bp) nounwind { 17entry: 18 %gep = getelementptr i16, ptr %bp, i32 4000 19 %v = load i16, ptr %gep, align 2 20 ret i16 %v 21} 22 23; CHECK-LABEL: load8 24; CHECK: ldb %r0, [%r0,4000] 25 26define i8 @load8(ptr %bp) nounwind { 27entry: 28 %gep = getelementptr i8, ptr %bp, i32 4000 29 %v = load i8, ptr %gep, align 1 30 ret i8 %v 31} 32 33; CHECK-LABEL: sextload16 34; CHECK: ldh.x %r0, [%r0,8000] 35 36define i32 @sextload16(ptr %bp) nounwind { 37entry: 38 %gep = getelementptr i16, ptr %bp, i32 4000 39 %vl = load i16, ptr %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 47define i32 @sextload8(ptr %bp) nounwind { 48entry: 49 %gep = getelementptr i8, ptr %bp, i32 4000 50 %vl = load i8, ptr %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 58define i32 @s_sextload16(ptr %bp) nounwind { 59entry: 60 %gep = getelementptr i16, ptr %bp, i32 16 61 %vl = load i16, ptr %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 69define i32 @s_sextload8(ptr %bp) nounwind { 70entry: 71 %gep = getelementptr i8, ptr %bp, i32 16 72 %vl = load i8, ptr %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. 82define void @store32(i32 %val, ptr %bp) nounwind { 83entry: 84 %gep = getelementptr i32, ptr %bp, i32 4000 85 store i32 %val, ptr %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 93define void @store16(i16 zeroext %val, ptr %bp) nounwind { 94entry: 95 %gep = getelementptr i16, ptr %bp, i32 4000 96 store i16 %val, ptr %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 104define void @store8(i8 zeroext %val, ptr %bp) nounwind { 105entry: 106 %gep = getelementptr i8, ptr %bp, i32 4000 107 store i8 %val, ptr %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] 115define void @s_store32(i32 %val, ptr %bp) nounwind { 116entry: 117 %gep = getelementptr i32, ptr %bp, i32 16 118 store i32 %val, ptr %gep, align 4 119 ret void 120} 121 122; CHECK-LABEL: s_store16 123; CHECK-NOT: add 124; CHECK: sth %r0, [%r1,32] 125define void @s_store16(i16 zeroext %val, ptr %bp) nounwind { 126entry: 127 %gep = getelementptr i16, ptr %bp, i32 16 128 store i16 %val, ptr %gep, align 2 129 ret void 130} 131 132; CHECK-LABEL: s_store8 133; CHECK-NOT: add 134; CHECK: stb %r0, [%r1,16] 135define void @s_store8(i8 zeroext %val, ptr %bp) nounwind { 136entry: 137 %gep = getelementptr i8, ptr %bp, i32 16 138 store i8 %val, ptr %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] 150define void @g_store32(i32 %val) nounwind { 151entry: 152 store i32 %val, ptr getelementptr inbounds ([128 x i32], ptr @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] 159define i32 @g_load32() nounwind { 160 %gep = getelementptr inbounds [128 x i32], ptr @aaaa, i32 0, i32 16 161 %v = load i32, ptr %gep, align 4 162 ret i32 %v 163} 164 165; CHECK-LABEL: g_store16 166; CHECK-NOT: add 167; CHECK: sth %r0, [@bbbb+32] 168define void @g_store16(i16 %val) nounwind { 169entry: 170 store i16 %val, ptr getelementptr inbounds ([128 x i16], ptr @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] 177define i16 @g_load16() nounwind { 178 %gep = getelementptr inbounds [128 x i16], ptr @bbbb, i16 0, i16 16 179 %v = load i16, ptr %gep, align 2 180 ret i16 %v 181} 182 183; CHECK-LABEL: g_store8 184; CHECK-NOT: add 185; CHECK: stb %r0, [@cccc+16] 186define void @g_store8(i8 %val) nounwind { 187entry: 188 store i8 %val, ptr getelementptr inbounds ([128 x i8], ptr @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] 195define i8 @g_load8() nounwind { 196 %gep = getelementptr inbounds [128 x i8], ptr @cccc, i8 0, i8 16 197 %v = load i8, ptr %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 205define i32 @align2_load32(ptr %p) nounwind { 206entry: 207 %bp = bitcast ptr %p to ptr 208 %v = load i32, ptr %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[[AREG2:[0-9]+]], %r[[REG2]], 16 219; CHECK-DAG: asl %r[[AREG3:[0-9]+]], %r[[REG3]], 24 220; CHECK-DAG: or %r[[AREG01:[0-9]+]], %r[[AREG1]], %r[[REG0]] 221; CHECK-DAG: or %r[[AREG23:[0-9]+]], %r[[AREG3]], %r[[AREG2]] 222; CHECK-DAG: or %r0, %r[[AREG23]], %r[[AREG01]] 223define i32 @align1_load32(ptr %p) nounwind { 224entry: 225 %bp = bitcast ptr %p to ptr 226 %v = load i32, ptr %bp, align 1 227 ret i32 %v 228} 229 230; CHECK-LABEL: align1_load16 231; CHECK-DAG: ldb %r[[REG0:[0-9]+]], [%r0,0] 232; CHECK-DAG: ldb %r[[REG1:[0-9]+]], [%r0,1] 233; CHECK-DAG: asl %r[[REG2:[0-9]+]], %r[[REG1]], 8 234define i16 @align1_load16(ptr %p) nounwind { 235entry: 236 %bp = bitcast ptr %p to ptr 237 %v = load i16, ptr %bp, align 1 238 ret i16 %v 239} 240 241; CHECK-LABEL: align2_store32 242; CHECK-DAG: lsr %r[[REG:[0-9]+]], %r1, 16 243; CHECK-DAG: sth %r1, [%r0,0] 244; CHECK-DAG: sth %r[[REG:[0-9]+]], [%r0,2] 245define void @align2_store32(ptr %p, i32 %v) nounwind { 246entry: 247 %bp = bitcast ptr %p to ptr 248 store i32 %v, ptr %bp, align 2 249 ret void 250} 251 252; CHECK-LABEL: align1_store16 253; CHECK-DAG: lsr %r[[REG:[0-9]+]], %r1, 8 254; CHECK-DAG: stb %r1, [%r0,0] 255; CHECK-DAG: stb %r[[REG:[0-9]+]], [%r0,1] 256define void @align1_store16(ptr %p, i16 %v) nounwind { 257entry: 258 %bp = bitcast ptr %p to ptr 259 store i16 %v, ptr %bp, align 1 260 ret void 261} 262 263; CHECK-LABEL: align1_store32 264; CHECK-DAG: lsr %r[[REG0:[0-9]+]], %r1, 8 265; CHECK-DAG: lsr %r[[REG1:[0-9]+]], %r1, 16 266; CHECK-DAG: lsr %r[[REG2:[0-9]+]], %r1, 24 267; CHECK-DAG: stb %r1, [%r0,0] 268; CHECK-DAG: stb %r[[REG0]], [%r0,1] 269; CHECK-DAG: stb %r[[REG1]], [%r0,2] 270; CHECK-DAG: stb %r[[REG2]], [%r0,3] 271define void @align1_store32(ptr %p, i32 %v) nounwind { 272entry: 273 %bp = bitcast ptr %p to ptr 274 store i32 %v, ptr %bp, align 1 275 ret void 276} 277