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(ptr %p, i32 %n) { 10entry: 11 %arrayidx = getelementptr inbounds i8, ptr %p, i32 %n 12 %0 = load i8, ptr %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(ptr %p, i32 %n) { 22entry: 23 %arrayidx = getelementptr inbounds i16, ptr %p, i32 %n 24 %0 = load i16, ptr %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(ptr %p, i32 %n) { 32entry: 33 %arrayidx = getelementptr inbounds i8, ptr %p, i32 %n 34 %0 = load i8, ptr %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(ptr %p, i32 %n) { 44entry: 45 %arrayidx = getelementptr inbounds i16, ptr %p, i32 %n 46 %0 = load i16, ptr %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(ptr %p, i32 %n) { 56entry: 57 %arrayidx = getelementptr inbounds i32, ptr %p, i32 %n 58 %0 = load i32, ptr %arrayidx, align 4 59 ret i32 %0 60} 61 62; CHECK-LABEL: strb_rr 63; CHECK: strb r2, [r0, r1] 64define void @strb_rr(ptr %p, i32 %n, i32 %x) { 65entry: 66 %conv = trunc i32 %x to i8 67 %arrayidx = getelementptr inbounds i8, ptr %p, i32 %n 68 store i8 %conv, ptr %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(ptr %p, i32 %n, i32 %x) { 77entry: 78 %conv = trunc i32 %x to i16 79 %arrayidx = getelementptr inbounds i16, ptr %p, i32 %n 80 store i16 %conv, ptr %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(ptr %p, i32 %n, i32 %x) { 89entry: 90 %arrayidx = getelementptr inbounds i32, ptr %p, i32 %n 91 store i32 %x, ptr %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(ptr %p) { 103entry: 104 %0 = load i8, ptr %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(ptr %p) { 114entry: 115 %0 = load i16, ptr %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(ptr %p) { 123entry: 124 %0 = load i8, ptr %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(ptr %p) { 132entry: 133 %0 = load i16, ptr %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(ptr %p) { 141entry: 142 %0 = load i32, ptr %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(ptr %p, i32 %x) { 149entry: 150 %conv = trunc i32 %x to i8 151 store i8 %conv, ptr %p, align 1 152 ret void 153} 154 155; CHECK-LABEL: strh_ri_zero 156; CHECK: strh r1, [r0] 157define void @strh_ri_zero(ptr %p, i32 %x) { 158entry: 159 %conv = trunc i32 %x to i16 160 store i16 %conv, ptr %p, align 2 161 ret void 162} 163 164; CHECK-LABEL: str_ri_zero 165; CHECK: str r1, [r0] 166define void @str_ri_zero(ptr %p, i32 %x) { 167entry: 168 store i32 %x, ptr %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(ptr %p) { 180entry: 181 %arrayidx = getelementptr inbounds i8, ptr %p, i32 31 182 %0 = load i8, ptr %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(ptr %p) { 192entry: 193 %arrayidx = getelementptr inbounds i16, ptr %p, i32 31 194 %0 = load i16, ptr %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(ptr %p) { 202entry: 203 %arrayidx = getelementptr inbounds i8, ptr %p, i32 31 204 %0 = load i8, ptr %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(ptr %p) { 212entry: 213 %arrayidx = getelementptr inbounds i16, ptr %p, i32 31 214 %0 = load i16, ptr %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(ptr %p) { 222entry: 223 %arrayidx = getelementptr inbounds i32, ptr %p, i32 31 224 %0 = load i32, ptr %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(ptr %p, i32 %x) { 231entry: 232 %conv = trunc i32 %x to i8 233 %arrayidx = getelementptr inbounds i8, ptr %p, i32 31 234 store i8 %conv, ptr %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(ptr %p, i32 %x) { 241entry: 242 %conv = trunc i32 %x to i16 243 %arrayidx = getelementptr inbounds i16, ptr %p, i32 31 244 store i16 %conv, ptr %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(ptr %p, i32 %x) { 251entry: 252 %arrayidx = getelementptr inbounds i32, ptr %p, i32 31 253 store i32 %x, ptr %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(ptr %p) { 265entry: 266 %arrayidx = getelementptr inbounds i8, ptr %p, i32 32 267 %0 = load i8, ptr %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(ptr %p) { 277entry: 278 %arrayidx = getelementptr inbounds i16, ptr %p, i32 32 279 %0 = load i16, ptr %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(ptr %p) { 289entry: 290 %arrayidx = getelementptr inbounds i8, ptr %p, i32 32 291 %0 = load i8, ptr %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(ptr %p) { 301entry: 302 %arrayidx = getelementptr inbounds i16, ptr %p, i32 32 303 %0 = load i16, ptr %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(ptr %p) { 313entry: 314 %arrayidx = getelementptr inbounds i32, ptr %p, i32 32 315 %0 = load i32, ptr %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(ptr %p, i32 %x) { 324entry: 325 %conv = trunc i32 %x to i8 326 %arrayidx = getelementptr inbounds i8, ptr %p, i32 32 327 store i8 %conv, ptr %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(ptr %p, i32 %x) { 336entry: 337 %conv = trunc i32 %x to i16 338 %arrayidx = getelementptr inbounds i16, ptr %p, i32 32 339 store i16 %conv, ptr %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(ptr %p, i32 %x) { 348entry: 349 %arrayidx = getelementptr inbounds i32, ptr %p, i32 32 350 store i32 %x, ptr %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(ptr %p) { 362entry: 363 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095 364 %0 = load i8, ptr %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(ptr %p) { 374entry: 375 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095 376 %0 = load i16, ptr %add.ptr, align 2 377 %conv = sext i16 %0 to i32 378 ret i32 %conv 379} 380 381; CHECK-LABEL: ldrb_ri_t2_max 382; CHECK-T1: ldr r1, .LCP 383; CHECK-T1: ldrb r0, [r0, r1] 384; CHECK-T2: ldrb.w r0, [r0, #4095] 385define i32 @ldrb_ri_t2_max(ptr %p) { 386entry: 387 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095 388 %0 = load i8, ptr %add.ptr, align 1 389 %conv = zext i8 %0 to i32 390 ret i32 %conv 391} 392 393; CHECK-LABEL: ldrh_ri_t2_max 394; CHECK-T1: ldr r1, .LCP 395; CHECK-T1: ldrh r0, [r0, r1] 396; CHECK-T2: ldrh.w r0, [r0, #4095] 397define i32 @ldrh_ri_t2_max(ptr %p) { 398entry: 399 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095 400 %0 = load i16, ptr %add.ptr, align 2 401 %conv = zext i16 %0 to i32 402 ret i32 %conv 403} 404 405; CHECK-LABEL: ldr_ri_t2_max 406; CHECK-T1: ldr r1, .LCP 407; CHECK-T1: ldr r0, [r0, r1] 408; CHECK-T2: ldr.w r0, [r0, #4095] 409define i32 @ldr_ri_t2_max(ptr %p) { 410entry: 411 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095 412 %0 = load i32, ptr %add.ptr, align 4 413 ret i32 %0 414} 415 416; CHECK-LABEL: strb_ri_t2_max 417; CHECK-T1: ldr r2, .LCP 418; CHECK-T1: strb r1, [r0, r2] 419; CHECK-T2: strb.w r1, [r0, #4095] 420define void @strb_ri_t2_max(ptr %p, i32 %x) { 421entry: 422 %conv = trunc i32 %x to i8 423 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095 424 store i8 %conv, ptr %add.ptr, align 1 425 ret void 426} 427 428; CHECK-LABEL: strh_ri_t2_max 429; CHECK-T1: ldr r2, .LCP 430; CHECK-T1: strh r1, [r0, r2] 431; CHECK-T2: strh.w r1, [r0, #4095] 432define void @strh_ri_t2_max(ptr %p, i32 %x) { 433entry: 434 %conv = trunc i32 %x to i16 435 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095 436 store i16 %conv, ptr %add.ptr, align 2 437 ret void 438} 439 440; CHECK-LABEL: str_ri_t2_max 441; CHECK-T1: ldr r2, .LCP 442; CHECK-T1: str r1, [r0, r2] 443; CHECK-T2: str.w r1, [r0, #4095] 444define void @str_ri_t2_max(ptr %p, i32 %x) { 445entry: 446 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095 447 store i32 %x, ptr %add.ptr, align 4 448 ret void 449} 450 451 452; One past maximum Thumb-2 immediate offset 453 454; CHECK-LABEL: ldrsb_ri_t2_too_big 455; CHECK-T1: movs r1, #1 456; CHECK-T1: lsls r1, r1, #12 457; CHECK-T2: mov.w r1, #4096 458; CHECK: ldrsb r0, [r0, r1] 459define i32 @ldrsb_ri_t2_too_big(ptr %p) { 460entry: 461 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096 462 %0 = load i8, ptr %add.ptr, align 1 463 %conv = sext i8 %0 to i32 464 ret i32 %conv 465} 466 467; CHECK-LABEL: ldrsh_ri_t2_too_big 468; CHECK-T1: movs r1, #1 469; CHECK-T1: lsls r1, r1, #12 470; CHECK-T2: mov.w r1, #4096 471; CHECK: ldrsh r0, [r0, r1] 472define i32 @ldrsh_ri_t2_too_big(ptr %p) { 473entry: 474 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096 475 %0 = load i16, ptr %add.ptr, align 2 476 %conv = sext i16 %0 to i32 477 ret i32 %conv 478} 479 480; CHECK-LABEL: ldrb_ri_t2_too_big 481; CHECK-T1: movs r1, #1 482; CHECK-T1: lsls r1, r1, #12 483; CHECK-T2: mov.w r1, #4096 484; CHECK: ldrb r0, [r0, r1] 485define i32 @ldrb_ri_t2_too_big(ptr %p) { 486entry: 487 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096 488 %0 = load i8, ptr %add.ptr, align 1 489 %conv = zext i8 %0 to i32 490 ret i32 %conv 491} 492 493; CHECK-LABEL: ldrh_ri_t2_too_big 494; CHECK-T1: movs r1, #1 495; CHECK-T1: lsls r1, r1, #12 496; CHECK-T2: mov.w r1, #4096 497; CHECK: ldrh r0, [r0, r1] 498define i32 @ldrh_ri_t2_too_big(ptr %p) { 499entry: 500 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096 501 %0 = load i16, ptr %add.ptr, align 2 502 %conv = zext i16 %0 to i32 503 ret i32 %conv 504} 505 506; CHECK-LABEL: ldr_ri_t2_too_big 507; CHECK-T1: movs r1, #1 508; CHECK-T1: lsls r1, r1, #12 509; CHECK-T2: mov.w r1, #4096 510; CHECK: ldr r0, [r0, r1] 511define i32 @ldr_ri_t2_too_big(ptr %p) { 512entry: 513 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096 514 %0 = load i32, ptr %add.ptr, align 4 515 ret i32 %0 516} 517 518; CHECK-LABEL: strb_ri_t2_too_big 519; CHECK-T1: movs r2, #1 520; CHECK-T1: lsls r2, r2, #12 521; CHECK-T2: mov.w r2, #4096 522; CHECK: strb r1, [r0, r2] 523define void @strb_ri_t2_too_big(ptr %p, i32 %x) { 524entry: 525 %conv = trunc i32 %x to i8 526 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096 527 store i8 %conv, ptr %add.ptr, align 1 528 ret void 529} 530 531; CHECK-LABEL: strh_ri_t2_too_big 532; CHECK-T1: movs r2, #1 533; CHECK-T1: lsls r2, r2, #12 534; CHECK-T2: mov.w r2, #4096 535; CHECK: strh r1, [r0, r2] 536define void @strh_ri_t2_too_big(ptr %p, i32 %x) { 537entry: 538 %conv = trunc i32 %x to i16 539 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096 540 store i16 %conv, ptr %add.ptr, align 2 541 ret void 542} 543 544; CHECK-LABEL: str_ri_t2_too_big 545; CHECK-T1: movs r2, #1 546; CHECK-T1: lsls r2, r2, #12 547; CHECK-T2: mov.w r2, #4096 548; CHECK: str r1, [r0, r2] 549define void @str_ri_t2_too_big(ptr %p, i32 %x) { 550entry: 551 %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096 552 store i32 %x, ptr %add.ptr, align 4 553 ret void 554} 555 556 557; Negative offset 558 559define i32 @ldrsb_ri_negative(ptr %p) { 560; CHECK-T1-LABEL: ldrsb_ri_negative: 561; CHECK-T1: @ %bb.0: @ %entry 562; CHECK-T1-NEXT: movs r1, #0 563; CHECK-T1-NEXT: mvns r1, r1 564; CHECK-T1-NEXT: ldrsb r0, [r0, r1] 565; CHECK-T1-NEXT: bx lr 566; 567; CHECK-T2-LABEL: ldrsb_ri_negative: 568; CHECK-T2: @ %bb.0: @ %entry 569; CHECK-T2-NEXT: ldrsb r0, [r0, #-1] 570; CHECK-T2-NEXT: bx lr 571entry: 572 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1 573 %0 = load i8, ptr %add.ptr, align 1 574 %conv = sext i8 %0 to i32 575 ret i32 %conv 576} 577 578define i32 @ldrsh_ri_negative(ptr %p) { 579; CHECK-T1-LABEL: ldrsh_ri_negative: 580; CHECK-T1: @ %bb.0: @ %entry 581; CHECK-T1-NEXT: movs r1, #0 582; CHECK-T1-NEXT: mvns r1, r1 583; CHECK-T1-NEXT: ldrsh r0, [r0, r1] 584; CHECK-T1-NEXT: bx lr 585; 586; CHECK-T2-LABEL: ldrsh_ri_negative: 587; CHECK-T2: @ %bb.0: @ %entry 588; CHECK-T2-NEXT: ldrsh r0, [r0, #-1] 589; CHECK-T2-NEXT: bx lr 590entry: 591 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1 592 %0 = load i16, ptr %add.ptr, align 2 593 %conv = sext i16 %0 to i32 594 ret i32 %conv 595} 596 597define i32 @ldrb_ri_negative(ptr %p) { 598; CHECK-T1-LABEL: ldrb_ri_negative: 599; CHECK-T1: @ %bb.0: @ %entry 600; CHECK-T1-NEXT: subs r0, r0, #1 601; CHECK-T1-NEXT: ldrb r0, [r0] 602; CHECK-T1-NEXT: bx lr 603; 604; CHECK-T2-LABEL: ldrb_ri_negative: 605; CHECK-T2: @ %bb.0: @ %entry 606; CHECK-T2-NEXT: ldrb r0, [r0, #-1] 607; CHECK-T2-NEXT: bx lr 608entry: 609 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1 610 %0 = load i8, ptr %add.ptr, align 1 611 %conv = zext i8 %0 to i32 612 ret i32 %conv 613} 614 615define i32 @ldrh_ri_negative(ptr %p) { 616; CHECK-T1-LABEL: ldrh_ri_negative: 617; CHECK-T1: @ %bb.0: @ %entry 618; CHECK-T1-NEXT: subs r0, r0, #1 619; CHECK-T1-NEXT: ldrh r0, [r0] 620; CHECK-T1-NEXT: bx lr 621; 622; CHECK-T2-LABEL: ldrh_ri_negative: 623; CHECK-T2: @ %bb.0: @ %entry 624; CHECK-T2-NEXT: ldrh r0, [r0, #-1] 625; CHECK-T2-NEXT: bx lr 626entry: 627 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1 628 %0 = load i16, ptr %add.ptr, align 2 629 %conv = zext i16 %0 to i32 630 ret i32 %conv 631} 632 633define i32 @ldr_ri_negative(ptr %p) { 634; CHECK-T1-LABEL: ldr_ri_negative: 635; CHECK-T1: @ %bb.0: @ %entry 636; CHECK-T1-NEXT: subs r0, r0, #1 637; CHECK-T1-NEXT: ldr r0, [r0] 638; CHECK-T1-NEXT: bx lr 639; 640; CHECK-T2-LABEL: ldr_ri_negative: 641; CHECK-T2: @ %bb.0: @ %entry 642; CHECK-T2-NEXT: ldr r0, [r0, #-1] 643; CHECK-T2-NEXT: bx lr 644entry: 645 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1 646 %0 = load i32, ptr %add.ptr, align 4 647 ret i32 %0 648} 649 650define void @strb_ri_negative(ptr %p, i32 %x) { 651; CHECK-T1-LABEL: strb_ri_negative: 652; CHECK-T1: @ %bb.0: @ %entry 653; CHECK-T1-NEXT: subs r0, r0, #1 654; CHECK-T1-NEXT: strb r1, [r0] 655; CHECK-T1-NEXT: bx lr 656; 657; CHECK-T2-LABEL: strb_ri_negative: 658; CHECK-T2: @ %bb.0: @ %entry 659; CHECK-T2-NEXT: strb r1, [r0, #-1] 660; CHECK-T2-NEXT: bx lr 661entry: 662 %conv = trunc i32 %x to i8 663 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1 664 store i8 %conv, ptr %add.ptr, align 1 665 ret void 666} 667 668define void @strh_ri_negative(ptr %p, i32 %x) { 669; CHECK-T1-LABEL: strh_ri_negative: 670; CHECK-T1: @ %bb.0: @ %entry 671; CHECK-T1-NEXT: subs r0, r0, #1 672; CHECK-T1-NEXT: strh r1, [r0] 673; CHECK-T1-NEXT: bx lr 674; 675; CHECK-T2-LABEL: strh_ri_negative: 676; CHECK-T2: @ %bb.0: @ %entry 677; CHECK-T2-NEXT: strh r1, [r0, #-1] 678; CHECK-T2-NEXT: bx lr 679entry: 680 %conv = trunc i32 %x to i16 681 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1 682 store i16 %conv, ptr %add.ptr, align 2 683 ret void 684} 685 686define void @str_ri_negative(ptr %p, i32 %x) { 687; CHECK-T1-LABEL: str_ri_negative: 688; CHECK-T1: @ %bb.0: @ %entry 689; CHECK-T1-NEXT: subs r0, r0, #1 690; CHECK-T1-NEXT: str r1, [r0] 691; CHECK-T1-NEXT: bx lr 692; 693; CHECK-T2-LABEL: str_ri_negative: 694; CHECK-T2: @ %bb.0: @ %entry 695; CHECK-T2-NEXT: str r1, [r0, #-1] 696; CHECK-T2-NEXT: bx lr 697entry: 698 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1 699 store i32 %x, ptr %add.ptr, align 4 700 ret void 701} 702 703 704; Negative 255 offset 705 706define i32 @ldrsb_ri_negative255(ptr %p) { 707; CHECK-T1-LABEL: ldrsb_ri_negative255: 708; CHECK-T1: @ %bb.0: @ %entry 709; CHECK-T1-NEXT: movs r1, #254 710; CHECK-T1-NEXT: mvns r1, r1 711; CHECK-T1-NEXT: ldrsb r0, [r0, r1] 712; CHECK-T1-NEXT: bx lr 713; 714; CHECK-T2-LABEL: ldrsb_ri_negative255: 715; CHECK-T2: @ %bb.0: @ %entry 716; CHECK-T2-NEXT: ldrsb r0, [r0, #-255] 717; CHECK-T2-NEXT: bx lr 718entry: 719 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255 720 %0 = load i8, ptr %add.ptr, align 1 721 %conv = sext i8 %0 to i32 722 ret i32 %conv 723} 724 725define i32 @ldrsh_ri_negative255(ptr %p) { 726; CHECK-T1-LABEL: ldrsh_ri_negative255: 727; CHECK-T1: @ %bb.0: @ %entry 728; CHECK-T1-NEXT: movs r1, #254 729; CHECK-T1-NEXT: mvns r1, r1 730; CHECK-T1-NEXT: ldrsh r0, [r0, r1] 731; CHECK-T1-NEXT: bx lr 732; 733; CHECK-T2-LABEL: ldrsh_ri_negative255: 734; CHECK-T2: @ %bb.0: @ %entry 735; CHECK-T2-NEXT: ldrsh r0, [r0, #-255] 736; CHECK-T2-NEXT: bx lr 737entry: 738 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255 739 %0 = load i16, ptr %add.ptr, align 2 740 %conv = sext i16 %0 to i32 741 ret i32 %conv 742} 743 744define i32 @ldrb_ri_negative255(ptr %p) { 745; CHECK-T1-LABEL: ldrb_ri_negative255: 746; CHECK-T1: @ %bb.0: @ %entry 747; CHECK-T1-NEXT: subs r0, #255 748; CHECK-T1-NEXT: ldrb r0, [r0] 749; CHECK-T1-NEXT: bx lr 750; 751; CHECK-T2-LABEL: ldrb_ri_negative255: 752; CHECK-T2: @ %bb.0: @ %entry 753; CHECK-T2-NEXT: ldrb r0, [r0, #-255] 754; CHECK-T2-NEXT: bx lr 755entry: 756 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255 757 %0 = load i8, ptr %add.ptr, align 1 758 %conv = zext i8 %0 to i32 759 ret i32 %conv 760} 761 762define i32 @ldrh_ri_negative255(ptr %p) { 763; CHECK-T1-LABEL: ldrh_ri_negative255: 764; CHECK-T1: @ %bb.0: @ %entry 765; CHECK-T1-NEXT: subs r0, #255 766; CHECK-T1-NEXT: ldrh r0, [r0] 767; CHECK-T1-NEXT: bx lr 768; 769; CHECK-T2-LABEL: ldrh_ri_negative255: 770; CHECK-T2: @ %bb.0: @ %entry 771; CHECK-T2-NEXT: ldrh r0, [r0, #-255] 772; CHECK-T2-NEXT: bx lr 773entry: 774 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255 775 %0 = load i16, ptr %add.ptr, align 2 776 %conv = zext i16 %0 to i32 777 ret i32 %conv 778} 779 780define i32 @ldr_ri_negative255(ptr %p) { 781; CHECK-T1-LABEL: ldr_ri_negative255: 782; CHECK-T1: @ %bb.0: @ %entry 783; CHECK-T1-NEXT: subs r0, #255 784; CHECK-T1-NEXT: ldr r0, [r0] 785; CHECK-T1-NEXT: bx lr 786; 787; CHECK-T2-LABEL: ldr_ri_negative255: 788; CHECK-T2: @ %bb.0: @ %entry 789; CHECK-T2-NEXT: ldr r0, [r0, #-255] 790; CHECK-T2-NEXT: bx lr 791entry: 792 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255 793 %0 = load i32, ptr %add.ptr, align 4 794 ret i32 %0 795} 796 797define void @strb_ri_negative255(ptr %p, i32 %x) { 798; CHECK-T1-LABEL: strb_ri_negative255: 799; CHECK-T1: @ %bb.0: @ %entry 800; CHECK-T1-NEXT: subs r0, #255 801; CHECK-T1-NEXT: strb r1, [r0] 802; CHECK-T1-NEXT: bx lr 803; 804; CHECK-T2-LABEL: strb_ri_negative255: 805; CHECK-T2: @ %bb.0: @ %entry 806; CHECK-T2-NEXT: strb r1, [r0, #-255] 807; CHECK-T2-NEXT: bx lr 808entry: 809 %conv = trunc i32 %x to i8 810 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255 811 store i8 %conv, ptr %add.ptr, align 1 812 ret void 813} 814 815define void @strh_ri_negative255(ptr %p, i32 %x) { 816; CHECK-T1-LABEL: strh_ri_negative255: 817; CHECK-T1: @ %bb.0: @ %entry 818; CHECK-T1-NEXT: subs r0, #255 819; CHECK-T1-NEXT: strh r1, [r0] 820; CHECK-T1-NEXT: bx lr 821; 822; CHECK-T2-LABEL: strh_ri_negative255: 823; CHECK-T2: @ %bb.0: @ %entry 824; CHECK-T2-NEXT: strh r1, [r0, #-255] 825; CHECK-T2-NEXT: bx lr 826entry: 827 %conv = trunc i32 %x to i16 828 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255 829 store i16 %conv, ptr %add.ptr, align 2 830 ret void 831} 832 833define void @str_ri_negative255(ptr %p, i32 %x) { 834; CHECK-T1-LABEL: str_ri_negative255: 835; CHECK-T1: @ %bb.0: @ %entry 836; CHECK-T1-NEXT: subs r0, #255 837; CHECK-T1-NEXT: str r1, [r0] 838; CHECK-T1-NEXT: bx lr 839; 840; CHECK-T2-LABEL: str_ri_negative255: 841; CHECK-T2: @ %bb.0: @ %entry 842; CHECK-T2-NEXT: str r1, [r0, #-255] 843; CHECK-T2-NEXT: bx lr 844entry: 845 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255 846 store i32 %x, ptr %add.ptr, align 4 847 ret void 848} 849 850 851; Negative 256 offset 852 853define i32 @ldrsb_ri_negative256(ptr %p) { 854; CHECK-T1-LABEL: ldrsb_ri_negative256: 855; CHECK-T1: @ %bb.0: @ %entry 856; CHECK-T1-NEXT: movs r1, #255 857; CHECK-T1-NEXT: mvns r1, r1 858; CHECK-T1-NEXT: ldrsb r0, [r0, r1] 859; CHECK-T1-NEXT: bx lr 860; 861; CHECK-T2-LABEL: ldrsb_ri_negative256: 862; CHECK-T2: @ %bb.0: @ %entry 863; CHECK-T2-NEXT: mvn r1, #255 864; CHECK-T2-NEXT: ldrsb r0, [r0, r1] 865; CHECK-T2-NEXT: bx lr 866entry: 867 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256 868 %0 = load i8, ptr %add.ptr, align 1 869 %conv = sext i8 %0 to i32 870 ret i32 %conv 871} 872 873define i32 @ldrsh_ri_negative256(ptr %p) { 874; CHECK-T1-LABEL: ldrsh_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: ldrsh r0, [r0, r1] 879; CHECK-T1-NEXT: bx lr 880; 881; CHECK-T2-LABEL: ldrsh_ri_negative256: 882; CHECK-T2: @ %bb.0: @ %entry 883; CHECK-T2-NEXT: mvn r1, #255 884; CHECK-T2-NEXT: ldrsh r0, [r0, r1] 885; CHECK-T2-NEXT: bx lr 886entry: 887 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256 888 %0 = load i16, ptr %add.ptr, align 2 889 %conv = sext i16 %0 to i32 890 ret i32 %conv 891} 892 893define i32 @ldrb_ri_negative256(ptr %p) { 894; CHECK-T1-LABEL: ldrb_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: ldrb r0, [r0, r1] 899; CHECK-T1-NEXT: bx lr 900; 901; CHECK-T2-LABEL: ldrb_ri_negative256: 902; CHECK-T2: @ %bb.0: @ %entry 903; CHECK-T2-NEXT: mvn r1, #255 904; CHECK-T2-NEXT: ldrb r0, [r0, r1] 905; CHECK-T2-NEXT: bx lr 906entry: 907 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256 908 %0 = load i8, ptr %add.ptr, align 1 909 %conv = zext i8 %0 to i32 910 ret i32 %conv 911} 912 913define i32 @ldrh_ri_negative256(ptr %p) { 914; CHECK-T1-LABEL: ldrh_ri_negative256: 915; CHECK-T1: @ %bb.0: @ %entry 916; CHECK-T1-NEXT: movs r1, #255 917; CHECK-T1-NEXT: mvns r1, r1 918; CHECK-T1-NEXT: ldrh r0, [r0, r1] 919; CHECK-T1-NEXT: bx lr 920; 921; CHECK-T2-LABEL: ldrh_ri_negative256: 922; CHECK-T2: @ %bb.0: @ %entry 923; CHECK-T2-NEXT: mvn r1, #255 924; CHECK-T2-NEXT: ldrh r0, [r0, r1] 925; CHECK-T2-NEXT: bx lr 926entry: 927 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256 928 %0 = load i16, ptr %add.ptr, align 2 929 %conv = zext i16 %0 to i32 930 ret i32 %conv 931} 932 933define i32 @ldr_ri_negative256(ptr %p) { 934; CHECK-T1-LABEL: ldr_ri_negative256: 935; CHECK-T1: @ %bb.0: @ %entry 936; CHECK-T1-NEXT: movs r1, #255 937; CHECK-T1-NEXT: mvns r1, r1 938; CHECK-T1-NEXT: ldr r0, [r0, r1] 939; CHECK-T1-NEXT: bx lr 940; 941; CHECK-T2-LABEL: ldr_ri_negative256: 942; CHECK-T2: @ %bb.0: @ %entry 943; CHECK-T2-NEXT: mvn r1, #255 944; CHECK-T2-NEXT: ldr r0, [r0, r1] 945; CHECK-T2-NEXT: bx lr 946entry: 947 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256 948 %0 = load i32, ptr %add.ptr, align 4 949 ret i32 %0 950} 951 952define void @strb_ri_negative256(ptr %p, i32 %x) { 953; CHECK-T1-LABEL: strb_ri_negative256: 954; CHECK-T1: @ %bb.0: @ %entry 955; CHECK-T1-NEXT: movs r2, #255 956; CHECK-T1-NEXT: mvns r2, r2 957; CHECK-T1-NEXT: strb r1, [r0, r2] 958; CHECK-T1-NEXT: bx lr 959; 960; CHECK-T2-LABEL: strb_ri_negative256: 961; CHECK-T2: @ %bb.0: @ %entry 962; CHECK-T2-NEXT: mvn r2, #255 963; CHECK-T2-NEXT: strb r1, [r0, r2] 964; CHECK-T2-NEXT: bx lr 965entry: 966 %conv = trunc i32 %x to i8 967 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256 968 store i8 %conv, ptr %add.ptr, align 1 969 ret void 970} 971 972define void @strh_ri_negative256(ptr %p, i32 %x) { 973; CHECK-T1-LABEL: strh_ri_negative256: 974; CHECK-T1: @ %bb.0: @ %entry 975; CHECK-T1-NEXT: movs r2, #255 976; CHECK-T1-NEXT: mvns r2, r2 977; CHECK-T1-NEXT: strh r1, [r0, r2] 978; CHECK-T1-NEXT: bx lr 979; 980; CHECK-T2-LABEL: strh_ri_negative256: 981; CHECK-T2: @ %bb.0: @ %entry 982; CHECK-T2-NEXT: mvn r2, #255 983; CHECK-T2-NEXT: strh r1, [r0, r2] 984; CHECK-T2-NEXT: bx lr 985entry: 986 %conv = trunc i32 %x to i16 987 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256 988 store i16 %conv, ptr %add.ptr, align 2 989 ret void 990} 991 992define void @str_ri_negative256(ptr %p, i32 %x) { 993; CHECK-T1-LABEL: str_ri_negative256: 994; CHECK-T1: @ %bb.0: @ %entry 995; CHECK-T1-NEXT: movs r2, #255 996; CHECK-T1-NEXT: mvns r2, r2 997; CHECK-T1-NEXT: str r1, [r0, r2] 998; CHECK-T1-NEXT: bx lr 999; 1000; CHECK-T2-LABEL: str_ri_negative256: 1001; CHECK-T2: @ %bb.0: @ %entry 1002; CHECK-T2-NEXT: mvn r2, #255 1003; CHECK-T2-NEXT: str r1, [r0, r2] 1004; CHECK-T2-NEXT: bx lr 1005entry: 1006 %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256 1007 store i32 %x, ptr %add.ptr, align 4 1008 ret void 1009} 1010