1; RUN: llc -mtriple=thumbv6m-eabi %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-T1 2; RUN: llc -mtriple=thumbv7m-eabi %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-T2 3 4 5; Register offset 6 7; CHECK-LABEL: ldrsb_rr 8; CHECK: ldrsb r0, [r0, r1] 9define i32 @ldrsb_rr(i8* %p, i32 %n) { 10entry: 11 %arrayidx = getelementptr inbounds i8, i8* %p, i32 %n 12 %0 = load i8, i8* %arrayidx, align 1 13 %conv = sext i8 %0 to i32 14 ret i32 %conv 15} 16 17; CHECK-LABEL: ldrsh_rr 18; CHECK-T1: lsls r1, r1, #1 19; CHECK-T1: ldrsh r0, [r0, r1] 20; CHECK-T2: ldrsh.w r0, [r0, r1, lsl #1] 21define i32 @ldrsh_rr(i16* %p, i32 %n) { 22entry: 23 %arrayidx = getelementptr inbounds i16, i16* %p, i32 %n 24 %0 = load i16, i16* %arrayidx, align 2 25 %conv = sext i16 %0 to i32 26 ret i32 %conv 27} 28 29; CHECK-LABEL: ldrb_rr 30; CHECK: ldrb r0, [r0, r1] 31define i32 @ldrb_rr(i8* %p, i32 %n) { 32entry: 33 %arrayidx = getelementptr inbounds i8, i8* %p, i32 %n 34 %0 = load i8, i8* %arrayidx, align 1 35 %conv = zext i8 %0 to i32 36 ret i32 %conv 37} 38 39; CHECK-LABEL: ldrh_rr 40; CHECK-T1: lsls r1, r1, #1 41; CHECK-T1: ldrh r0, [r0, r1] 42; CHECK-T2: ldrh.w r0, [r0, r1, lsl #1] 43define i32 @ldrh_rr(i16* %p, i32 %n) { 44entry: 45 %arrayidx = getelementptr inbounds i16, i16* %p, i32 %n 46 %0 = load i16, i16* %arrayidx, align 2 47 %conv = zext i16 %0 to i32 48 ret i32 %conv 49} 50 51; CHECK-LABEL: ldr_rr 52; CHECK-T1: lsls r1, r1, #2 53; CHECK-T1: ldr r0, [r0, r1] 54; CHECK-T2: ldr.w r0, [r0, r1, lsl #2] 55define i32 @ldr_rr(i32* %p, i32 %n) { 56entry: 57 %arrayidx = getelementptr inbounds i32, i32* %p, i32 %n 58 %0 = load i32, i32* %arrayidx, align 4 59 ret i32 %0 60} 61 62; CHECK-LABEL: strb_rr 63; CHECK: strb r2, [r0, r1] 64define void @strb_rr(i8* %p, i32 %n, i32 %x) { 65entry: 66 %conv = trunc i32 %x to i8 67 %arrayidx = getelementptr inbounds i8, i8* %p, i32 %n 68 store i8 %conv, i8* %arrayidx, align 1 69 ret void 70} 71 72; CHECK-LABEL: strh_rr 73; CHECK-T1: lsls r1, r1, #1 74; CHECK-T1: strh r2, [r0, r1] 75; CHECK-T2: strh.w r2, [r0, r1, lsl #1] 76define void @strh_rr(i16* %p, i32 %n, i32 %x) { 77entry: 78 %conv = trunc i32 %x to i16 79 %arrayidx = getelementptr inbounds i16, i16* %p, i32 %n 80 store i16 %conv, i16* %arrayidx, align 2 81 ret void 82} 83 84; CHECK-LABEL: str_rr 85; CHECK-T1: lsls r1, r1, #2 86; CHECK-T1: str r2, [r0, r1] 87; CHECK-T2: str.w r2, [r0, r1, lsl #2] 88define void @str_rr(i32* %p, i32 %n, i32 %x) { 89entry: 90 %arrayidx = getelementptr inbounds i32, i32* %p, i32 %n 91 store i32 %x, i32* %arrayidx, align 4 92 ret void 93} 94 95 96; Immediate offset of zero 97 98; CHECK-LABEL: ldrsb_ri_zero 99; CHECK-T1: movs r1, #0 100; CHECK-T1: ldrsb r0, [r0, r1] 101; CHECK-T2: ldrsb.w r0, [r0] 102define i32 @ldrsb_ri_zero(i8* %p) { 103entry: 104 %0 = load i8, i8* %p, align 1 105 %conv = sext i8 %0 to i32 106 ret i32 %conv 107} 108 109; CHECK-LABEL: ldrsh_ri_zero 110; CHECK-T1: movs r1, #0 111; CHECK-T1: ldrsh r0, [r0, r1] 112; CHECK-T2: ldrsh.w r0, [r0] 113define i32 @ldrsh_ri_zero(i16* %p) { 114entry: 115 %0 = load i16, i16* %p, align 2 116 %conv = sext i16 %0 to i32 117 ret i32 %conv 118} 119 120; CHECK-LABEL: ldrb_ri_zero 121; CHECK: ldrb r0, [r0] 122define i32 @ldrb_ri_zero(i8* %p) { 123entry: 124 %0 = load i8, i8* %p, align 1 125 %conv = zext i8 %0 to i32 126 ret i32 %conv 127} 128 129; CHECK-LABEL: ldrh_ri_zero 130; CHECK: ldrh r0, [r0] 131define i32 @ldrh_ri_zero(i16* %p) { 132entry: 133 %0 = load i16, i16* %p, align 2 134 %conv = zext i16 %0 to i32 135 ret i32 %conv 136} 137 138; CHECK-LABEL: ldr_ri_zero 139; CHECK: ldr r0, [r0] 140define i32 @ldr_ri_zero(i32* %p) { 141entry: 142 %0 = load i32, i32* %p, align 4 143 ret i32 %0 144} 145 146; CHECK-LABEL: strb_ri_zero 147; CHECK: strb r1, [r0] 148define void @strb_ri_zero(i8* %p, i32 %x) { 149entry: 150 %conv = trunc i32 %x to i8 151 store i8 %conv, i8* %p, align 1 152 ret void 153} 154 155; CHECK-LABEL: strh_ri_zero 156; CHECK: strh r1, [r0] 157define void @strh_ri_zero(i16* %p, i32 %x) { 158entry: 159 %conv = trunc i32 %x to i16 160 store i16 %conv, i16* %p, align 2 161 ret void 162} 163 164; CHECK-LABEL: str_ri_zero 165; CHECK: str r1, [r0] 166define void @str_ri_zero(i32* %p, i32 %x) { 167entry: 168 store i32 %x, i32* %p, align 4 169 ret void 170} 171 172 173; Maximum Thumb-1 immediate offset 174 175; CHECK-LABEL: ldrsb_ri_t1_max 176; CHECK-T1: movs r1, #31 177; CHECK-T1: ldrsb r0, [r0, r1] 178; CHECK-T2: ldrsb.w r0, [r0, #31] 179define i32 @ldrsb_ri_t1_max(i8* %p) { 180entry: 181 %arrayidx = getelementptr inbounds i8, i8* %p, i32 31 182 %0 = load i8, i8* %arrayidx, align 1 183 %conv = sext i8 %0 to i32 184 ret i32 %conv 185} 186 187; CHECK-LABEL: ldrsh_ri_t1_max 188; CHECK-T1: movs r1, #62 189; CHECK-T1: ldrsh r0, [r0, r1] 190; CHECK-T2: ldrsh.w r0, [r0, #62] 191define i32 @ldrsh_ri_t1_max(i16* %p) { 192entry: 193 %arrayidx = getelementptr inbounds i16, i16* %p, i32 31 194 %0 = load i16, i16* %arrayidx, align 2 195 %conv = sext i16 %0 to i32 196 ret i32 %conv 197} 198 199; CHECK-LABEL: ldrb_ri_t1_max 200; CHECK: ldrb r0, [r0, #31] 201define i32 @ldrb_ri_t1_max(i8* %p) { 202entry: 203 %arrayidx = getelementptr inbounds i8, i8* %p, i32 31 204 %0 = load i8, i8* %arrayidx, align 1 205 %conv = zext i8 %0 to i32 206 ret i32 %conv 207} 208 209; CHECK-LABEL: ldrh_ri_t1_max 210; CHECK: ldrh r0, [r0, #62] 211define i32 @ldrh_ri_t1_max(i16* %p) { 212entry: 213 %arrayidx = getelementptr inbounds i16, i16* %p, i32 31 214 %0 = load i16, i16* %arrayidx, align 2 215 %conv = zext i16 %0 to i32 216 ret i32 %conv 217} 218 219; CHECK-LABEL: ldr_ri_t1_max 220; CHECK: ldr r0, [r0, #124] 221define i32 @ldr_ri_t1_max(i32* %p) { 222entry: 223 %arrayidx = getelementptr inbounds i32, i32* %p, i32 31 224 %0 = load i32, i32* %arrayidx, align 4 225 ret i32 %0 226} 227 228; CHECK-LABEL: strb_ri_t1_max 229; CHECK: strb r1, [r0, #31] 230define void @strb_ri_t1_max(i8* %p, i32 %x) { 231entry: 232 %conv = trunc i32 %x to i8 233 %arrayidx = getelementptr inbounds i8, i8* %p, i32 31 234 store i8 %conv, i8* %arrayidx, align 1 235 ret void 236} 237 238; CHECK-LABEL: strh_ri_t1_max 239; CHECK: strh r1, [r0, #62] 240define void @strh_ri_t1_max(i16* %p, i32 %x) { 241entry: 242 %conv = trunc i32 %x to i16 243 %arrayidx = getelementptr inbounds i16, i16* %p, i32 31 244 store i16 %conv, i16* %arrayidx, align 2 245 ret void 246} 247 248; CHECK-LABEL: str_ri_t1_max 249; CHECK: str r1, [r0, #124] 250define void @str_ri_t1_max(i32* %p, i32 %x) { 251entry: 252 %arrayidx = getelementptr inbounds i32, i32* %p, i32 31 253 store i32 %x, i32* %arrayidx, align 4 254 ret void 255} 256 257 258; One past maximum Thumb-1 immediate offset 259 260; CHECK-LABEL: ldrsb_ri_t1_too_big 261; CHECK-T1: movs r1, #32 262; CHECK-T1: ldrsb r0, [r0, r1] 263; CHECK-T2: ldrsb.w r0, [r0, #32] 264define i32 @ldrsb_ri_t1_too_big(i8* %p) { 265entry: 266 %arrayidx = getelementptr inbounds i8, i8* %p, i32 32 267 %0 = load i8, i8* %arrayidx, align 1 268 %conv = sext i8 %0 to i32 269 ret i32 %conv 270} 271 272; CHECK-LABEL: ldrsh_ri_t1_too_big 273; CHECK-T1: movs r1, #64 274; CHECK-T1: ldrsh r0, [r0, r1] 275; CHECK-T2: ldrsh.w r0, [r0, #64] 276define i32 @ldrsh_ri_t1_too_big(i16* %p) { 277entry: 278 %arrayidx = getelementptr inbounds i16, i16* %p, i32 32 279 %0 = load i16, i16* %arrayidx, align 2 280 %conv = sext i16 %0 to i32 281 ret i32 %conv 282} 283 284; CHECK-LABEL: ldrb_ri_t1_too_big 285; CHECK-T1: movs r1, #32 286; CHECK-T1: ldrb r0, [r0, r1] 287; CHECK-T2: ldrb.w r0, [r0, #32] 288define i32 @ldrb_ri_t1_too_big(i8* %p) { 289entry: 290 %arrayidx = getelementptr inbounds i8, i8* %p, i32 32 291 %0 = load i8, i8* %arrayidx, align 1 292 %conv = zext i8 %0 to i32 293 ret i32 %conv 294} 295 296; CHECK-LABEL: ldrh_ri_t1_too_big 297; CHECK-T1: movs r1, #64 298; CHECK-T1: ldrh r0, [r0, r1] 299; CHECK-T2: ldrh.w r0, [r0, #64] 300define i32 @ldrh_ri_t1_too_big(i16* %p) { 301entry: 302 %arrayidx = getelementptr inbounds i16, i16* %p, i32 32 303 %0 = load i16, i16* %arrayidx, align 2 304 %conv = zext i16 %0 to i32 305 ret i32 %conv 306} 307 308; CHECK-LABEL: ldr_ri_t1_too_big 309; CHECK-T1: movs r1, #128 310; CHECK-T1: ldr r0, [r0, r1] 311; CHECK-T2: ldr.w r0, [r0, #128] 312define i32 @ldr_ri_t1_too_big(i32* %p) { 313entry: 314 %arrayidx = getelementptr inbounds i32, i32* %p, i32 32 315 %0 = load i32, i32* %arrayidx, align 4 316 ret i32 %0 317} 318 319; CHECK-LABEL: strb_ri_t1_too_big 320; CHECK-T1: movs r2, #32 321; CHECK-T1: strb r1, [r0, r2] 322; CHECK-T2: strb.w r1, [r0, #32] 323define void @strb_ri_t1_too_big(i8* %p, i32 %x) { 324entry: 325 %conv = trunc i32 %x to i8 326 %arrayidx = getelementptr inbounds i8, i8* %p, i32 32 327 store i8 %conv, i8* %arrayidx, align 1 328 ret void 329} 330 331; CHECK-LABEL: strh_ri_t1_too_big 332; CHECK-T1: movs r2, #64 333; CHECK-T1: strh r1, [r0, r2] 334; CHECK-T2: strh.w r1, [r0, #64] 335define void @strh_ri_t1_too_big(i16* %p, i32 %x) { 336entry: 337 %conv = trunc i32 %x to i16 338 %arrayidx = getelementptr inbounds i16, i16* %p, i32 32 339 store i16 %conv, i16* %arrayidx, align 2 340 ret void 341} 342 343; CHECK-LABEL: str_ri_t1_too_big 344; CHECK-T1: movs r2, #128 345; CHECK-T1: str r1, [r0, r2] 346; CHECK-T2: str.w r1, [r0, #128] 347define void @str_ri_t1_too_big(i32* %p, i32 %x) { 348entry: 349 %arrayidx = getelementptr inbounds i32, i32* %p, i32 32 350 store i32 %x, i32* %arrayidx, align 4 351 ret void 352} 353 354 355; Maximum Thumb-2 immediate offset 356 357; CHECK-LABEL: ldrsb_ri_t2_max 358; CHECK-T1: ldr r1, .LCP 359; CHECK-T1: ldrsb r0, [r0, r1] 360; CHECK-T2: ldrsb.w r0, [r0, #4095] 361define i32 @ldrsb_ri_t2_max(i8* %p) { 362entry: 363 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095 364 %0 = load i8, i8* %add.ptr, align 1 365 %conv = sext i8 %0 to i32 366 ret i32 %conv 367} 368 369; CHECK-LABEL: ldrsh_ri_t2_max 370; CHECK-T1: ldr r1, .LCP 371; CHECK-T1: ldrsh r0, [r0, r1] 372; CHECK-T2: ldrsh.w r0, [r0, #4095] 373define i32 @ldrsh_ri_t2_max(i8* %p) { 374entry: 375 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095 376 %0 = bitcast i8* %add.ptr to i16* 377 %1 = load i16, i16* %0, align 2 378 %conv = sext i16 %1 to i32 379 ret i32 %conv 380} 381 382; CHECK-LABEL: ldrb_ri_t2_max 383; CHECK-T1: ldr r1, .LCP 384; CHECK-T1: ldrb r0, [r0, r1] 385; CHECK-T2: ldrb.w r0, [r0, #4095] 386define i32 @ldrb_ri_t2_max(i8* %p) { 387entry: 388 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095 389 %0 = load i8, i8* %add.ptr, align 1 390 %conv = zext i8 %0 to i32 391 ret i32 %conv 392} 393 394; CHECK-LABEL: ldrh_ri_t2_max 395; CHECK-T1: ldr r1, .LCP 396; CHECK-T1: ldrh r0, [r0, r1] 397; CHECK-T2: ldrh.w r0, [r0, #4095] 398define i32 @ldrh_ri_t2_max(i8* %p) { 399entry: 400 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095 401 %0 = bitcast i8* %add.ptr to i16* 402 %1 = load i16, i16* %0, align 2 403 %conv = zext i16 %1 to i32 404 ret i32 %conv 405} 406 407; CHECK-LABEL: ldr_ri_t2_max 408; CHECK-T1: ldr r1, .LCP 409; CHECK-T1: ldr r0, [r0, r1] 410; CHECK-T2: ldr.w r0, [r0, #4095] 411define i32 @ldr_ri_t2_max(i8* %p) { 412entry: 413 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095 414 %0 = bitcast i8* %add.ptr to i32* 415 %1 = load i32, i32* %0, align 4 416 ret i32 %1 417} 418 419; CHECK-LABEL: strb_ri_t2_max 420; CHECK-T1: ldr r2, .LCP 421; CHECK-T1: strb r1, [r0, r2] 422; CHECK-T2: strb.w r1, [r0, #4095] 423define void @strb_ri_t2_max(i8* %p, i32 %x) { 424entry: 425 %conv = trunc i32 %x to i8 426 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095 427 store i8 %conv, i8* %add.ptr, align 1 428 ret void 429} 430 431; CHECK-LABEL: strh_ri_t2_max 432; CHECK-T1: ldr r2, .LCP 433; CHECK-T1: strh r1, [r0, r2] 434; CHECK-T2: strh.w r1, [r0, #4095] 435define void @strh_ri_t2_max(i8* %p, i32 %x) { 436entry: 437 %conv = trunc i32 %x to i16 438 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095 439 %0 = bitcast i8* %add.ptr to i16* 440 store i16 %conv, i16* %0, align 2 441 ret void 442} 443 444; CHECK-LABEL: str_ri_t2_max 445; CHECK-T1: ldr r2, .LCP 446; CHECK-T1: str r1, [r0, r2] 447; CHECK-T2: str.w r1, [r0, #4095] 448define void @str_ri_t2_max(i8* %p, i32 %x) { 449entry: 450 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095 451 %0 = bitcast i8* %add.ptr to i32* 452 store i32 %x, i32* %0, align 4 453 ret void 454} 455 456 457; One past maximum Thumb-2 immediate offset 458 459; CHECK-LABEL: ldrsb_ri_t2_too_big 460; CHECK-T1: movs r1, #1 461; CHECK-T1: lsls r1, r1, #12 462; CHECK-T2: mov.w r1, #4096 463; CHECK: ldrsb r0, [r0, r1] 464define i32 @ldrsb_ri_t2_too_big(i8* %p) { 465entry: 466 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096 467 %0 = load i8, i8* %add.ptr, align 1 468 %conv = sext i8 %0 to i32 469 ret i32 %conv 470} 471 472; CHECK-LABEL: ldrsh_ri_t2_too_big 473; CHECK-T1: movs r1, #1 474; CHECK-T1: lsls r1, r1, #12 475; CHECK-T2: mov.w r1, #4096 476; CHECK: ldrsh r0, [r0, r1] 477define i32 @ldrsh_ri_t2_too_big(i8* %p) { 478entry: 479 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096 480 %0 = bitcast i8* %add.ptr to i16* 481 %1 = load i16, i16* %0, align 2 482 %conv = sext i16 %1 to i32 483 ret i32 %conv 484} 485 486; CHECK-LABEL: ldrb_ri_t2_too_big 487; CHECK-T1: movs r1, #1 488; CHECK-T1: lsls r1, r1, #12 489; CHECK-T2: mov.w r1, #4096 490; CHECK: ldrb r0, [r0, r1] 491define i32 @ldrb_ri_t2_too_big(i8* %p) { 492entry: 493 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096 494 %0 = load i8, i8* %add.ptr, align 1 495 %conv = zext i8 %0 to i32 496 ret i32 %conv 497} 498 499; CHECK-LABEL: ldrh_ri_t2_too_big 500; CHECK-T1: movs r1, #1 501; CHECK-T1: lsls r1, r1, #12 502; CHECK-T2: mov.w r1, #4096 503; CHECK: ldrh r0, [r0, r1] 504define i32 @ldrh_ri_t2_too_big(i8* %p) { 505entry: 506 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096 507 %0 = bitcast i8* %add.ptr to i16* 508 %1 = load i16, i16* %0, align 2 509 %conv = zext i16 %1 to i32 510 ret i32 %conv 511} 512 513; CHECK-LABEL: ldr_ri_t2_too_big 514; CHECK-T1: movs r1, #1 515; CHECK-T1: lsls r1, r1, #12 516; CHECK-T2: mov.w r1, #4096 517; CHECK: ldr r0, [r0, r1] 518define i32 @ldr_ri_t2_too_big(i8* %p) { 519entry: 520 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096 521 %0 = bitcast i8* %add.ptr to i32* 522 %1 = load i32, i32* %0, align 4 523 ret i32 %1 524} 525 526; CHECK-LABEL: strb_ri_t2_too_big 527; CHECK-T1: movs r2, #1 528; CHECK-T1: lsls r2, r2, #12 529; CHECK-T2: mov.w r2, #4096 530; CHECK: strb r1, [r0, r2] 531define void @strb_ri_t2_too_big(i8* %p, i32 %x) { 532entry: 533 %conv = trunc i32 %x to i8 534 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096 535 store i8 %conv, i8* %add.ptr, align 1 536 ret void 537} 538 539; CHECK-LABEL: strh_ri_t2_too_big 540; CHECK-T1: movs r2, #1 541; CHECK-T1: lsls r2, r2, #12 542; CHECK-T2: mov.w r2, #4096 543; CHECK: strh r1, [r0, r2] 544define void @strh_ri_t2_too_big(i8* %p, i32 %x) { 545entry: 546 %conv = trunc i32 %x to i16 547 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096 548 %0 = bitcast i8* %add.ptr to i16* 549 store i16 %conv, i16* %0, align 2 550 ret void 551} 552 553; CHECK-LABEL: str_ri_t2_too_big 554; CHECK-T1: movs r2, #1 555; CHECK-T1: lsls r2, r2, #12 556; CHECK-T2: mov.w r2, #4096 557; CHECK: str r1, [r0, r2] 558define void @str_ri_t2_too_big(i8* %p, i32 %x) { 559entry: 560 %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096 561 %0 = bitcast i8* %add.ptr to i32* 562 store i32 %x, i32* %0, align 4 563 ret void 564} 565 566 567; Negative offset 568 569define i32 @ldrsb_ri_negative(i8* %p) { 570; CHECK-T1-LABEL: ldrsb_ri_negative: 571; CHECK-T1: @ %bb.0: @ %entry 572; CHECK-T1-NEXT: movs r1, #0 573; CHECK-T1-NEXT: mvns r1, r1 574; CHECK-T1-NEXT: ldrsb r0, [r0, r1] 575; CHECK-T1-NEXT: bx lr 576; 577; CHECK-T2-LABEL: ldrsb_ri_negative: 578; CHECK-T2: @ %bb.0: @ %entry 579; CHECK-T2-NEXT: ldrsb r0, [r0, #-1] 580; CHECK-T2-NEXT: bx lr 581entry: 582 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1 583 %0 = load i8, i8* %add.ptr, align 1 584 %conv = sext i8 %0 to i32 585 ret i32 %conv 586} 587 588define i32 @ldrsh_ri_negative(i8* %p) { 589; CHECK-T1-LABEL: ldrsh_ri_negative: 590; CHECK-T1: @ %bb.0: @ %entry 591; CHECK-T1-NEXT: movs r1, #0 592; CHECK-T1-NEXT: mvns r1, r1 593; CHECK-T1-NEXT: ldrsh r0, [r0, r1] 594; CHECK-T1-NEXT: bx lr 595; 596; CHECK-T2-LABEL: ldrsh_ri_negative: 597; CHECK-T2: @ %bb.0: @ %entry 598; CHECK-T2-NEXT: ldrsh r0, [r0, #-1] 599; CHECK-T2-NEXT: bx lr 600entry: 601 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1 602 %0 = bitcast i8* %add.ptr to i16* 603 %1 = load i16, i16* %0, align 2 604 %conv = sext i16 %1 to i32 605 ret i32 %conv 606} 607 608define i32 @ldrb_ri_negative(i8* %p) { 609; CHECK-T1-LABEL: ldrb_ri_negative: 610; CHECK-T1: @ %bb.0: @ %entry 611; CHECK-T1-NEXT: subs r0, r0, #1 612; CHECK-T1-NEXT: ldrb r0, [r0] 613; CHECK-T1-NEXT: bx lr 614; 615; CHECK-T2-LABEL: ldrb_ri_negative: 616; CHECK-T2: @ %bb.0: @ %entry 617; CHECK-T2-NEXT: ldrb r0, [r0, #-1] 618; CHECK-T2-NEXT: bx lr 619entry: 620 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1 621 %0 = load i8, i8* %add.ptr, align 1 622 %conv = zext i8 %0 to i32 623 ret i32 %conv 624} 625 626define i32 @ldrh_ri_negative(i8* %p) { 627; CHECK-T1-LABEL: ldrh_ri_negative: 628; CHECK-T1: @ %bb.0: @ %entry 629; CHECK-T1-NEXT: subs r0, r0, #1 630; CHECK-T1-NEXT: ldrh r0, [r0] 631; CHECK-T1-NEXT: bx lr 632; 633; CHECK-T2-LABEL: ldrh_ri_negative: 634; CHECK-T2: @ %bb.0: @ %entry 635; CHECK-T2-NEXT: ldrh r0, [r0, #-1] 636; CHECK-T2-NEXT: bx lr 637entry: 638 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1 639 %0 = bitcast i8* %add.ptr to i16* 640 %1 = load i16, i16* %0, align 2 641 %conv = zext i16 %1 to i32 642 ret i32 %conv 643} 644 645define i32 @ldr_ri_negative(i8* %p) { 646; CHECK-T1-LABEL: ldr_ri_negative: 647; CHECK-T1: @ %bb.0: @ %entry 648; CHECK-T1-NEXT: subs r0, r0, #1 649; CHECK-T1-NEXT: ldr r0, [r0] 650; CHECK-T1-NEXT: bx lr 651; 652; CHECK-T2-LABEL: ldr_ri_negative: 653; CHECK-T2: @ %bb.0: @ %entry 654; CHECK-T2-NEXT: ldr r0, [r0, #-1] 655; CHECK-T2-NEXT: bx lr 656entry: 657 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1 658 %0 = bitcast i8* %add.ptr to i32* 659 %1 = load i32, i32* %0, align 4 660 ret i32 %1 661} 662 663define void @strb_ri_negative(i8* %p, i32 %x) { 664; CHECK-T1-LABEL: strb_ri_negative: 665; CHECK-T1: @ %bb.0: @ %entry 666; CHECK-T1-NEXT: subs r0, r0, #1 667; CHECK-T1-NEXT: strb r1, [r0] 668; CHECK-T1-NEXT: bx lr 669; 670; CHECK-T2-LABEL: strb_ri_negative: 671; CHECK-T2: @ %bb.0: @ %entry 672; CHECK-T2-NEXT: strb r1, [r0, #-1] 673; CHECK-T2-NEXT: bx lr 674entry: 675 %conv = trunc i32 %x to i8 676 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1 677 store i8 %conv, i8* %add.ptr, align 1 678 ret void 679} 680 681define void @strh_ri_negative(i8* %p, i32 %x) { 682; CHECK-T1-LABEL: strh_ri_negative: 683; CHECK-T1: @ %bb.0: @ %entry 684; CHECK-T1-NEXT: subs r0, r0, #1 685; CHECK-T1-NEXT: strh r1, [r0] 686; CHECK-T1-NEXT: bx lr 687; 688; CHECK-T2-LABEL: strh_ri_negative: 689; CHECK-T2: @ %bb.0: @ %entry 690; CHECK-T2-NEXT: strh r1, [r0, #-1] 691; CHECK-T2-NEXT: bx lr 692entry: 693 %conv = trunc i32 %x to i16 694 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1 695 %0 = bitcast i8* %add.ptr to i16* 696 store i16 %conv, i16* %0, align 2 697 ret void 698} 699 700define void @str_ri_negative(i8* %p, i32 %x) { 701; CHECK-T1-LABEL: str_ri_negative: 702; CHECK-T1: @ %bb.0: @ %entry 703; CHECK-T1-NEXT: subs r0, r0, #1 704; CHECK-T1-NEXT: str r1, [r0] 705; CHECK-T1-NEXT: bx lr 706; 707; CHECK-T2-LABEL: str_ri_negative: 708; CHECK-T2: @ %bb.0: @ %entry 709; CHECK-T2-NEXT: str r1, [r0, #-1] 710; CHECK-T2-NEXT: bx lr 711entry: 712 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1 713 %0 = bitcast i8* %add.ptr to i32* 714 store i32 %x, i32* %0, align 4 715 ret void 716} 717 718 719; Negative 255 offset 720 721define i32 @ldrsb_ri_negative255(i8* %p) { 722; CHECK-T1-LABEL: ldrsb_ri_negative255: 723; CHECK-T1: @ %bb.0: @ %entry 724; CHECK-T1-NEXT: movs r1, #254 725; CHECK-T1-NEXT: mvns r1, r1 726; CHECK-T1-NEXT: ldrsb r0, [r0, r1] 727; CHECK-T1-NEXT: bx lr 728; 729; CHECK-T2-LABEL: ldrsb_ri_negative255: 730; CHECK-T2: @ %bb.0: @ %entry 731; CHECK-T2-NEXT: ldrsb r0, [r0, #-255] 732; CHECK-T2-NEXT: bx lr 733entry: 734 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255 735 %0 = load i8, i8* %add.ptr, align 1 736 %conv = sext i8 %0 to i32 737 ret i32 %conv 738} 739 740define i32 @ldrsh_ri_negative255(i8* %p) { 741; CHECK-T1-LABEL: ldrsh_ri_negative255: 742; CHECK-T1: @ %bb.0: @ %entry 743; CHECK-T1-NEXT: movs r1, #254 744; CHECK-T1-NEXT: mvns r1, r1 745; CHECK-T1-NEXT: ldrsh r0, [r0, r1] 746; CHECK-T1-NEXT: bx lr 747; 748; CHECK-T2-LABEL: ldrsh_ri_negative255: 749; CHECK-T2: @ %bb.0: @ %entry 750; CHECK-T2-NEXT: ldrsh r0, [r0, #-255] 751; CHECK-T2-NEXT: bx lr 752entry: 753 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255 754 %0 = bitcast i8* %add.ptr to i16* 755 %1 = load i16, i16* %0, align 2 756 %conv = sext i16 %1 to i32 757 ret i32 %conv 758} 759 760define i32 @ldrb_ri_negative255(i8* %p) { 761; CHECK-T1-LABEL: ldrb_ri_negative255: 762; CHECK-T1: @ %bb.0: @ %entry 763; CHECK-T1-NEXT: subs r0, #255 764; CHECK-T1-NEXT: ldrb r0, [r0] 765; CHECK-T1-NEXT: bx lr 766; 767; CHECK-T2-LABEL: ldrb_ri_negative255: 768; CHECK-T2: @ %bb.0: @ %entry 769; CHECK-T2-NEXT: ldrb r0, [r0, #-255] 770; CHECK-T2-NEXT: bx lr 771entry: 772 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255 773 %0 = load i8, i8* %add.ptr, align 1 774 %conv = zext i8 %0 to i32 775 ret i32 %conv 776} 777 778define i32 @ldrh_ri_negative255(i8* %p) { 779; CHECK-T1-LABEL: ldrh_ri_negative255: 780; CHECK-T1: @ %bb.0: @ %entry 781; CHECK-T1-NEXT: subs r0, #255 782; CHECK-T1-NEXT: ldrh r0, [r0] 783; CHECK-T1-NEXT: bx lr 784; 785; CHECK-T2-LABEL: ldrh_ri_negative255: 786; CHECK-T2: @ %bb.0: @ %entry 787; CHECK-T2-NEXT: ldrh r0, [r0, #-255] 788; CHECK-T2-NEXT: bx lr 789entry: 790 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255 791 %0 = bitcast i8* %add.ptr to i16* 792 %1 = load i16, i16* %0, align 2 793 %conv = zext i16 %1 to i32 794 ret i32 %conv 795} 796 797define i32 @ldr_ri_negative255(i8* %p) { 798; CHECK-T1-LABEL: ldr_ri_negative255: 799; CHECK-T1: @ %bb.0: @ %entry 800; CHECK-T1-NEXT: subs r0, #255 801; CHECK-T1-NEXT: ldr r0, [r0] 802; CHECK-T1-NEXT: bx lr 803; 804; CHECK-T2-LABEL: ldr_ri_negative255: 805; CHECK-T2: @ %bb.0: @ %entry 806; CHECK-T2-NEXT: ldr r0, [r0, #-255] 807; CHECK-T2-NEXT: bx lr 808entry: 809 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255 810 %0 = bitcast i8* %add.ptr to i32* 811 %1 = load i32, i32* %0, align 4 812 ret i32 %1 813} 814 815define void @strb_ri_negative255(i8* %p, i32 %x) { 816; CHECK-T1-LABEL: strb_ri_negative255: 817; CHECK-T1: @ %bb.0: @ %entry 818; CHECK-T1-NEXT: subs r0, #255 819; CHECK-T1-NEXT: strb r1, [r0] 820; CHECK-T1-NEXT: bx lr 821; 822; CHECK-T2-LABEL: strb_ri_negative255: 823; CHECK-T2: @ %bb.0: @ %entry 824; CHECK-T2-NEXT: strb r1, [r0, #-255] 825; CHECK-T2-NEXT: bx lr 826entry: 827 %conv = trunc i32 %x to i8 828 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255 829 store i8 %conv, i8* %add.ptr, align 1 830 ret void 831} 832 833define void @strh_ri_negative255(i8* %p, i32 %x) { 834; CHECK-T1-LABEL: strh_ri_negative255: 835; CHECK-T1: @ %bb.0: @ %entry 836; CHECK-T1-NEXT: subs r0, #255 837; CHECK-T1-NEXT: strh r1, [r0] 838; CHECK-T1-NEXT: bx lr 839; 840; CHECK-T2-LABEL: strh_ri_negative255: 841; CHECK-T2: @ %bb.0: @ %entry 842; CHECK-T2-NEXT: strh r1, [r0, #-255] 843; CHECK-T2-NEXT: bx lr 844entry: 845 %conv = trunc i32 %x to i16 846 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255 847 %0 = bitcast i8* %add.ptr to i16* 848 store i16 %conv, i16* %0, align 2 849 ret void 850} 851 852define void @str_ri_negative255(i8* %p, i32 %x) { 853; CHECK-T1-LABEL: str_ri_negative255: 854; CHECK-T1: @ %bb.0: @ %entry 855; CHECK-T1-NEXT: subs r0, #255 856; CHECK-T1-NEXT: str r1, [r0] 857; CHECK-T1-NEXT: bx lr 858; 859; CHECK-T2-LABEL: str_ri_negative255: 860; CHECK-T2: @ %bb.0: @ %entry 861; CHECK-T2-NEXT: str r1, [r0, #-255] 862; CHECK-T2-NEXT: bx lr 863entry: 864 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255 865 %0 = bitcast i8* %add.ptr to i32* 866 store i32 %x, i32* %0, align 4 867 ret void 868} 869 870 871; Negative 256 offset 872 873define i32 @ldrsb_ri_negative256(i8* %p) { 874; CHECK-T1-LABEL: ldrsb_ri_negative256: 875; CHECK-T1: @ %bb.0: @ %entry 876; CHECK-T1-NEXT: movs r1, #255 877; CHECK-T1-NEXT: mvns r1, r1 878; CHECK-T1-NEXT: ldrsb r0, [r0, r1] 879; CHECK-T1-NEXT: bx lr 880; 881; CHECK-T2-LABEL: ldrsb_ri_negative256: 882; CHECK-T2: @ %bb.0: @ %entry 883; CHECK-T2-NEXT: mvn r1, #255 884; CHECK-T2-NEXT: ldrsb r0, [r0, r1] 885; CHECK-T2-NEXT: bx lr 886entry: 887 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256 888 %0 = load i8, i8* %add.ptr, align 1 889 %conv = sext i8 %0 to i32 890 ret i32 %conv 891} 892 893define i32 @ldrsh_ri_negative256(i8* %p) { 894; CHECK-T1-LABEL: ldrsh_ri_negative256: 895; CHECK-T1: @ %bb.0: @ %entry 896; CHECK-T1-NEXT: movs r1, #255 897; CHECK-T1-NEXT: mvns r1, r1 898; CHECK-T1-NEXT: ldrsh r0, [r0, r1] 899; CHECK-T1-NEXT: bx lr 900; 901; CHECK-T2-LABEL: ldrsh_ri_negative256: 902; CHECK-T2: @ %bb.0: @ %entry 903; CHECK-T2-NEXT: mvn r1, #255 904; CHECK-T2-NEXT: ldrsh r0, [r0, r1] 905; CHECK-T2-NEXT: bx lr 906entry: 907 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256 908 %0 = bitcast i8* %add.ptr to i16* 909 %1 = load i16, i16* %0, align 2 910 %conv = sext i16 %1 to i32 911 ret i32 %conv 912} 913 914define i32 @ldrb_ri_negative256(i8* %p) { 915; CHECK-T1-LABEL: ldrb_ri_negative256: 916; CHECK-T1: @ %bb.0: @ %entry 917; CHECK-T1-NEXT: movs r1, #255 918; CHECK-T1-NEXT: mvns r1, r1 919; CHECK-T1-NEXT: ldrb r0, [r0, r1] 920; CHECK-T1-NEXT: bx lr 921; 922; CHECK-T2-LABEL: ldrb_ri_negative256: 923; CHECK-T2: @ %bb.0: @ %entry 924; CHECK-T2-NEXT: mvn r1, #255 925; CHECK-T2-NEXT: ldrb r0, [r0, r1] 926; CHECK-T2-NEXT: bx lr 927entry: 928 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256 929 %0 = load i8, i8* %add.ptr, align 1 930 %conv = zext i8 %0 to i32 931 ret i32 %conv 932} 933 934define i32 @ldrh_ri_negative256(i8* %p) { 935; CHECK-T1-LABEL: ldrh_ri_negative256: 936; CHECK-T1: @ %bb.0: @ %entry 937; CHECK-T1-NEXT: movs r1, #255 938; CHECK-T1-NEXT: mvns r1, r1 939; CHECK-T1-NEXT: ldrh r0, [r0, r1] 940; CHECK-T1-NEXT: bx lr 941; 942; CHECK-T2-LABEL: ldrh_ri_negative256: 943; CHECK-T2: @ %bb.0: @ %entry 944; CHECK-T2-NEXT: mvn r1, #255 945; CHECK-T2-NEXT: ldrh r0, [r0, r1] 946; CHECK-T2-NEXT: bx lr 947entry: 948 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256 949 %0 = bitcast i8* %add.ptr to i16* 950 %1 = load i16, i16* %0, align 2 951 %conv = zext i16 %1 to i32 952 ret i32 %conv 953} 954 955define i32 @ldr_ri_negative256(i8* %p) { 956; CHECK-T1-LABEL: ldr_ri_negative256: 957; CHECK-T1: @ %bb.0: @ %entry 958; CHECK-T1-NEXT: movs r1, #255 959; CHECK-T1-NEXT: mvns r1, r1 960; CHECK-T1-NEXT: ldr r0, [r0, r1] 961; CHECK-T1-NEXT: bx lr 962; 963; CHECK-T2-LABEL: ldr_ri_negative256: 964; CHECK-T2: @ %bb.0: @ %entry 965; CHECK-T2-NEXT: mvn r1, #255 966; CHECK-T2-NEXT: ldr r0, [r0, r1] 967; CHECK-T2-NEXT: bx lr 968entry: 969 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256 970 %0 = bitcast i8* %add.ptr to i32* 971 %1 = load i32, i32* %0, align 4 972 ret i32 %1 973} 974 975define void @strb_ri_negative256(i8* %p, i32 %x) { 976; CHECK-T1-LABEL: strb_ri_negative256: 977; CHECK-T1: @ %bb.0: @ %entry 978; CHECK-T1-NEXT: movs r2, #255 979; CHECK-T1-NEXT: mvns r2, r2 980; CHECK-T1-NEXT: strb r1, [r0, r2] 981; CHECK-T1-NEXT: bx lr 982; 983; CHECK-T2-LABEL: strb_ri_negative256: 984; CHECK-T2: @ %bb.0: @ %entry 985; CHECK-T2-NEXT: mvn r2, #255 986; CHECK-T2-NEXT: strb r1, [r0, r2] 987; CHECK-T2-NEXT: bx lr 988entry: 989 %conv = trunc i32 %x to i8 990 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256 991 store i8 %conv, i8* %add.ptr, align 1 992 ret void 993} 994 995define void @strh_ri_negative256(i8* %p, i32 %x) { 996; CHECK-T1-LABEL: strh_ri_negative256: 997; CHECK-T1: @ %bb.0: @ %entry 998; CHECK-T1-NEXT: movs r2, #255 999; CHECK-T1-NEXT: mvns r2, r2 1000; CHECK-T1-NEXT: strh r1, [r0, r2] 1001; CHECK-T1-NEXT: bx lr 1002; 1003; CHECK-T2-LABEL: strh_ri_negative256: 1004; CHECK-T2: @ %bb.0: @ %entry 1005; CHECK-T2-NEXT: mvn r2, #255 1006; CHECK-T2-NEXT: strh r1, [r0, r2] 1007; CHECK-T2-NEXT: bx lr 1008entry: 1009 %conv = trunc i32 %x to i16 1010 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256 1011 %0 = bitcast i8* %add.ptr to i16* 1012 store i16 %conv, i16* %0, align 2 1013 ret void 1014} 1015 1016define void @str_ri_negative256(i8* %p, i32 %x) { 1017; CHECK-T1-LABEL: str_ri_negative256: 1018; CHECK-T1: @ %bb.0: @ %entry 1019; CHECK-T1-NEXT: movs r2, #255 1020; CHECK-T1-NEXT: mvns r2, r2 1021; CHECK-T1-NEXT: str r1, [r0, r2] 1022; CHECK-T1-NEXT: bx lr 1023; 1024; CHECK-T2-LABEL: str_ri_negative256: 1025; CHECK-T2: @ %bb.0: @ %entry 1026; CHECK-T2-NEXT: mvn r2, #255 1027; CHECK-T2-NEXT: str r1, [r0, r2] 1028; CHECK-T2-NEXT: bx lr 1029entry: 1030 %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256 1031 %0 = bitcast i8* %add.ptr to i32* 1032 store i32 %x, i32* %0, align 4 1033 ret void 1034} 1035