1; RUN: llc -march=arc < %s | FileCheck %s 2 3; CHECK-LABEL: load32 4; CHECK: ld %r0, [%r0,16000] 5 6define i32 @load32(i32* %bp) nounwind { 7entry: 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 16define i16 @load16(i16* %bp) nounwind { 17entry: 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 26define i8 @load8(i8* %bp) nounwind { 27entry: 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 36define i32 @sextload16(i16* %bp) nounwind { 37entry: 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 47define i32 @sextload8(i8* %bp) nounwind { 48entry: 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 58define i32 @s_sextload16(i16* %bp) nounwind { 59entry: 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 69define i32 @s_sextload8(i8* %bp) nounwind { 70entry: 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. 82define void @store32(i32 %val, i32* %bp) nounwind { 83entry: 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 93define void @store16(i16 zeroext %val, i16* %bp) nounwind { 94entry: 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 104define void @store8(i8 zeroext %val, i8* %bp) nounwind { 105entry: 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] 115define void @s_store32(i32 %val, i32* %bp) nounwind { 116entry: 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] 125define void @s_store16(i16 zeroext %val, i16* %bp) nounwind { 126entry: 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] 135define void @s_store8(i8 zeroext %val, i8* %bp) nounwind { 136entry: 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] 150define void @g_store32(i32 %val) nounwind { 151entry: 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] 159define 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] 168define void @g_store16(i16 %val) nounwind { 169entry: 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] 177define 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] 186define void @g_store8(i8 %val) nounwind { 187entry: 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] 195define 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 205define i32 @align2_load32(i8* %p) nounwind { 206entry: 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 219define i32 @align1_load32(i8* %p) nounwind { 220entry: 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 230define i16 @align1_load16(i8* %p) nounwind { 231entry: 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] 241define void @align2_store32(i8* %p, i32 %v) nounwind { 242entry: 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] 252define void @align1_store16(i8* %p, i16 %v) nounwind { 253entry: 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] 267define void @align1_store32(i8* %p, i32 %v) nounwind { 268entry: 269 %bp = bitcast i8* %p to i32* 270 store i32 %v, i32* %bp, align 1 271 ret void 272} 273