1; RUN: llc --mtriple=loongarch32 --mattr=+d --relocation-model=static < %s | FileCheck %s --check-prefixes=ALL,LA32NOPIC,LA32 2; RUN: llc --mtriple=loongarch32 --mattr=+d --relocation-model=pic < %s | FileCheck %s --check-prefixes=ALL,LA32PIC,LA32 3; RUN: llc --mtriple=loongarch64 --mattr=+d --relocation-model=static < %s | FileCheck %s --check-prefixes=ALL,LA64NOPIC,LA64 4; RUN: llc --mtriple=loongarch64 --mattr=+d --relocation-model=pic < %s | FileCheck %s --check-prefixes=ALL,LA64PIC,LA64 5 6;; Check load from and store to global variables. 7@G = dso_local global i32 zeroinitializer, align 4 8@arr = dso_local global [10 x i32] zeroinitializer, align 4 9 10define i32 @load_store_global() nounwind { 11; ALL-LABEL: load_store_global: 12; ALL: # %bb.0: 13 14; LA32NOPIC-NEXT: pcalau12i $a0, G 15; LA32NOPIC-NEXT: addi.w $a1, $a0, G 16; LA32PIC-NEXT: pcalau12i $a0, .LG$local 17; LA32PIC-NEXT: addi.w $a1, $a0, .LG$local 18; LA32-NEXT: ld.w $a0, $a1, 0 19; LA32-NEXT: addi.w $a0, $a0, 1 20; LA32-NEXT: st.w $a0, $a1, 0 21 22; LA64NOPIC-NEXT: pcalau12i $a0, G 23; LA64NOPIC-NEXT: addi.d $a1, $a0, G 24; LA64PIC-NEXT: pcalau12i $a0, .LG$local 25; LA64PIC-NEXT: addi.d $a1, $a0, .LG$local 26; LA64-NEXT: ld.w $a0, $a1, 0 27; LA64-NEXT: addi.d $a0, $a0, 1 28; LA64-NEXT: st.w $a0, $a1, 0 29 30; ALL-NEXT: jirl $zero, $ra, 0 31 32 %v = load i32, ptr @G 33 %sum = add i32 %v, 1 34 store i32 %sum, ptr @G 35 ret i32 %sum 36} 37 38define i32 @load_store_global_array(i32 %a) nounwind { 39; ALL-LABEL: load_store_global_array: 40; ALL: # %bb.0: 41 42; LA32NOPIC-NEXT: pcalau12i $a1, arr 43; LA32NOPIC-NEXT: addi.w $a2, $a1, arr 44; LA32PIC-NEXT: pcalau12i $a1, .Larr$local 45; LA32PIC-NEXT: addi.w $a2, $a1, .Larr$local 46; LA32-NEXT: ld.w $a1, $a2, 0 47; LA32-NEXT: st.w $a0, $a2, 0 48; LA32NOPIC-NEXT: ld.w $a3, $a2, 0 49; LA32NOPIC-NEXT: st.w $a0, $a2, 0 50; LA32PIC-NEXT: ld.w $a3, $a2, 36 51; LA32PIC-NEXT: st.w $a0, $a2, 36 52 53; LA64NOPIC-NEXT: pcalau12i $a1, arr 54; LA64NOPIC-NEXT: addi.d $a2, $a1, arr 55; LA64PIC-NEXT: pcalau12i $a1, .Larr$local 56; LA64PIC-NEXT: addi.d $a2, $a1, .Larr$local 57; LA64-NEXT: ld.w $a1, $a2, 0 58; LA64-NEXT: st.w $a0, $a2, 0 59; LA64NOPIC-NEXT: ld.w $a3, $a2, 0 60; LA64NOPIC-NEXT: st.w $a0, $a2, 0 61; LA64PIC-NEXT: ld.w $a3, $a2, 36 62; LA64PIC-NEXT: st.w $a0, $a2, 36 63 64; ALL-NEXT: move $a0, $a1 65; ALL-NEXT: jirl $zero, $ra, 0 66 67 %1 = load volatile i32, ptr @arr, align 4 68 store i32 %a, ptr @arr, align 4 69 %2 = getelementptr [10 x i32], ptr @arr, i32 0, i32 9 70 %3 = load volatile i32, ptr %2, align 4 71 store i32 %a, ptr %2, align 4 72 ret i32 %1 73} 74 75;; Check indexed and unindexed, sext, zext and anyext loads. 76 77define i64 @ld_b(ptr %a) nounwind { 78; LA32-LABEL: ld_b: 79; LA32: # %bb.0: 80; LA32-NEXT: ld.b $a1, $a0, 0 81; LA32-NEXT: ld.b $a0, $a0, 1 82; LA32-NEXT: srai.w $a1, $a0, 31 83; LA32-NEXT: jirl $zero, $ra, 0 84; 85; LA64-LABEL: ld_b: 86; LA64: # %bb.0: 87; LA64-NEXT: ld.b $a1, $a0, 0 88; LA64-NEXT: ld.b $a0, $a0, 1 89; LA64-NEXT: jirl $zero, $ra, 0 90 %1 = getelementptr i8, ptr %a, i64 1 91 %2 = load i8, ptr %1 92 %3 = sext i8 %2 to i64 93 %4 = load volatile i8, ptr %a 94 ret i64 %3 95} 96 97define i64 @ld_h(ptr %a) nounwind { 98; LA32-LABEL: ld_h: 99; LA32: # %bb.0: 100; LA32-NEXT: ld.h $a1, $a0, 0 101; LA32-NEXT: ld.h $a0, $a0, 4 102; LA32-NEXT: srai.w $a1, $a0, 31 103; LA32-NEXT: jirl $zero, $ra, 0 104; 105; LA64-LABEL: ld_h: 106; LA64: # %bb.0: 107; LA64-NEXT: ld.h $a1, $a0, 0 108; LA64-NEXT: ld.h $a0, $a0, 4 109; LA64-NEXT: jirl $zero, $ra, 0 110 %1 = getelementptr i16, ptr %a, i64 2 111 %2 = load i16, ptr %1 112 %3 = sext i16 %2 to i64 113 %4 = load volatile i16, ptr %a 114 ret i64 %3 115} 116 117define i64 @ld_w(ptr %a) nounwind { 118; LA32-LABEL: ld_w: 119; LA32: # %bb.0: 120; LA32-NEXT: ld.w $a1, $a0, 0 121; LA32-NEXT: ld.w $a0, $a0, 12 122; LA32-NEXT: srai.w $a1, $a0, 31 123; LA32-NEXT: jirl $zero, $ra, 0 124; 125; LA64-LABEL: ld_w: 126; LA64: # %bb.0: 127; LA64-NEXT: ld.w $a1, $a0, 0 128; LA64-NEXT: ld.w $a0, $a0, 12 129; LA64-NEXT: jirl $zero, $ra, 0 130 %1 = getelementptr i32, ptr %a, i64 3 131 %2 = load i32, ptr %1 132 %3 = sext i32 %2 to i64 133 %4 = load volatile i32, ptr %a 134 ret i64 %3 135} 136 137define i64 @ld_d(ptr %a) nounwind { 138; LA32-LABEL: ld_d: 139; LA32: # %bb.0: 140; LA32-NEXT: ld.w $a1, $a0, 4 141; LA32-NEXT: ld.w $a1, $a0, 0 142; LA32-NEXT: ld.w $a1, $a0, 28 143; LA32-NEXT: ld.w $a0, $a0, 24 144; LA32-NEXT: jirl $zero, $ra, 0 145; 146; LA64-LABEL: ld_d: 147; LA64: # %bb.0: 148; LA64-NEXT: ld.d $a1, $a0, 0 149; LA64-NEXT: ld.d $a0, $a0, 24 150; LA64-NEXT: jirl $zero, $ra, 0 151 %1 = getelementptr i64, ptr %a, i64 3 152 %2 = load i64, ptr %1 153 %3 = load volatile i64, ptr %a 154 ret i64 %2 155} 156 157define i64 @ld_bu(ptr %a) nounwind { 158; LA32-LABEL: ld_bu: 159; LA32: # %bb.0: 160; LA32-NEXT: ld.bu $a1, $a0, 0 161; LA32-NEXT: ld.bu $a2, $a0, 4 162; LA32-NEXT: add.w $a0, $a2, $a1 163; LA32-NEXT: sltu $a1, $a0, $a2 164; LA32-NEXT: jirl $zero, $ra, 0 165; 166; LA64-LABEL: ld_bu: 167; LA64: # %bb.0: 168; LA64-NEXT: ld.bu $a1, $a0, 0 169; LA64-NEXT: ld.bu $a0, $a0, 4 170; LA64-NEXT: add.d $a0, $a0, $a1 171; LA64-NEXT: jirl $zero, $ra, 0 172 %1 = getelementptr i8, ptr %a, i64 4 173 %2 = load i8, ptr %1 174 %3 = zext i8 %2 to i64 175 %4 = load volatile i8, ptr %a 176 %5 = zext i8 %4 to i64 177 %6 = add i64 %3, %5 178 ret i64 %6 179} 180 181define i64 @ld_hu(ptr %a) nounwind { 182; LA32-LABEL: ld_hu: 183; LA32: # %bb.0: 184; LA32-NEXT: ld.hu $a1, $a0, 0 185; LA32-NEXT: ld.hu $a2, $a0, 10 186; LA32-NEXT: add.w $a0, $a2, $a1 187; LA32-NEXT: sltu $a1, $a0, $a2 188; LA32-NEXT: jirl $zero, $ra, 0 189; 190; LA64-LABEL: ld_hu: 191; LA64: # %bb.0: 192; LA64-NEXT: ld.hu $a1, $a0, 0 193; LA64-NEXT: ld.hu $a0, $a0, 10 194; LA64-NEXT: add.d $a0, $a0, $a1 195; LA64-NEXT: jirl $zero, $ra, 0 196 %1 = getelementptr i16, ptr %a, i64 5 197 %2 = load i16, ptr %1 198 %3 = zext i16 %2 to i64 199 %4 = load volatile i16, ptr %a 200 %5 = zext i16 %4 to i64 201 %6 = add i64 %3, %5 202 ret i64 %6 203} 204 205define i64 @ld_wu(ptr %a) nounwind { 206; LA32-LABEL: ld_wu: 207; LA32: # %bb.0: 208; LA32-NEXT: ld.w $a1, $a0, 0 209; LA32-NEXT: ld.w $a2, $a0, 20 210; LA32-NEXT: add.w $a0, $a2, $a1 211; LA32-NEXT: sltu $a1, $a0, $a2 212; LA32-NEXT: jirl $zero, $ra, 0 213; 214; LA64-LABEL: ld_wu: 215; LA64: # %bb.0: 216; LA64-NEXT: ld.wu $a1, $a0, 0 217; LA64-NEXT: ld.wu $a0, $a0, 20 218; LA64-NEXT: add.d $a0, $a0, $a1 219; LA64-NEXT: jirl $zero, $ra, 0 220 %1 = getelementptr i32, ptr %a, i64 5 221 %2 = load i32, ptr %1 222 %3 = zext i32 %2 to i64 223 %4 = load volatile i32, ptr %a 224 %5 = zext i32 %4 to i64 225 %6 = add i64 %3, %5 226 ret i64 %6 227} 228 229;; Check indexed and unindexed stores. 230 231define void @st_b(ptr %a, i8 %b) nounwind { 232; ALL-LABEL: st_b: 233; ALL: # %bb.0: 234; ALL-NEXT: st.b $a1, $a0, 6 235; ALL-NEXT: st.b $a1, $a0, 0 236; ALL-NEXT: jirl $zero, $ra, 0 237 store i8 %b, ptr %a 238 %1 = getelementptr i8, ptr %a, i64 6 239 store i8 %b, ptr %1 240 ret void 241} 242 243define void @st_h(ptr %a, i16 %b) nounwind { 244; ALL-LABEL: st_h: 245; ALL: # %bb.0: 246; ALL-NEXT: st.h $a1, $a0, 14 247; ALL-NEXT: st.h $a1, $a0, 0 248; ALL-NEXT: jirl $zero, $ra, 0 249 store i16 %b, ptr %a 250 %1 = getelementptr i16, ptr %a, i64 7 251 store i16 %b, ptr %1 252 ret void 253} 254 255define void @st_w(ptr %a, i32 %b) nounwind { 256; ALL-LABEL: st_w: 257; ALL: # %bb.0: 258; ALL-NEXT: st.w $a1, $a0, 28 259; ALL-NEXT: st.w $a1, $a0, 0 260; ALL-NEXT: jirl $zero, $ra, 0 261 store i32 %b, ptr %a 262 %1 = getelementptr i32, ptr %a, i64 7 263 store i32 %b, ptr %1 264 ret void 265} 266 267define void @st_d(ptr %a, i64 %b) nounwind { 268; LA32-LABEL: st_d: 269; LA32: # %bb.0: 270; LA32-NEXT: st.w $a2, $a0, 68 271; LA32-NEXT: st.w $a2, $a0, 4 272; LA32-NEXT: st.w $a1, $a0, 64 273; LA32-NEXT: st.w $a1, $a0, 0 274; LA32-NEXT: jirl $zero, $ra, 0 275; 276; LA64-LABEL: st_d: 277; LA64: # %bb.0: 278; LA64-NEXT: st.d $a1, $a0, 64 279; LA64-NEXT: st.d $a1, $a0, 0 280; LA64-NEXT: jirl $zero, $ra, 0 281 store i64 %b, ptr %a 282 %1 = getelementptr i64, ptr %a, i64 8 283 store i64 %b, ptr %1 284 ret void 285} 286 287;; Check load from and store to an i1 location. 288define i64 @load_sext_zext_anyext_i1(ptr %a) nounwind { 289 ;; sextload i1 290; LA32-LABEL: load_sext_zext_anyext_i1: 291; LA32: # %bb.0: 292; LA32-NEXT: ld.b $a1, $a0, 0 293; LA32-NEXT: ld.bu $a1, $a0, 1 294; LA32-NEXT: ld.bu $a2, $a0, 2 295; LA32-NEXT: sub.w $a0, $a2, $a1 296; LA32-NEXT: sltu $a1, $a2, $a1 297; LA32-NEXT: sub.w $a1, $zero, $a1 298; LA32-NEXT: jirl $zero, $ra, 0 299; 300; LA64-LABEL: load_sext_zext_anyext_i1: 301; LA64: # %bb.0: 302; LA64-NEXT: ld.b $a1, $a0, 0 303; LA64-NEXT: ld.bu $a1, $a0, 1 304; LA64-NEXT: ld.bu $a0, $a0, 2 305; LA64-NEXT: sub.d $a0, $a0, $a1 306; LA64-NEXT: jirl $zero, $ra, 0 307 %1 = getelementptr i1, ptr %a, i64 1 308 %2 = load i1, ptr %1 309 %3 = sext i1 %2 to i64 310 ;; zextload i1 311 %4 = getelementptr i1, ptr %a, i64 2 312 %5 = load i1, ptr %4 313 %6 = zext i1 %5 to i64 314 %7 = add i64 %3, %6 315 ;; extload i1 (anyext). Produced as the load is unused. 316 %8 = load volatile i1, ptr %a 317 ret i64 %7 318} 319 320define i16 @load_sext_zext_anyext_i1_i16(ptr %a) nounwind { 321 ;; sextload i1 322; LA32-LABEL: load_sext_zext_anyext_i1_i16: 323; LA32: # %bb.0: 324; LA32-NEXT: ld.b $a1, $a0, 0 325; LA32-NEXT: ld.bu $a1, $a0, 1 326; LA32-NEXT: ld.bu $a0, $a0, 2 327; LA32-NEXT: sub.w $a0, $a0, $a1 328; LA32-NEXT: jirl $zero, $ra, 0 329; 330; LA64-LABEL: load_sext_zext_anyext_i1_i16: 331; LA64: # %bb.0: 332; LA64-NEXT: ld.b $a1, $a0, 0 333; LA64-NEXT: ld.bu $a1, $a0, 1 334; LA64-NEXT: ld.bu $a0, $a0, 2 335; LA64-NEXT: sub.d $a0, $a0, $a1 336; LA64-NEXT: jirl $zero, $ra, 0 337 %1 = getelementptr i1, ptr %a, i64 1 338 %2 = load i1, ptr %1 339 %3 = sext i1 %2 to i16 340 ;; zextload i1 341 %4 = getelementptr i1, ptr %a, i64 2 342 %5 = load i1, ptr %4 343 %6 = zext i1 %5 to i16 344 %7 = add i16 %3, %6 345 ;; extload i1 (anyext). Produced as the load is unused. 346 %8 = load volatile i1, ptr %a 347 ret i16 %7 348} 349 350define i64 @ld_sd_constant(i64 %a) nounwind { 351; LA32-LABEL: ld_sd_constant: 352; LA32: # %bb.0: 353; LA32-NEXT: lu12i.w $a3, -136485 354; LA32-NEXT: ori $a4, $a3, 3823 355; LA32-NEXT: ld.w $a2, $a4, 0 356; LA32-NEXT: st.w $a0, $a4, 0 357; LA32-NEXT: ori $a0, $a3, 3827 358; LA32-NEXT: ld.w $a3, $a0, 0 359; LA32-NEXT: st.w $a1, $a0, 0 360; LA32-NEXT: move $a0, $a2 361; LA32-NEXT: move $a1, $a3 362; LA32-NEXT: jirl $zero, $ra, 0 363; 364; LA64-LABEL: ld_sd_constant: 365; LA64: # %bb.0: 366; LA64-NEXT: lu12i.w $a1, -136485 367; LA64-NEXT: ori $a1, $a1, 3823 368; LA64-NEXT: lu32i.d $a1, -147729 369; LA64-NEXT: lu52i.d $a2, $a1, -534 370; LA64-NEXT: ld.d $a1, $a2, 0 371; LA64-NEXT: st.d $a0, $a2, 0 372; LA64-NEXT: move $a0, $a1 373; LA64-NEXT: jirl $zero, $ra, 0 374 %1 = inttoptr i64 16045690984833335023 to ptr 375 %2 = load volatile i64, ptr %1 376 store i64 %a, ptr %1 377 ret i64 %2 378} 379 380;; Check load from and store to a float location. 381define float @load_store_float(ptr %a, float %b) nounwind { 382; ALL-LABEL: load_store_float: 383; ALL: # %bb.0: 384; ALL-NEXT: fld.s $fa1, $a0, 4 385; ALL-NEXT: fst.s $fa0, $a0, 4 386; ALL-NEXT: fmov.s $fa0, $fa1 387; ALL-NEXT: jirl $zero, $ra, 0 388 %1 = getelementptr float, ptr %a, i64 1 389 %2 = load float, ptr %1 390 store float %b, ptr %1 391 ret float %2 392} 393 394;; Check load from and store to a double location. 395define double @load_store_double(ptr %a, double %b) nounwind { 396; ALL-LABEL: load_store_double: 397; ALL: # %bb.0: 398; ALL-NEXT: fld.d $fa1, $a0, 8 399; ALL-NEXT: fst.d $fa0, $a0, 8 400; ALL-NEXT: fmov.d $fa0, $fa1 401; ALL-NEXT: jirl $zero, $ra, 0 402 %1 = getelementptr double, ptr %a, i64 1 403 %2 = load double, ptr %1 404 store double %b, ptr %1 405 ret double %2 406} 407