1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ 3; RUN: | FileCheck -check-prefix=RV32I %s 4; RUN: llc -mtriple=riscv32 -verify-machineinstrs -code-model=medium < %s \ 5; RUN: | FileCheck -check-prefix=RV32I-MEDIUM %s 6; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ 7; RUN: | FileCheck -check-prefix=RV64I %s 8; RUN: llc -mtriple=riscv64 -verify-machineinstrs -code-model=medium < %s \ 9; RUN: | FileCheck -check-prefix=RV64I-MEDIUM %s 10; RUN: llc -mtriple=riscv64 -verify-machineinstrs -code-model=large < %s \ 11; RUN: | FileCheck -check-prefix=RV64I-LARGE %s 12 13; We can often fold an ADDI into the offset of load/store instructions: 14; (load (addi base, off1), off2) -> (load base, off1+off2) 15; (store val, (addi base, off1), off2) -> (store val, base, off1+off2) 16; This is possible when the off1+off2 continues to fit the 12-bit immediate. 17; Check if we do the fold under various conditions. If off1 is (the low part of) 18; an address the fold's safety depends on the variable's alignment. 19 20@g_0 = dso_local global i64 0 21@g_1 = dso_local global i64 0, align 1 22@g_2 = dso_local global i64 0, align 2 23@g_4 = dso_local global i64 0, align 4 24@g_8 = dso_local global i64 0, align 8 25@g_16 = dso_local global i64 0, align 16 26 27define dso_local i64 @load_g_0() nounwind { 28; RV32I-LABEL: load_g_0: 29; RV32I: # %bb.0: # %entry 30; RV32I-NEXT: lui a1, %hi(g_0) 31; RV32I-NEXT: lw a0, %lo(g_0)(a1) 32; RV32I-NEXT: lw a1, %lo(g_0+4)(a1) 33; RV32I-NEXT: ret 34; 35; RV32I-MEDIUM-LABEL: load_g_0: 36; RV32I-MEDIUM: # %bb.0: # %entry 37; RV32I-MEDIUM-NEXT: .Lpcrel_hi0: 38; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_0) 39; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi0) 40; RV32I-MEDIUM-NEXT: lw a0, 0(a1) 41; RV32I-MEDIUM-NEXT: lw a1, 4(a1) 42; RV32I-MEDIUM-NEXT: ret 43; 44; RV64I-LABEL: load_g_0: 45; RV64I: # %bb.0: # %entry 46; RV64I-NEXT: lui a0, %hi(g_0) 47; RV64I-NEXT: ld a0, %lo(g_0)(a0) 48; RV64I-NEXT: ret 49; 50; RV64I-MEDIUM-LABEL: load_g_0: 51; RV64I-MEDIUM: # %bb.0: # %entry 52; RV64I-MEDIUM-NEXT: .Lpcrel_hi0: 53; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_0) 54; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi0)(a0) 55; RV64I-MEDIUM-NEXT: ret 56; 57; RV64I-LARGE-LABEL: load_g_0: 58; RV64I-LARGE: # %bb.0: # %entry 59; RV64I-LARGE-NEXT: .Lpcrel_hi0: 60; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI0_0) 61; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi0)(a0) 62; RV64I-LARGE-NEXT: ld a0, 0(a0) 63; RV64I-LARGE-NEXT: ret 64entry: 65 %0 = load i64, ptr @g_0 66 ret i64 %0 67} 68 69define dso_local i64 @load_g_1() nounwind { 70; RV32I-LABEL: load_g_1: 71; RV32I: # %bb.0: # %entry 72; RV32I-NEXT: lui a1, %hi(g_1) 73; RV32I-NEXT: lw a0, %lo(g_1)(a1) 74; RV32I-NEXT: addi a1, a1, %lo(g_1) 75; RV32I-NEXT: lw a1, 4(a1) 76; RV32I-NEXT: ret 77; 78; RV32I-MEDIUM-LABEL: load_g_1: 79; RV32I-MEDIUM: # %bb.0: # %entry 80; RV32I-MEDIUM-NEXT: .Lpcrel_hi1: 81; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_1) 82; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi1) 83; RV32I-MEDIUM-NEXT: lw a0, 0(a1) 84; RV32I-MEDIUM-NEXT: lw a1, 4(a1) 85; RV32I-MEDIUM-NEXT: ret 86; 87; RV64I-LABEL: load_g_1: 88; RV64I: # %bb.0: # %entry 89; RV64I-NEXT: lui a0, %hi(g_1) 90; RV64I-NEXT: ld a0, %lo(g_1)(a0) 91; RV64I-NEXT: ret 92; 93; RV64I-MEDIUM-LABEL: load_g_1: 94; RV64I-MEDIUM: # %bb.0: # %entry 95; RV64I-MEDIUM-NEXT: .Lpcrel_hi1: 96; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_1) 97; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi1)(a0) 98; RV64I-MEDIUM-NEXT: ret 99; 100; RV64I-LARGE-LABEL: load_g_1: 101; RV64I-LARGE: # %bb.0: # %entry 102; RV64I-LARGE-NEXT: .Lpcrel_hi1: 103; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI1_0) 104; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi1)(a0) 105; RV64I-LARGE-NEXT: ld a0, 0(a0) 106; RV64I-LARGE-NEXT: ret 107entry: 108 %0 = load i64, ptr @g_1 109 ret i64 %0 110} 111 112define dso_local i64 @load_g_2() nounwind { 113; RV32I-LABEL: load_g_2: 114; RV32I: # %bb.0: # %entry 115; RV32I-NEXT: lui a1, %hi(g_2) 116; RV32I-NEXT: lw a0, %lo(g_2)(a1) 117; RV32I-NEXT: addi a1, a1, %lo(g_2) 118; RV32I-NEXT: lw a1, 4(a1) 119; RV32I-NEXT: ret 120; 121; RV32I-MEDIUM-LABEL: load_g_2: 122; RV32I-MEDIUM: # %bb.0: # %entry 123; RV32I-MEDIUM-NEXT: .Lpcrel_hi2: 124; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_2) 125; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi2) 126; RV32I-MEDIUM-NEXT: lw a0, 0(a1) 127; RV32I-MEDIUM-NEXT: lw a1, 4(a1) 128; RV32I-MEDIUM-NEXT: ret 129; 130; RV64I-LABEL: load_g_2: 131; RV64I: # %bb.0: # %entry 132; RV64I-NEXT: lui a0, %hi(g_2) 133; RV64I-NEXT: ld a0, %lo(g_2)(a0) 134; RV64I-NEXT: ret 135; 136; RV64I-MEDIUM-LABEL: load_g_2: 137; RV64I-MEDIUM: # %bb.0: # %entry 138; RV64I-MEDIUM-NEXT: .Lpcrel_hi2: 139; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_2) 140; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi2)(a0) 141; RV64I-MEDIUM-NEXT: ret 142; 143; RV64I-LARGE-LABEL: load_g_2: 144; RV64I-LARGE: # %bb.0: # %entry 145; RV64I-LARGE-NEXT: .Lpcrel_hi2: 146; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI2_0) 147; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi2)(a0) 148; RV64I-LARGE-NEXT: ld a0, 0(a0) 149; RV64I-LARGE-NEXT: ret 150entry: 151 %0 = load i64, ptr @g_2 152 ret i64 %0 153} 154 155define dso_local i64 @load_g_4() nounwind { 156; RV32I-LABEL: load_g_4: 157; RV32I: # %bb.0: # %entry 158; RV32I-NEXT: lui a1, %hi(g_4) 159; RV32I-NEXT: lw a0, %lo(g_4)(a1) 160; RV32I-NEXT: addi a1, a1, %lo(g_4) 161; RV32I-NEXT: lw a1, 4(a1) 162; RV32I-NEXT: ret 163; 164; RV32I-MEDIUM-LABEL: load_g_4: 165; RV32I-MEDIUM: # %bb.0: # %entry 166; RV32I-MEDIUM-NEXT: .Lpcrel_hi3: 167; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4) 168; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi3) 169; RV32I-MEDIUM-NEXT: lw a0, 0(a1) 170; RV32I-MEDIUM-NEXT: lw a1, 4(a1) 171; RV32I-MEDIUM-NEXT: ret 172; 173; RV64I-LABEL: load_g_4: 174; RV64I: # %bb.0: # %entry 175; RV64I-NEXT: lui a0, %hi(g_4) 176; RV64I-NEXT: ld a0, %lo(g_4)(a0) 177; RV64I-NEXT: ret 178; 179; RV64I-MEDIUM-LABEL: load_g_4: 180; RV64I-MEDIUM: # %bb.0: # %entry 181; RV64I-MEDIUM-NEXT: .Lpcrel_hi3: 182; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4) 183; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi3)(a0) 184; RV64I-MEDIUM-NEXT: ret 185; 186; RV64I-LARGE-LABEL: load_g_4: 187; RV64I-LARGE: # %bb.0: # %entry 188; RV64I-LARGE-NEXT: .Lpcrel_hi3: 189; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI3_0) 190; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi3)(a0) 191; RV64I-LARGE-NEXT: ld a0, 0(a0) 192; RV64I-LARGE-NEXT: ret 193entry: 194 %0 = load i64, ptr @g_4 195 ret i64 %0 196} 197 198define dso_local i64 @load_g_8() nounwind { 199; RV32I-LABEL: load_g_8: 200; RV32I: # %bb.0: # %entry 201; RV32I-NEXT: lui a1, %hi(g_8) 202; RV32I-NEXT: lw a0, %lo(g_8)(a1) 203; RV32I-NEXT: lw a1, %lo(g_8+4)(a1) 204; RV32I-NEXT: ret 205; 206; RV32I-MEDIUM-LABEL: load_g_8: 207; RV32I-MEDIUM: # %bb.0: # %entry 208; RV32I-MEDIUM-NEXT: .Lpcrel_hi4: 209; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_8) 210; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi4) 211; RV32I-MEDIUM-NEXT: lw a0, 0(a1) 212; RV32I-MEDIUM-NEXT: lw a1, 4(a1) 213; RV32I-MEDIUM-NEXT: ret 214; 215; RV64I-LABEL: load_g_8: 216; RV64I: # %bb.0: # %entry 217; RV64I-NEXT: lui a0, %hi(g_8) 218; RV64I-NEXT: ld a0, %lo(g_8)(a0) 219; RV64I-NEXT: ret 220; 221; RV64I-MEDIUM-LABEL: load_g_8: 222; RV64I-MEDIUM: # %bb.0: # %entry 223; RV64I-MEDIUM-NEXT: .Lpcrel_hi4: 224; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_8) 225; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi4)(a0) 226; RV64I-MEDIUM-NEXT: ret 227; 228; RV64I-LARGE-LABEL: load_g_8: 229; RV64I-LARGE: # %bb.0: # %entry 230; RV64I-LARGE-NEXT: .Lpcrel_hi4: 231; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI4_0) 232; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi4)(a0) 233; RV64I-LARGE-NEXT: ld a0, 0(a0) 234; RV64I-LARGE-NEXT: ret 235entry: 236 %0 = load i64, ptr @g_8 237 ret i64 %0 238} 239 240define dso_local i64 @load_g_16() nounwind { 241; RV32I-LABEL: load_g_16: 242; RV32I: # %bb.0: # %entry 243; RV32I-NEXT: lui a1, %hi(g_16) 244; RV32I-NEXT: lw a0, %lo(g_16)(a1) 245; RV32I-NEXT: lw a1, %lo(g_16+4)(a1) 246; RV32I-NEXT: ret 247; 248; RV32I-MEDIUM-LABEL: load_g_16: 249; RV32I-MEDIUM: # %bb.0: # %entry 250; RV32I-MEDIUM-NEXT: .Lpcrel_hi5: 251; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_16) 252; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi5) 253; RV32I-MEDIUM-NEXT: lw a0, 0(a1) 254; RV32I-MEDIUM-NEXT: lw a1, 4(a1) 255; RV32I-MEDIUM-NEXT: ret 256; 257; RV64I-LABEL: load_g_16: 258; RV64I: # %bb.0: # %entry 259; RV64I-NEXT: lui a0, %hi(g_16) 260; RV64I-NEXT: ld a0, %lo(g_16)(a0) 261; RV64I-NEXT: ret 262; 263; RV64I-MEDIUM-LABEL: load_g_16: 264; RV64I-MEDIUM: # %bb.0: # %entry 265; RV64I-MEDIUM-NEXT: .Lpcrel_hi5: 266; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_16) 267; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi5)(a0) 268; RV64I-MEDIUM-NEXT: ret 269; 270; RV64I-LARGE-LABEL: load_g_16: 271; RV64I-LARGE: # %bb.0: # %entry 272; RV64I-LARGE-NEXT: .Lpcrel_hi5: 273; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI5_0) 274; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi5)(a0) 275; RV64I-LARGE-NEXT: ld a0, 0(a0) 276; RV64I-LARGE-NEXT: ret 277entry: 278 %0 = load i64, ptr @g_16 279 ret i64 %0 280} 281 282define dso_local void @store_g_4() nounwind { 283; RV32I-LABEL: store_g_4: 284; RV32I: # %bb.0: # %entry 285; RV32I-NEXT: lui a0, %hi(g_4) 286; RV32I-NEXT: sw zero, %lo(g_4)(a0) 287; RV32I-NEXT: addi a0, a0, %lo(g_4) 288; RV32I-NEXT: sw zero, 4(a0) 289; RV32I-NEXT: ret 290; 291; RV32I-MEDIUM-LABEL: store_g_4: 292; RV32I-MEDIUM: # %bb.0: # %entry 293; RV32I-MEDIUM-NEXT: .Lpcrel_hi6: 294; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4) 295; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi6) 296; RV32I-MEDIUM-NEXT: sw zero, 0(a0) 297; RV32I-MEDIUM-NEXT: sw zero, 4(a0) 298; RV32I-MEDIUM-NEXT: ret 299; 300; RV64I-LABEL: store_g_4: 301; RV64I: # %bb.0: # %entry 302; RV64I-NEXT: lui a0, %hi(g_4) 303; RV64I-NEXT: sd zero, %lo(g_4)(a0) 304; RV64I-NEXT: ret 305; 306; RV64I-MEDIUM-LABEL: store_g_4: 307; RV64I-MEDIUM: # %bb.0: # %entry 308; RV64I-MEDIUM-NEXT: .Lpcrel_hi6: 309; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4) 310; RV64I-MEDIUM-NEXT: sd zero, %pcrel_lo(.Lpcrel_hi6)(a0) 311; RV64I-MEDIUM-NEXT: ret 312; 313; RV64I-LARGE-LABEL: store_g_4: 314; RV64I-LARGE: # %bb.0: # %entry 315; RV64I-LARGE-NEXT: .Lpcrel_hi6: 316; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI6_0) 317; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi6)(a0) 318; RV64I-LARGE-NEXT: sd zero, 0(a0) 319; RV64I-LARGE-NEXT: ret 320entry: 321 store i64 0, ptr @g_4 322 ret void 323} 324 325define dso_local void @store_g_8() nounwind { 326; RV32I-LABEL: store_g_8: 327; RV32I: # %bb.0: # %entry 328; RV32I-NEXT: lui a0, %hi(g_8) 329; RV32I-NEXT: sw zero, %lo(g_8+4)(a0) 330; RV32I-NEXT: sw zero, %lo(g_8)(a0) 331; RV32I-NEXT: ret 332; 333; RV32I-MEDIUM-LABEL: store_g_8: 334; RV32I-MEDIUM: # %bb.0: # %entry 335; RV32I-MEDIUM-NEXT: .Lpcrel_hi7: 336; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_8) 337; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi7) 338; RV32I-MEDIUM-NEXT: sw zero, 0(a0) 339; RV32I-MEDIUM-NEXT: sw zero, 4(a0) 340; RV32I-MEDIUM-NEXT: ret 341; 342; RV64I-LABEL: store_g_8: 343; RV64I: # %bb.0: # %entry 344; RV64I-NEXT: lui a0, %hi(g_8) 345; RV64I-NEXT: sd zero, %lo(g_8)(a0) 346; RV64I-NEXT: ret 347; 348; RV64I-MEDIUM-LABEL: store_g_8: 349; RV64I-MEDIUM: # %bb.0: # %entry 350; RV64I-MEDIUM-NEXT: .Lpcrel_hi7: 351; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_8) 352; RV64I-MEDIUM-NEXT: sd zero, %pcrel_lo(.Lpcrel_hi7)(a0) 353; RV64I-MEDIUM-NEXT: ret 354; 355; RV64I-LARGE-LABEL: store_g_8: 356; RV64I-LARGE: # %bb.0: # %entry 357; RV64I-LARGE-NEXT: .Lpcrel_hi7: 358; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI7_0) 359; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi7)(a0) 360; RV64I-LARGE-NEXT: sd zero, 0(a0) 361; RV64I-LARGE-NEXT: ret 362entry: 363 store i64 0, ptr @g_8 364 ret void 365} 366 367; Check if we can fold ADDI into the offset of store instructions, 368; when store instructions is the root node in DAG. 369 370@g_4_i32 = global i32 0, align 4 371 372define dso_local void @inc_g_i32() nounwind { 373; RV32I-LABEL: inc_g_i32: 374; RV32I: # %bb.0: # %entry 375; RV32I-NEXT: lui a0, %hi(g_4_i32) 376; RV32I-NEXT: lw a1, %lo(g_4_i32)(a0) 377; RV32I-NEXT: addi a1, a1, 1 378; RV32I-NEXT: sw a1, %lo(g_4_i32)(a0) 379; RV32I-NEXT: ret 380; 381; RV32I-MEDIUM-LABEL: inc_g_i32: 382; RV32I-MEDIUM: # %bb.0: # %entry 383; RV32I-MEDIUM-NEXT: .Lpcrel_hi8: 384; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4_i32) 385; RV32I-MEDIUM-NEXT: lw a1, %pcrel_lo(.Lpcrel_hi8)(a0) 386; RV32I-MEDIUM-NEXT: addi a1, a1, 1 387; RV32I-MEDIUM-NEXT: sw a1, %pcrel_lo(.Lpcrel_hi8)(a0) 388; RV32I-MEDIUM-NEXT: ret 389; 390; RV64I-LABEL: inc_g_i32: 391; RV64I: # %bb.0: # %entry 392; RV64I-NEXT: lui a0, %hi(g_4_i32) 393; RV64I-NEXT: lw a1, %lo(g_4_i32)(a0) 394; RV64I-NEXT: addi a1, a1, 1 395; RV64I-NEXT: sw a1, %lo(g_4_i32)(a0) 396; RV64I-NEXT: ret 397; 398; RV64I-MEDIUM-LABEL: inc_g_i32: 399; RV64I-MEDIUM: # %bb.0: # %entry 400; RV64I-MEDIUM-NEXT: .Lpcrel_hi8: 401; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4_i32) 402; RV64I-MEDIUM-NEXT: lw a1, %pcrel_lo(.Lpcrel_hi8)(a0) 403; RV64I-MEDIUM-NEXT: addi a1, a1, 1 404; RV64I-MEDIUM-NEXT: sw a1, %pcrel_lo(.Lpcrel_hi8)(a0) 405; RV64I-MEDIUM-NEXT: ret 406; 407; RV64I-LARGE-LABEL: inc_g_i32: 408; RV64I-LARGE: # %bb.0: # %entry 409; RV64I-LARGE-NEXT: .Lpcrel_hi8: 410; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI8_0) 411; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi8)(a0) 412; RV64I-LARGE-NEXT: lw a1, 0(a0) 413; RV64I-LARGE-NEXT: addi a1, a1, 1 414; RV64I-LARGE-NEXT: sw a1, 0(a0) 415; RV64I-LARGE-NEXT: ret 416entry: 417 %0 = load i32, ptr @g_4_i32 418 %inc = add i32 %0, 1 419 store i32 %inc, ptr @g_4_i32 420 br label %if.end 421 422if.end: 423 ret void 424} 425 426; Check for folds in accesses to elements of an i32 array. 427 428@ga = dso_local local_unnamed_addr global [2 x i32] zeroinitializer, align 4 429 430define dso_local i32 @load_ga() local_unnamed_addr #0 { 431; RV32I-LABEL: load_ga: 432; RV32I: # %bb.0: 433; RV32I-NEXT: lui a0, %hi(ga+4) 434; RV32I-NEXT: lw a0, %lo(ga+4)(a0) 435; RV32I-NEXT: ret 436; 437; RV32I-MEDIUM-LABEL: load_ga: 438; RV32I-MEDIUM: # %bb.0: 439; RV32I-MEDIUM-NEXT: .Lpcrel_hi9: 440; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ga+4) 441; RV32I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi9)(a0) 442; RV32I-MEDIUM-NEXT: ret 443; 444; RV64I-LABEL: load_ga: 445; RV64I: # %bb.0: 446; RV64I-NEXT: lui a0, %hi(ga+4) 447; RV64I-NEXT: lw a0, %lo(ga+4)(a0) 448; RV64I-NEXT: ret 449; 450; RV64I-MEDIUM-LABEL: load_ga: 451; RV64I-MEDIUM: # %bb.0: 452; RV64I-MEDIUM-NEXT: .Lpcrel_hi9: 453; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ga+4) 454; RV64I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi9)(a0) 455; RV64I-MEDIUM-NEXT: ret 456; 457; RV64I-LARGE-LABEL: load_ga: 458; RV64I-LARGE: # %bb.0: 459; RV64I-LARGE-NEXT: .Lpcrel_hi9: 460; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI9_0) 461; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi9)(a0) 462; RV64I-LARGE-NEXT: lw a0, 4(a0) 463; RV64I-LARGE-NEXT: ret 464 %1 = load i32, ptr getelementptr inbounds ([2 x i32], ptr @ga, i32 0, i32 1), align 4 465 ret i32 %1 466} 467 468; Check for folds in accesses to the second element of an i64 array. 469 470@ga_8 = dso_local local_unnamed_addr global [2 x i64] zeroinitializer, align 8 471@ga_16 = dso_local local_unnamed_addr global [2 x i64] zeroinitializer, align 16 472 473define dso_local i64 @load_ga_8() nounwind { 474; RV32I-LABEL: load_ga_8: 475; RV32I: # %bb.0: # %entry 476; RV32I-NEXT: lui a1, %hi(ga_8) 477; RV32I-NEXT: addi a1, a1, %lo(ga_8) 478; RV32I-NEXT: lw a0, 8(a1) 479; RV32I-NEXT: lw a1, 12(a1) 480; RV32I-NEXT: ret 481; 482; RV32I-MEDIUM-LABEL: load_ga_8: 483; RV32I-MEDIUM: # %bb.0: # %entry 484; RV32I-MEDIUM-NEXT: .Lpcrel_hi10: 485; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ga_8) 486; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi10) 487; RV32I-MEDIUM-NEXT: lw a0, 8(a1) 488; RV32I-MEDIUM-NEXT: lw a1, 12(a1) 489; RV32I-MEDIUM-NEXT: ret 490; 491; RV64I-LABEL: load_ga_8: 492; RV64I: # %bb.0: # %entry 493; RV64I-NEXT: lui a0, %hi(ga_8+8) 494; RV64I-NEXT: ld a0, %lo(ga_8+8)(a0) 495; RV64I-NEXT: ret 496; 497; RV64I-MEDIUM-LABEL: load_ga_8: 498; RV64I-MEDIUM: # %bb.0: # %entry 499; RV64I-MEDIUM-NEXT: .Lpcrel_hi10: 500; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ga_8+8) 501; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi10)(a0) 502; RV64I-MEDIUM-NEXT: ret 503; 504; RV64I-LARGE-LABEL: load_ga_8: 505; RV64I-LARGE: # %bb.0: # %entry 506; RV64I-LARGE-NEXT: .Lpcrel_hi10: 507; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI10_0) 508; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi10)(a0) 509; RV64I-LARGE-NEXT: ld a0, 8(a0) 510; RV64I-LARGE-NEXT: ret 511entry: 512 %0 = load i64, ptr getelementptr inbounds ([2 x i64], ptr @ga_8, i32 0, i32 1) 513 ret i64 %0 514} 515 516define dso_local i64 @load_ga_16() nounwind { 517; RV32I-LABEL: load_ga_16: 518; RV32I: # %bb.0: # %entry 519; RV32I-NEXT: lui a1, %hi(ga_16) 520; RV32I-NEXT: lw a0, %lo(ga_16+8)(a1) 521; RV32I-NEXT: lw a1, %lo(ga_16+12)(a1) 522; RV32I-NEXT: ret 523; 524; RV32I-MEDIUM-LABEL: load_ga_16: 525; RV32I-MEDIUM: # %bb.0: # %entry 526; RV32I-MEDIUM-NEXT: .Lpcrel_hi11: 527; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ga_16) 528; RV32I-MEDIUM-NEXT: addi a1, a0, %pcrel_lo(.Lpcrel_hi11) 529; RV32I-MEDIUM-NEXT: lw a0, 8(a1) 530; RV32I-MEDIUM-NEXT: lw a1, 12(a1) 531; RV32I-MEDIUM-NEXT: ret 532; 533; RV64I-LABEL: load_ga_16: 534; RV64I: # %bb.0: # %entry 535; RV64I-NEXT: lui a0, %hi(ga_16) 536; RV64I-NEXT: ld a0, %lo(ga_16+8)(a0) 537; RV64I-NEXT: ret 538; 539; RV64I-MEDIUM-LABEL: load_ga_16: 540; RV64I-MEDIUM: # %bb.0: # %entry 541; RV64I-MEDIUM-NEXT: .Lpcrel_hi11: 542; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ga_16+8) 543; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi11)(a0) 544; RV64I-MEDIUM-NEXT: ret 545; 546; RV64I-LARGE-LABEL: load_ga_16: 547; RV64I-LARGE: # %bb.0: # %entry 548; RV64I-LARGE-NEXT: .Lpcrel_hi11: 549; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI11_0) 550; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi11)(a0) 551; RV64I-LARGE-NEXT: ld a0, 8(a0) 552; RV64I-LARGE-NEXT: ret 553entry: 554 %0 = load i64, ptr getelementptr inbounds ([2 x i64], ptr @ga_16, i32 0, i32 1) 555 ret i64 %0 556} 557 558; Check for folds in accesses to block address. 559define dso_local ptr @load_ba_1() nounwind { 560; RV32I-LABEL: load_ba_1: 561; RV32I: # %bb.0: # %entry 562; RV32I-NEXT: .Ltmp0: # Block address taken 563; RV32I-NEXT: # %bb.1: # %label 564; RV32I-NEXT: lui a0, %hi(.Ltmp0) 565; RV32I-NEXT: lw a0, %lo(.Ltmp0)(a0) 566; RV32I-NEXT: ret 567; 568; RV32I-MEDIUM-LABEL: load_ba_1: 569; RV32I-MEDIUM: # %bb.0: # %entry 570; RV32I-MEDIUM-NEXT: .Ltmp0: # Block address taken 571; RV32I-MEDIUM-NEXT: # %bb.1: # %label 572; RV32I-MEDIUM-NEXT: .Lpcrel_hi12: 573; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(.Ltmp0) 574; RV32I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi12)(a0) 575; RV32I-MEDIUM-NEXT: ret 576; 577; RV64I-LABEL: load_ba_1: 578; RV64I: # %bb.0: # %entry 579; RV64I-NEXT: .Ltmp0: # Block address taken 580; RV64I-NEXT: # %bb.1: # %label 581; RV64I-NEXT: lui a0, %hi(.Ltmp0) 582; RV64I-NEXT: ld a0, %lo(.Ltmp0)(a0) 583; RV64I-NEXT: ret 584; 585; RV64I-MEDIUM-LABEL: load_ba_1: 586; RV64I-MEDIUM: # %bb.0: # %entry 587; RV64I-MEDIUM-NEXT: .Ltmp0: # Block address taken 588; RV64I-MEDIUM-NEXT: # %bb.1: # %label 589; RV64I-MEDIUM-NEXT: .Lpcrel_hi12: 590; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(.Ltmp0) 591; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi12)(a0) 592; RV64I-MEDIUM-NEXT: ret 593; 594; RV64I-LARGE-LABEL: load_ba_1: 595; RV64I-LARGE: # %bb.0: # %entry 596; RV64I-LARGE-NEXT: .Ltmp0: # Block address taken 597; RV64I-LARGE-NEXT: # %bb.1: # %label 598; RV64I-LARGE-NEXT: .Lpcrel_hi12: 599; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.Ltmp0) 600; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi12)(a0) 601; RV64I-LARGE-NEXT: ret 602entry: 603 br label %label 604label: 605 %0 = load ptr, ptr blockaddress(@load_ba_1, %label) 606 ret ptr %0 607} 608 609define dso_local ptr @load_ba_2() nounwind { 610; RV32I-LABEL: load_ba_2: 611; RV32I: # %bb.0: # %entry 612; RV32I-NEXT: .Ltmp1: # Block address taken 613; RV32I-NEXT: # %bb.1: # %label 614; RV32I-NEXT: lui a0, %hi(.Ltmp1+8) 615; RV32I-NEXT: lw a0, %lo(.Ltmp1+8)(a0) 616; RV32I-NEXT: ret 617; 618; RV32I-MEDIUM-LABEL: load_ba_2: 619; RV32I-MEDIUM: # %bb.0: # %entry 620; RV32I-MEDIUM-NEXT: .Ltmp1: # Block address taken 621; RV32I-MEDIUM-NEXT: # %bb.1: # %label 622; RV32I-MEDIUM-NEXT: .Lpcrel_hi13: 623; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(.Ltmp1+8) 624; RV32I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi13)(a0) 625; RV32I-MEDIUM-NEXT: ret 626; 627; RV64I-LABEL: load_ba_2: 628; RV64I: # %bb.0: # %entry 629; RV64I-NEXT: .Ltmp1: # Block address taken 630; RV64I-NEXT: # %bb.1: # %label 631; RV64I-NEXT: lui a0, %hi(.Ltmp1+8) 632; RV64I-NEXT: ld a0, %lo(.Ltmp1+8)(a0) 633; RV64I-NEXT: ret 634; 635; RV64I-MEDIUM-LABEL: load_ba_2: 636; RV64I-MEDIUM: # %bb.0: # %entry 637; RV64I-MEDIUM-NEXT: .Ltmp1: # Block address taken 638; RV64I-MEDIUM-NEXT: # %bb.1: # %label 639; RV64I-MEDIUM-NEXT: .Lpcrel_hi13: 640; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(.Ltmp1+8) 641; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi13)(a0) 642; RV64I-MEDIUM-NEXT: ret 643; 644; RV64I-LARGE-LABEL: load_ba_2: 645; RV64I-LARGE: # %bb.0: # %entry 646; RV64I-LARGE-NEXT: .Ltmp1: # Block address taken 647; RV64I-LARGE-NEXT: # %bb.1: # %label 648; RV64I-LARGE-NEXT: .Lpcrel_hi13: 649; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.Ltmp1+8) 650; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi13)(a0) 651; RV64I-LARGE-NEXT: ret 652entry: 653 br label %label 654label: 655 %0 = load ptr, ptr getelementptr inbounds (i8, ptr blockaddress(@load_ba_2, %label), i32 8) 656 ret ptr %0 657} 658 659; Check for folds in accesses to thread-local variables. 660 661@tl_4 = dso_local thread_local global i64 0, align 4 662@tl_8 = dso_local thread_local global i64 0, align 8 663 664define dso_local i64 @load_tl_4() nounwind { 665; RV32I-LABEL: load_tl_4: 666; RV32I: # %bb.0: # %entry 667; RV32I-NEXT: lui a0, %tprel_hi(tl_4) 668; RV32I-NEXT: add a1, a0, tp, %tprel_add(tl_4) 669; RV32I-NEXT: lw a0, %tprel_lo(tl_4)(a1) 670; RV32I-NEXT: addi a1, a1, %tprel_lo(tl_4) 671; RV32I-NEXT: lw a1, 4(a1) 672; RV32I-NEXT: ret 673; 674; RV32I-MEDIUM-LABEL: load_tl_4: 675; RV32I-MEDIUM: # %bb.0: # %entry 676; RV32I-MEDIUM-NEXT: lui a0, %tprel_hi(tl_4) 677; RV32I-MEDIUM-NEXT: add a1, a0, tp, %tprel_add(tl_4) 678; RV32I-MEDIUM-NEXT: lw a0, %tprel_lo(tl_4)(a1) 679; RV32I-MEDIUM-NEXT: addi a1, a1, %tprel_lo(tl_4) 680; RV32I-MEDIUM-NEXT: lw a1, 4(a1) 681; RV32I-MEDIUM-NEXT: ret 682; 683; RV64I-LABEL: load_tl_4: 684; RV64I: # %bb.0: # %entry 685; RV64I-NEXT: lui a0, %tprel_hi(tl_4) 686; RV64I-NEXT: add a0, a0, tp, %tprel_add(tl_4) 687; RV64I-NEXT: ld a0, %tprel_lo(tl_4)(a0) 688; RV64I-NEXT: ret 689; 690; RV64I-MEDIUM-LABEL: load_tl_4: 691; RV64I-MEDIUM: # %bb.0: # %entry 692; RV64I-MEDIUM-NEXT: lui a0, %tprel_hi(tl_4) 693; RV64I-MEDIUM-NEXT: add a0, a0, tp, %tprel_add(tl_4) 694; RV64I-MEDIUM-NEXT: ld a0, %tprel_lo(tl_4)(a0) 695; RV64I-MEDIUM-NEXT: ret 696; 697; RV64I-LARGE-LABEL: load_tl_4: 698; RV64I-LARGE: # %bb.0: # %entry 699; RV64I-LARGE-NEXT: lui a0, %tprel_hi(tl_4) 700; RV64I-LARGE-NEXT: add a0, a0, tp, %tprel_add(tl_4) 701; RV64I-LARGE-NEXT: ld a0, %tprel_lo(tl_4)(a0) 702; RV64I-LARGE-NEXT: ret 703entry: 704 %0 = load i64, ptr @tl_4 705 ret i64 %0 706} 707 708define dso_local i64 @load_tl_8() nounwind { 709; RV32I-LABEL: load_tl_8: 710; RV32I: # %bb.0: # %entry 711; RV32I-NEXT: lui a0, %tprel_hi(tl_8) 712; RV32I-NEXT: add a1, a0, tp, %tprel_add(tl_8) 713; RV32I-NEXT: lw a0, %tprel_lo(tl_8)(a1) 714; RV32I-NEXT: lw a1, %tprel_lo(tl_8+4)(a1) 715; RV32I-NEXT: ret 716; 717; RV32I-MEDIUM-LABEL: load_tl_8: 718; RV32I-MEDIUM: # %bb.0: # %entry 719; RV32I-MEDIUM-NEXT: lui a0, %tprel_hi(tl_8) 720; RV32I-MEDIUM-NEXT: add a1, a0, tp, %tprel_add(tl_8) 721; RV32I-MEDIUM-NEXT: lw a0, %tprel_lo(tl_8)(a1) 722; RV32I-MEDIUM-NEXT: lw a1, %tprel_lo(tl_8+4)(a1) 723; RV32I-MEDIUM-NEXT: ret 724; 725; RV64I-LABEL: load_tl_8: 726; RV64I: # %bb.0: # %entry 727; RV64I-NEXT: lui a0, %tprel_hi(tl_8) 728; RV64I-NEXT: add a0, a0, tp, %tprel_add(tl_8) 729; RV64I-NEXT: ld a0, %tprel_lo(tl_8)(a0) 730; RV64I-NEXT: ret 731; 732; RV64I-MEDIUM-LABEL: load_tl_8: 733; RV64I-MEDIUM: # %bb.0: # %entry 734; RV64I-MEDIUM-NEXT: lui a0, %tprel_hi(tl_8) 735; RV64I-MEDIUM-NEXT: add a0, a0, tp, %tprel_add(tl_8) 736; RV64I-MEDIUM-NEXT: ld a0, %tprel_lo(tl_8)(a0) 737; RV64I-MEDIUM-NEXT: ret 738; 739; RV64I-LARGE-LABEL: load_tl_8: 740; RV64I-LARGE: # %bb.0: # %entry 741; RV64I-LARGE-NEXT: lui a0, %tprel_hi(tl_8) 742; RV64I-LARGE-NEXT: add a0, a0, tp, %tprel_add(tl_8) 743; RV64I-LARGE-NEXT: ld a0, %tprel_lo(tl_8)(a0) 744; RV64I-LARGE-NEXT: ret 745entry: 746 %0 = load i64, ptr @tl_8 747 ret i64 %0 748} 749 750define dso_local i64 @load_const_ok() nounwind { 751; RV32I-LABEL: load_const_ok: 752; RV32I: # %bb.0: # %entry 753; RV32I-NEXT: lw a0, 2040(zero) 754; RV32I-NEXT: lw a1, 2044(zero) 755; RV32I-NEXT: ret 756; 757; RV32I-MEDIUM-LABEL: load_const_ok: 758; RV32I-MEDIUM: # %bb.0: # %entry 759; RV32I-MEDIUM-NEXT: lw a0, 2040(zero) 760; RV32I-MEDIUM-NEXT: lw a1, 2044(zero) 761; RV32I-MEDIUM-NEXT: ret 762; 763; RV64I-LABEL: load_const_ok: 764; RV64I: # %bb.0: # %entry 765; RV64I-NEXT: ld a0, 2040(zero) 766; RV64I-NEXT: ret 767; 768; RV64I-MEDIUM-LABEL: load_const_ok: 769; RV64I-MEDIUM: # %bb.0: # %entry 770; RV64I-MEDIUM-NEXT: ld a0, 2040(zero) 771; RV64I-MEDIUM-NEXT: ret 772; 773; RV64I-LARGE-LABEL: load_const_ok: 774; RV64I-LARGE: # %bb.0: # %entry 775; RV64I-LARGE-NEXT: ld a0, 2040(zero) 776; RV64I-LARGE-NEXT: ret 777entry: 778 %0 = load i64, ptr inttoptr (i32 2040 to ptr) 779 ret i64 %0 780} 781 782define dso_local i64 @load_cost_overflow() nounwind { 783; RV32I-LABEL: load_cost_overflow: 784; RV32I: # %bb.0: # %entry 785; RV32I-NEXT: lui a0, 1 786; RV32I-NEXT: lw a1, -2048(a0) 787; RV32I-NEXT: lw a0, 2044(zero) 788; RV32I-NEXT: ret 789; 790; RV32I-MEDIUM-LABEL: load_cost_overflow: 791; RV32I-MEDIUM: # %bb.0: # %entry 792; RV32I-MEDIUM-NEXT: lui a0, 1 793; RV32I-MEDIUM-NEXT: lw a1, -2048(a0) 794; RV32I-MEDIUM-NEXT: lw a0, 2044(zero) 795; RV32I-MEDIUM-NEXT: ret 796; 797; RV64I-LABEL: load_cost_overflow: 798; RV64I: # %bb.0: # %entry 799; RV64I-NEXT: ld a0, 2044(zero) 800; RV64I-NEXT: ret 801; 802; RV64I-MEDIUM-LABEL: load_cost_overflow: 803; RV64I-MEDIUM: # %bb.0: # %entry 804; RV64I-MEDIUM-NEXT: ld a0, 2044(zero) 805; RV64I-MEDIUM-NEXT: ret 806; 807; RV64I-LARGE-LABEL: load_cost_overflow: 808; RV64I-LARGE: # %bb.0: # %entry 809; RV64I-LARGE-NEXT: ld a0, 2044(zero) 810; RV64I-LARGE-NEXT: ret 811entry: 812 %0 = load i64, ptr inttoptr (i64 2044 to ptr) 813 ret i64 %0 814} 815 816define dso_local i32 @load_const_medium() nounwind { 817; RV32I-LABEL: load_const_medium: 818; RV32I: # %bb.0: # %entry 819; RV32I-NEXT: lui a0, 1 820; RV32I-NEXT: lw a0, -16(a0) 821; RV32I-NEXT: ret 822; 823; RV32I-MEDIUM-LABEL: load_const_medium: 824; RV32I-MEDIUM: # %bb.0: # %entry 825; RV32I-MEDIUM-NEXT: lui a0, 1 826; RV32I-MEDIUM-NEXT: lw a0, -16(a0) 827; RV32I-MEDIUM-NEXT: ret 828; 829; RV64I-LABEL: load_const_medium: 830; RV64I: # %bb.0: # %entry 831; RV64I-NEXT: lui a0, 1 832; RV64I-NEXT: lw a0, -16(a0) 833; RV64I-NEXT: ret 834; 835; RV64I-MEDIUM-LABEL: load_const_medium: 836; RV64I-MEDIUM: # %bb.0: # %entry 837; RV64I-MEDIUM-NEXT: lui a0, 1 838; RV64I-MEDIUM-NEXT: lw a0, -16(a0) 839; RV64I-MEDIUM-NEXT: ret 840; 841; RV64I-LARGE-LABEL: load_const_medium: 842; RV64I-LARGE: # %bb.0: # %entry 843; RV64I-LARGE-NEXT: lui a0, 1 844; RV64I-LARGE-NEXT: lw a0, -16(a0) 845; RV64I-LARGE-NEXT: ret 846entry: 847 %0 = load i32, ptr inttoptr (i64 4080 to ptr) 848 ret i32 %0 849} 850 851; The constant here is 0x7ffff800, this value requires LUI+ADDIW on RV64, 852; LUI+ADDI would produce a different constant so we can't fold into the load 853; offset. 854define dso_local i32 @load_const_large() nounwind { 855; RV32I-LABEL: load_const_large: 856; RV32I: # %bb.0: # %entry 857; RV32I-NEXT: lui a0, 524288 858; RV32I-NEXT: lw a0, -2048(a0) 859; RV32I-NEXT: ret 860; 861; RV32I-MEDIUM-LABEL: load_const_large: 862; RV32I-MEDIUM: # %bb.0: # %entry 863; RV32I-MEDIUM-NEXT: lui a0, 524288 864; RV32I-MEDIUM-NEXT: lw a0, -2048(a0) 865; RV32I-MEDIUM-NEXT: ret 866; 867; RV64I-LABEL: load_const_large: 868; RV64I: # %bb.0: # %entry 869; RV64I-NEXT: lui a0, 524288 870; RV64I-NEXT: addiw a0, a0, -2048 871; RV64I-NEXT: lw a0, 0(a0) 872; RV64I-NEXT: ret 873; 874; RV64I-MEDIUM-LABEL: load_const_large: 875; RV64I-MEDIUM: # %bb.0: # %entry 876; RV64I-MEDIUM-NEXT: lui a0, 524288 877; RV64I-MEDIUM-NEXT: addiw a0, a0, -2048 878; RV64I-MEDIUM-NEXT: lw a0, 0(a0) 879; RV64I-MEDIUM-NEXT: ret 880; 881; RV64I-LARGE-LABEL: load_const_large: 882; RV64I-LARGE: # %bb.0: # %entry 883; RV64I-LARGE-NEXT: lui a0, 524288 884; RV64I-LARGE-NEXT: addiw a0, a0, -2048 885; RV64I-LARGE-NEXT: lw a0, 0(a0) 886; RV64I-LARGE-NEXT: ret 887entry: 888 %0 = load i32, ptr inttoptr (i64 2147481600 to ptr) 889 ret i32 %0 890} 891 892%struct.S = type { i64, i64 } 893 894define i64 @fold_addi_from_different_bb(i64 %k, i64 %n, ptr %a) nounwind { 895; RV32I-LABEL: fold_addi_from_different_bb: 896; RV32I: # %bb.0: # %entry 897; RV32I-NEXT: addi sp, sp, -48 898; RV32I-NEXT: sw ra, 44(sp) # 4-byte Folded Spill 899; RV32I-NEXT: sw s0, 40(sp) # 4-byte Folded Spill 900; RV32I-NEXT: sw s1, 36(sp) # 4-byte Folded Spill 901; RV32I-NEXT: sw s2, 32(sp) # 4-byte Folded Spill 902; RV32I-NEXT: sw s3, 28(sp) # 4-byte Folded Spill 903; RV32I-NEXT: sw s4, 24(sp) # 4-byte Folded Spill 904; RV32I-NEXT: sw s5, 20(sp) # 4-byte Folded Spill 905; RV32I-NEXT: sw s6, 16(sp) # 4-byte Folded Spill 906; RV32I-NEXT: sw s7, 12(sp) # 4-byte Folded Spill 907; RV32I-NEXT: mv s0, a4 908; RV32I-NEXT: mv s1, a3 909; RV32I-NEXT: mv s2, a2 910; RV32I-NEXT: beqz a3, .LBB20_3 911; RV32I-NEXT: # %bb.1: # %entry 912; RV32I-NEXT: slti a1, s1, 0 913; RV32I-NEXT: beqz a1, .LBB20_4 914; RV32I-NEXT: .LBB20_2: 915; RV32I-NEXT: li s3, 0 916; RV32I-NEXT: li s4, 0 917; RV32I-NEXT: j .LBB20_6 918; RV32I-NEXT: .LBB20_3: 919; RV32I-NEXT: seqz a1, s2 920; RV32I-NEXT: bnez a1, .LBB20_2 921; RV32I-NEXT: .LBB20_4: # %for.body.lr.ph 922; RV32I-NEXT: li s5, 0 923; RV32I-NEXT: li s6, 0 924; RV32I-NEXT: li s3, 0 925; RV32I-NEXT: li s4, 0 926; RV32I-NEXT: slli a0, a0, 4 927; RV32I-NEXT: add s7, s0, a0 928; RV32I-NEXT: .LBB20_5: # %for.body 929; RV32I-NEXT: # =>This Inner Loop Header: Depth=1 930; RV32I-NEXT: mv a0, s0 931; RV32I-NEXT: call f 932; RV32I-NEXT: lw a0, 8(s7) 933; RV32I-NEXT: lw a1, 12(s7) 934; RV32I-NEXT: addi s5, s5, 1 935; RV32I-NEXT: seqz a2, s5 936; RV32I-NEXT: add s6, s6, a2 937; RV32I-NEXT: xor a2, s5, s2 938; RV32I-NEXT: add a1, a1, s4 939; RV32I-NEXT: xor a3, s6, s1 940; RV32I-NEXT: or a2, a2, a3 941; RV32I-NEXT: add s3, a0, s3 942; RV32I-NEXT: sltu s4, s3, a0 943; RV32I-NEXT: add s4, a1, s4 944; RV32I-NEXT: bnez a2, .LBB20_5 945; RV32I-NEXT: .LBB20_6: # %for.cond.cleanup 946; RV32I-NEXT: mv a0, s3 947; RV32I-NEXT: mv a1, s4 948; RV32I-NEXT: lw ra, 44(sp) # 4-byte Folded Reload 949; RV32I-NEXT: lw s0, 40(sp) # 4-byte Folded Reload 950; RV32I-NEXT: lw s1, 36(sp) # 4-byte Folded Reload 951; RV32I-NEXT: lw s2, 32(sp) # 4-byte Folded Reload 952; RV32I-NEXT: lw s3, 28(sp) # 4-byte Folded Reload 953; RV32I-NEXT: lw s4, 24(sp) # 4-byte Folded Reload 954; RV32I-NEXT: lw s5, 20(sp) # 4-byte Folded Reload 955; RV32I-NEXT: lw s6, 16(sp) # 4-byte Folded Reload 956; RV32I-NEXT: lw s7, 12(sp) # 4-byte Folded Reload 957; RV32I-NEXT: addi sp, sp, 48 958; RV32I-NEXT: ret 959; 960; RV32I-MEDIUM-LABEL: fold_addi_from_different_bb: 961; RV32I-MEDIUM: # %bb.0: # %entry 962; RV32I-MEDIUM-NEXT: addi sp, sp, -48 963; RV32I-MEDIUM-NEXT: sw ra, 44(sp) # 4-byte Folded Spill 964; RV32I-MEDIUM-NEXT: sw s0, 40(sp) # 4-byte Folded Spill 965; RV32I-MEDIUM-NEXT: sw s1, 36(sp) # 4-byte Folded Spill 966; RV32I-MEDIUM-NEXT: sw s2, 32(sp) # 4-byte Folded Spill 967; RV32I-MEDIUM-NEXT: sw s3, 28(sp) # 4-byte Folded Spill 968; RV32I-MEDIUM-NEXT: sw s4, 24(sp) # 4-byte Folded Spill 969; RV32I-MEDIUM-NEXT: sw s5, 20(sp) # 4-byte Folded Spill 970; RV32I-MEDIUM-NEXT: sw s6, 16(sp) # 4-byte Folded Spill 971; RV32I-MEDIUM-NEXT: sw s7, 12(sp) # 4-byte Folded Spill 972; RV32I-MEDIUM-NEXT: mv s0, a4 973; RV32I-MEDIUM-NEXT: mv s1, a3 974; RV32I-MEDIUM-NEXT: mv s2, a2 975; RV32I-MEDIUM-NEXT: beqz a3, .LBB20_3 976; RV32I-MEDIUM-NEXT: # %bb.1: # %entry 977; RV32I-MEDIUM-NEXT: slti a1, s1, 0 978; RV32I-MEDIUM-NEXT: beqz a1, .LBB20_4 979; RV32I-MEDIUM-NEXT: .LBB20_2: 980; RV32I-MEDIUM-NEXT: li s3, 0 981; RV32I-MEDIUM-NEXT: li s4, 0 982; RV32I-MEDIUM-NEXT: j .LBB20_6 983; RV32I-MEDIUM-NEXT: .LBB20_3: 984; RV32I-MEDIUM-NEXT: seqz a1, s2 985; RV32I-MEDIUM-NEXT: bnez a1, .LBB20_2 986; RV32I-MEDIUM-NEXT: .LBB20_4: # %for.body.lr.ph 987; RV32I-MEDIUM-NEXT: li s5, 0 988; RV32I-MEDIUM-NEXT: li s6, 0 989; RV32I-MEDIUM-NEXT: li s3, 0 990; RV32I-MEDIUM-NEXT: li s4, 0 991; RV32I-MEDIUM-NEXT: slli a0, a0, 4 992; RV32I-MEDIUM-NEXT: add s7, s0, a0 993; RV32I-MEDIUM-NEXT: .LBB20_5: # %for.body 994; RV32I-MEDIUM-NEXT: # =>This Inner Loop Header: Depth=1 995; RV32I-MEDIUM-NEXT: mv a0, s0 996; RV32I-MEDIUM-NEXT: call f 997; RV32I-MEDIUM-NEXT: lw a0, 8(s7) 998; RV32I-MEDIUM-NEXT: lw a1, 12(s7) 999; RV32I-MEDIUM-NEXT: addi s5, s5, 1 1000; RV32I-MEDIUM-NEXT: seqz a2, s5 1001; RV32I-MEDIUM-NEXT: add s6, s6, a2 1002; RV32I-MEDIUM-NEXT: xor a2, s5, s2 1003; RV32I-MEDIUM-NEXT: add a1, a1, s4 1004; RV32I-MEDIUM-NEXT: xor a3, s6, s1 1005; RV32I-MEDIUM-NEXT: or a2, a2, a3 1006; RV32I-MEDIUM-NEXT: add s3, a0, s3 1007; RV32I-MEDIUM-NEXT: sltu s4, s3, a0 1008; RV32I-MEDIUM-NEXT: add s4, a1, s4 1009; RV32I-MEDIUM-NEXT: bnez a2, .LBB20_5 1010; RV32I-MEDIUM-NEXT: .LBB20_6: # %for.cond.cleanup 1011; RV32I-MEDIUM-NEXT: mv a0, s3 1012; RV32I-MEDIUM-NEXT: mv a1, s4 1013; RV32I-MEDIUM-NEXT: lw ra, 44(sp) # 4-byte Folded Reload 1014; RV32I-MEDIUM-NEXT: lw s0, 40(sp) # 4-byte Folded Reload 1015; RV32I-MEDIUM-NEXT: lw s1, 36(sp) # 4-byte Folded Reload 1016; RV32I-MEDIUM-NEXT: lw s2, 32(sp) # 4-byte Folded Reload 1017; RV32I-MEDIUM-NEXT: lw s3, 28(sp) # 4-byte Folded Reload 1018; RV32I-MEDIUM-NEXT: lw s4, 24(sp) # 4-byte Folded Reload 1019; RV32I-MEDIUM-NEXT: lw s5, 20(sp) # 4-byte Folded Reload 1020; RV32I-MEDIUM-NEXT: lw s6, 16(sp) # 4-byte Folded Reload 1021; RV32I-MEDIUM-NEXT: lw s7, 12(sp) # 4-byte Folded Reload 1022; RV32I-MEDIUM-NEXT: addi sp, sp, 48 1023; RV32I-MEDIUM-NEXT: ret 1024; 1025; RV64I-LABEL: fold_addi_from_different_bb: 1026; RV64I: # %bb.0: # %entry 1027; RV64I-NEXT: addi sp, sp, -48 1028; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 1029; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 1030; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 1031; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 1032; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 1033; RV64I-NEXT: blez a1, .LBB20_3 1034; RV64I-NEXT: # %bb.1: # %for.body.lr.ph 1035; RV64I-NEXT: mv s0, a2 1036; RV64I-NEXT: mv s1, a1 1037; RV64I-NEXT: li s2, 0 1038; RV64I-NEXT: slli a0, a0, 4 1039; RV64I-NEXT: add s3, a2, a0 1040; RV64I-NEXT: .LBB20_2: # %for.body 1041; RV64I-NEXT: # =>This Inner Loop Header: Depth=1 1042; RV64I-NEXT: mv a0, s0 1043; RV64I-NEXT: call f 1044; RV64I-NEXT: ld a0, 8(s3) 1045; RV64I-NEXT: addi s1, s1, -1 1046; RV64I-NEXT: add s2, a0, s2 1047; RV64I-NEXT: bnez s1, .LBB20_2 1048; RV64I-NEXT: j .LBB20_4 1049; RV64I-NEXT: .LBB20_3: 1050; RV64I-NEXT: li s2, 0 1051; RV64I-NEXT: .LBB20_4: # %for.cond.cleanup 1052; RV64I-NEXT: mv a0, s2 1053; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 1054; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 1055; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 1056; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 1057; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 1058; RV64I-NEXT: addi sp, sp, 48 1059; RV64I-NEXT: ret 1060; 1061; RV64I-MEDIUM-LABEL: fold_addi_from_different_bb: 1062; RV64I-MEDIUM: # %bb.0: # %entry 1063; RV64I-MEDIUM-NEXT: addi sp, sp, -48 1064; RV64I-MEDIUM-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 1065; RV64I-MEDIUM-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 1066; RV64I-MEDIUM-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 1067; RV64I-MEDIUM-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 1068; RV64I-MEDIUM-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 1069; RV64I-MEDIUM-NEXT: blez a1, .LBB20_3 1070; RV64I-MEDIUM-NEXT: # %bb.1: # %for.body.lr.ph 1071; RV64I-MEDIUM-NEXT: mv s0, a2 1072; RV64I-MEDIUM-NEXT: mv s1, a1 1073; RV64I-MEDIUM-NEXT: li s2, 0 1074; RV64I-MEDIUM-NEXT: slli a0, a0, 4 1075; RV64I-MEDIUM-NEXT: add s3, a2, a0 1076; RV64I-MEDIUM-NEXT: .LBB20_2: # %for.body 1077; RV64I-MEDIUM-NEXT: # =>This Inner Loop Header: Depth=1 1078; RV64I-MEDIUM-NEXT: mv a0, s0 1079; RV64I-MEDIUM-NEXT: call f 1080; RV64I-MEDIUM-NEXT: ld a0, 8(s3) 1081; RV64I-MEDIUM-NEXT: addi s1, s1, -1 1082; RV64I-MEDIUM-NEXT: add s2, a0, s2 1083; RV64I-MEDIUM-NEXT: bnez s1, .LBB20_2 1084; RV64I-MEDIUM-NEXT: j .LBB20_4 1085; RV64I-MEDIUM-NEXT: .LBB20_3: 1086; RV64I-MEDIUM-NEXT: li s2, 0 1087; RV64I-MEDIUM-NEXT: .LBB20_4: # %for.cond.cleanup 1088; RV64I-MEDIUM-NEXT: mv a0, s2 1089; RV64I-MEDIUM-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 1090; RV64I-MEDIUM-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 1091; RV64I-MEDIUM-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 1092; RV64I-MEDIUM-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 1093; RV64I-MEDIUM-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 1094; RV64I-MEDIUM-NEXT: addi sp, sp, 48 1095; RV64I-MEDIUM-NEXT: ret 1096; 1097; RV64I-LARGE-LABEL: fold_addi_from_different_bb: 1098; RV64I-LARGE: # %bb.0: # %entry 1099; RV64I-LARGE-NEXT: addi sp, sp, -48 1100; RV64I-LARGE-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 1101; RV64I-LARGE-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 1102; RV64I-LARGE-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 1103; RV64I-LARGE-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 1104; RV64I-LARGE-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 1105; RV64I-LARGE-NEXT: sd s4, 0(sp) # 8-byte Folded Spill 1106; RV64I-LARGE-NEXT: blez a1, .LBB20_3 1107; RV64I-LARGE-NEXT: # %bb.1: # %for.body.lr.ph 1108; RV64I-LARGE-NEXT: mv s0, a2 1109; RV64I-LARGE-NEXT: mv s1, a1 1110; RV64I-LARGE-NEXT: li s2, 0 1111; RV64I-LARGE-NEXT: .Lpcrel_hi14: 1112; RV64I-LARGE-NEXT: auipc a1, %pcrel_hi(.LCPI20_0) 1113; RV64I-LARGE-NEXT: ld s3, %pcrel_lo(.Lpcrel_hi14)(a1) 1114; RV64I-LARGE-NEXT: slli a0, a0, 4 1115; RV64I-LARGE-NEXT: add s4, a2, a0 1116; RV64I-LARGE-NEXT: .LBB20_2: # %for.body 1117; RV64I-LARGE-NEXT: # =>This Inner Loop Header: Depth=1 1118; RV64I-LARGE-NEXT: mv a0, s0 1119; RV64I-LARGE-NEXT: jalr s3 1120; RV64I-LARGE-NEXT: ld a0, 8(s4) 1121; RV64I-LARGE-NEXT: addi s1, s1, -1 1122; RV64I-LARGE-NEXT: add s2, a0, s2 1123; RV64I-LARGE-NEXT: bnez s1, .LBB20_2 1124; RV64I-LARGE-NEXT: j .LBB20_4 1125; RV64I-LARGE-NEXT: .LBB20_3: 1126; RV64I-LARGE-NEXT: li s2, 0 1127; RV64I-LARGE-NEXT: .LBB20_4: # %for.cond.cleanup 1128; RV64I-LARGE-NEXT: mv a0, s2 1129; RV64I-LARGE-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 1130; RV64I-LARGE-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 1131; RV64I-LARGE-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 1132; RV64I-LARGE-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 1133; RV64I-LARGE-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 1134; RV64I-LARGE-NEXT: ld s4, 0(sp) # 8-byte Folded Reload 1135; RV64I-LARGE-NEXT: addi sp, sp, 48 1136; RV64I-LARGE-NEXT: ret 1137entry: 1138 %cmp4 = icmp sgt i64 %n, 0 1139 br i1 %cmp4, label %for.body.lr.ph, label %for.cond.cleanup 1140 1141for.body.lr.ph: ; preds = %entry 1142 ; TODO: when this GEP is expanded, the resulting `addi` should be folded 1143 ; into the load in the loop body. 1144 %y = getelementptr inbounds %struct.S, ptr %a, i64 %k, i32 1 1145 br label %for.body 1146 1147for.cond.cleanup: ; preds = %for.body, %entry 1148 %s.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ] 1149 ret i64 %s.0.lcssa 1150 1151for.body: ; preds = %for.body.lr.ph, %for.body 1152 %i.06 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ] 1153 %s.05 = phi i64 [ 0, %for.body.lr.ph ], [ %add, %for.body ] 1154 call void @f(ptr %a) 1155 %0 = load i64, ptr %y, align 8 1156 %add = add nsw i64 %0, %s.05 1157 %inc = add nuw nsw i64 %i.06, 1 1158 %exitcond.not = icmp eq i64 %inc, %n 1159 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 1160} 1161 1162declare void @f(ptr) 1163 1164@g = external dso_local global [100 x [100 x i8]] 1165 1166; This test used to crash due to calling getVRegDef on X0. 1167define i32 @crash() { 1168; RV32I-LABEL: crash: 1169; RV32I: # %bb.0: # %entry 1170; RV32I-NEXT: lui a0, %hi(g+401) 1171; RV32I-NEXT: lbu a0, %lo(g+401)(a0) 1172; RV32I-NEXT: seqz a0, a0 1173; RV32I-NEXT: sw a0, 0(zero) 1174; RV32I-NEXT: li a0, 0 1175; RV32I-NEXT: ret 1176; 1177; RV32I-MEDIUM-LABEL: crash: 1178; RV32I-MEDIUM: # %bb.0: # %entry 1179; RV32I-MEDIUM-NEXT: .Lpcrel_hi14: 1180; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g+401) 1181; RV32I-MEDIUM-NEXT: lbu a0, %pcrel_lo(.Lpcrel_hi14)(a0) 1182; RV32I-MEDIUM-NEXT: seqz a0, a0 1183; RV32I-MEDIUM-NEXT: sw a0, 0(zero) 1184; RV32I-MEDIUM-NEXT: li a0, 0 1185; RV32I-MEDIUM-NEXT: ret 1186; 1187; RV64I-LABEL: crash: 1188; RV64I: # %bb.0: # %entry 1189; RV64I-NEXT: lui a0, %hi(g+401) 1190; RV64I-NEXT: lbu a0, %lo(g+401)(a0) 1191; RV64I-NEXT: seqz a0, a0 1192; RV64I-NEXT: sw a0, 0(zero) 1193; RV64I-NEXT: li a0, 0 1194; RV64I-NEXT: ret 1195; 1196; RV64I-MEDIUM-LABEL: crash: 1197; RV64I-MEDIUM: # %bb.0: # %entry 1198; RV64I-MEDIUM-NEXT: .Lpcrel_hi14: 1199; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g+401) 1200; RV64I-MEDIUM-NEXT: lbu a0, %pcrel_lo(.Lpcrel_hi14)(a0) 1201; RV64I-MEDIUM-NEXT: seqz a0, a0 1202; RV64I-MEDIUM-NEXT: sw a0, 0(zero) 1203; RV64I-MEDIUM-NEXT: li a0, 0 1204; RV64I-MEDIUM-NEXT: ret 1205; 1206; RV64I-LARGE-LABEL: crash: 1207; RV64I-LARGE: # %bb.0: # %entry 1208; RV64I-LARGE-NEXT: li a0, 1 1209; RV64I-LARGE-NEXT: .Lpcrel_hi15: 1210; RV64I-LARGE-NEXT: auipc a1, %pcrel_hi(.LCPI21_0) 1211; RV64I-LARGE-NEXT: ld a1, %pcrel_lo(.Lpcrel_hi15)(a1) 1212; RV64I-LARGE-NEXT: add a0, a1, a0 1213; RV64I-LARGE-NEXT: lbu a0, 400(a0) 1214; RV64I-LARGE-NEXT: seqz a0, a0 1215; RV64I-LARGE-NEXT: sw a0, 0(zero) 1216; RV64I-LARGE-NEXT: li a0, 0 1217; RV64I-LARGE-NEXT: ret 1218entry: 1219 %idxprom7.peel = sext i32 1 to i64 1220 br label %for.inc.peel 1221 1222for.inc.peel: ; preds = %entry 1223 %arrayidx8.3.peel = getelementptr [100 x [100 x i8]], ptr @g, i64 0, i64 4, i64 %idxprom7.peel 1224 %0 = load i8, ptr %arrayidx8.3.peel, align 1 1225 %tobool.not.3.peel = icmp eq i8 %0, 0 1226 %spec.select = select i1 %tobool.not.3.peel, i32 1, i32 0 1227 store i32 %spec.select, ptr null, align 4 1228 ret i32 0 1229} 1230