1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 2; Test i128 atomicrmw operations. 3; 4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z15 | FileCheck %s 5; 6; Test expansion of AtomicRMW instructions, which assume a natural alignment. 7; Note that the multiple regmoves inside the CDSG loops hopefully will go away 8; when the new i128 support is added. 9 10; Check register exchange. 11define i128 @atomicrmw_xchg(ptr %src, i128 %b) { 12; CHECK-LABEL: atomicrmw_xchg: 13; CHECK: # %bb.0: 14; CHECK-NEXT: vl %v1, 0(%r4), 3 15; CHECK-NEXT: vl %v0, 0(%r3), 4 16; CHECK-NEXT: vlgvg %r1, %v1, 1 17; CHECK-NEXT: vlgvg %r0, %v1, 0 18; CHECK-NEXT: .LBB0_1: # %atomicrmw.start 19; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 20; CHECK-NEXT: vlgvg %r5, %v0, 1 21; CHECK-NEXT: vlgvg %r4, %v0, 0 22; CHECK-NEXT: cdsg %r4, %r0, 0(%r3) 23; CHECK-NEXT: vlvgp %v0, %r4, %r5 24; CHECK-NEXT: jl .LBB0_1 25; CHECK-NEXT: # %bb.2: # %atomicrmw.end 26; CHECK-NEXT: vst %v0, 0(%r2), 3 27; CHECK-NEXT: br %r14 28 %res = atomicrmw xchg ptr %src, i128 %b seq_cst 29 ret i128 %res 30} 31 32; Check addition of a variable. 33define i128 @atomicrmw_add(ptr %src, i128 %b) { 34; CHECK-LABEL: atomicrmw_add: 35; CHECK: # %bb.0: 36; CHECK-NEXT: vl %v0, 0(%r4), 3 37; CHECK-NEXT: vl %v1, 0(%r3), 4 38; CHECK-NEXT: .LBB1_1: # %atomicrmw.start 39; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 40; CHECK-NEXT: vaq %v2, %v1, %v0 41; CHECK-NEXT: vlgvg %r1, %v2, 1 42; CHECK-NEXT: vlgvg %r0, %v2, 0 43; CHECK-NEXT: vlgvg %r5, %v1, 1 44; CHECK-NEXT: vlgvg %r4, %v1, 0 45; CHECK-NEXT: cdsg %r4, %r0, 0(%r3) 46; CHECK-NEXT: vlvgp %v1, %r4, %r5 47; CHECK-NEXT: jl .LBB1_1 48; CHECK-NEXT: # %bb.2: # %atomicrmw.end 49; CHECK-NEXT: vst %v1, 0(%r2), 3 50; CHECK-NEXT: br %r14 51 %res = atomicrmw add ptr %src, i128 %b seq_cst 52 ret i128 %res 53} 54 55; Check subtraction of a variable. 56define i128 @atomicrmw_sub(ptr %src, i128 %b) { 57; CHECK-LABEL: atomicrmw_sub: 58; CHECK: # %bb.0: 59; CHECK-NEXT: vl %v0, 0(%r4), 3 60; CHECK-NEXT: vl %v1, 0(%r3), 4 61; CHECK-NEXT: .LBB2_1: # %atomicrmw.start 62; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 63; CHECK-NEXT: vsq %v2, %v1, %v0 64; CHECK-NEXT: vlgvg %r1, %v2, 1 65; CHECK-NEXT: vlgvg %r0, %v2, 0 66; CHECK-NEXT: vlgvg %r5, %v1, 1 67; CHECK-NEXT: vlgvg %r4, %v1, 0 68; CHECK-NEXT: cdsg %r4, %r0, 0(%r3) 69; CHECK-NEXT: vlvgp %v1, %r4, %r5 70; CHECK-NEXT: jl .LBB2_1 71; CHECK-NEXT: # %bb.2: # %atomicrmw.end 72; CHECK-NEXT: vst %v1, 0(%r2), 3 73; CHECK-NEXT: br %r14 74 %res = atomicrmw sub ptr %src, i128 %b seq_cst 75 ret i128 %res 76} 77 78; Check AND of a variable. 79define i128 @atomicrmw_and(ptr %src, i128 %b) { 80; CHECK-LABEL: atomicrmw_and: 81; CHECK: # %bb.0: 82; CHECK-NEXT: vl %v0, 0(%r4), 3 83; CHECK-NEXT: vl %v1, 0(%r3), 4 84; CHECK-NEXT: .LBB3_1: # %atomicrmw.start 85; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 86; CHECK-NEXT: vn %v2, %v1, %v0 87; CHECK-NEXT: vlgvg %r1, %v2, 1 88; CHECK-NEXT: vlgvg %r0, %v2, 0 89; CHECK-NEXT: vlgvg %r5, %v1, 1 90; CHECK-NEXT: vlgvg %r4, %v1, 0 91; CHECK-NEXT: cdsg %r4, %r0, 0(%r3) 92; CHECK-NEXT: vlvgp %v1, %r4, %r5 93; CHECK-NEXT: jl .LBB3_1 94; CHECK-NEXT: # %bb.2: # %atomicrmw.end 95; CHECK-NEXT: vst %v1, 0(%r2), 3 96; CHECK-NEXT: br %r14 97 %res = atomicrmw and ptr %src, i128 %b seq_cst 98 ret i128 %res 99} 100 101; Check NAND of a variable. 102define i128 @atomicrmw_nand(ptr %src, i128 %b) { 103; CHECK-LABEL: atomicrmw_nand: 104; CHECK: # %bb.0: 105; CHECK-NEXT: vl %v0, 0(%r4), 3 106; CHECK-NEXT: vl %v1, 0(%r3), 4 107; CHECK-NEXT: .LBB4_1: # %atomicrmw.start 108; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 109; CHECK-NEXT: vlgvg %r1, %v1, 1 110; CHECK-NEXT: vlgvg %r0, %v1, 0 111; CHECK-NEXT: vnn %v1, %v1, %v0 112; CHECK-NEXT: vlgvg %r5, %v1, 1 113; CHECK-NEXT: vlgvg %r4, %v1, 0 114; CHECK-NEXT: cdsg %r0, %r4, 0(%r3) 115; CHECK-NEXT: vlvgp %v1, %r0, %r1 116; CHECK-NEXT: jl .LBB4_1 117; CHECK-NEXT: # %bb.2: # %atomicrmw.end 118; CHECK-NEXT: vst %v1, 0(%r2), 3 119; CHECK-NEXT: br %r14 120 %res = atomicrmw nand ptr %src, i128 %b seq_cst 121 ret i128 %res 122} 123 124; Check OR of a variable. 125define i128 @atomicrmw_or(ptr %src, i128 %b) { 126; CHECK-LABEL: atomicrmw_or: 127; CHECK: # %bb.0: 128; CHECK-NEXT: vl %v0, 0(%r4), 3 129; CHECK-NEXT: vl %v1, 0(%r3), 4 130; CHECK-NEXT: .LBB5_1: # %atomicrmw.start 131; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 132; CHECK-NEXT: vo %v2, %v1, %v0 133; CHECK-NEXT: vlgvg %r1, %v2, 1 134; CHECK-NEXT: vlgvg %r0, %v2, 0 135; CHECK-NEXT: vlgvg %r5, %v1, 1 136; CHECK-NEXT: vlgvg %r4, %v1, 0 137; CHECK-NEXT: cdsg %r4, %r0, 0(%r3) 138; CHECK-NEXT: vlvgp %v1, %r4, %r5 139; CHECK-NEXT: jl .LBB5_1 140; CHECK-NEXT: # %bb.2: # %atomicrmw.end 141; CHECK-NEXT: vst %v1, 0(%r2), 3 142; CHECK-NEXT: br %r14 143 %res = atomicrmw or ptr %src, i128 %b seq_cst 144 ret i128 %res 145} 146 147; Check XOR of a variable. 148define i128 @atomicrmw_xor(ptr %src, i128 %b) { 149; CHECK-LABEL: atomicrmw_xor: 150; CHECK: # %bb.0: 151; CHECK-NEXT: vl %v0, 0(%r4), 3 152; CHECK-NEXT: vl %v1, 0(%r3), 4 153; CHECK-NEXT: .LBB6_1: # %atomicrmw.start 154; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 155; CHECK-NEXT: vx %v2, %v1, %v0 156; CHECK-NEXT: vlgvg %r1, %v2, 1 157; CHECK-NEXT: vlgvg %r0, %v2, 0 158; CHECK-NEXT: vlgvg %r5, %v1, 1 159; CHECK-NEXT: vlgvg %r4, %v1, 0 160; CHECK-NEXT: cdsg %r4, %r0, 0(%r3) 161; CHECK-NEXT: vlvgp %v1, %r4, %r5 162; CHECK-NEXT: jl .LBB6_1 163; CHECK-NEXT: # %bb.2: # %atomicrmw.end 164; CHECK-NEXT: vst %v1, 0(%r2), 3 165; CHECK-NEXT: br %r14 166 %res = atomicrmw xor ptr %src, i128 %b seq_cst 167 ret i128 %res 168} 169 170; Check signed minimum. 171define i128 @atomicrmw_min(ptr %src, i128 %b) { 172; CHECK-LABEL: atomicrmw_min: 173; CHECK: # %bb.0: 174; CHECK-NEXT: vl %v0, 0(%r4), 3 175; CHECK-NEXT: vl %v1, 0(%r3), 4 176; CHECK-NEXT: j .LBB7_2 177; CHECK-NEXT: .LBB7_1: # %atomicrmw.start 178; CHECK-NEXT: # in Loop: Header=BB7_2 Depth=1 179; CHECK-NEXT: vlgvg %r1, %v1, 1 180; CHECK-NEXT: vlgvg %r0, %v1, 0 181; CHECK-NEXT: vlgvg %r5, %v2, 1 182; CHECK-NEXT: vlgvg %r4, %v2, 0 183; CHECK-NEXT: cdsg %r0, %r4, 0(%r3) 184; CHECK-NEXT: vlvgp %v1, %r0, %r1 185; CHECK-NEXT: je .LBB7_6 186; CHECK-NEXT: .LBB7_2: # %atomicrmw.start 187; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 188; CHECK-NEXT: vecg %v0, %v1 189; CHECK-NEXT: jlh .LBB7_4 190; CHECK-NEXT: # %bb.3: # %atomicrmw.start 191; CHECK-NEXT: # in Loop: Header=BB7_2 Depth=1 192; CHECK-NEXT: vchlgs %v2, %v1, %v0 193; CHECK-NEXT: .LBB7_4: # %atomicrmw.start 194; CHECK-NEXT: # in Loop: Header=BB7_2 Depth=1 195; CHECK-NEXT: vlr %v2, %v1 196; CHECK-NEXT: jnl .LBB7_1 197; CHECK-NEXT: # %bb.5: # %atomicrmw.start 198; CHECK-NEXT: # in Loop: Header=BB7_2 Depth=1 199; CHECK-NEXT: vlr %v2, %v0 200; CHECK-NEXT: j .LBB7_1 201; CHECK-NEXT: .LBB7_6: # %atomicrmw.end 202; CHECK-NEXT: vst %v1, 0(%r2), 3 203; CHECK-NEXT: br %r14 204 %res = atomicrmw min ptr %src, i128 %b seq_cst 205 ret i128 %res 206} 207 208; Check signed maximum. 209define i128 @atomicrmw_max(ptr %src, i128 %b) { 210; CHECK-LABEL: atomicrmw_max: 211; CHECK: # %bb.0: 212; CHECK-NEXT: vl %v0, 0(%r4), 3 213; CHECK-NEXT: vl %v1, 0(%r3), 4 214; CHECK-NEXT: j .LBB8_2 215; CHECK-NEXT: .LBB8_1: # %atomicrmw.start 216; CHECK-NEXT: # in Loop: Header=BB8_2 Depth=1 217; CHECK-NEXT: vlgvg %r1, %v1, 1 218; CHECK-NEXT: vlgvg %r0, %v1, 0 219; CHECK-NEXT: vlgvg %r5, %v2, 1 220; CHECK-NEXT: vlgvg %r4, %v2, 0 221; CHECK-NEXT: cdsg %r0, %r4, 0(%r3) 222; CHECK-NEXT: vlvgp %v1, %r0, %r1 223; CHECK-NEXT: je .LBB8_6 224; CHECK-NEXT: .LBB8_2: # %atomicrmw.start 225; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 226; CHECK-NEXT: vecg %v0, %v1 227; CHECK-NEXT: jlh .LBB8_4 228; CHECK-NEXT: # %bb.3: # %atomicrmw.start 229; CHECK-NEXT: # in Loop: Header=BB8_2 Depth=1 230; CHECK-NEXT: vchlgs %v2, %v1, %v0 231; CHECK-NEXT: .LBB8_4: # %atomicrmw.start 232; CHECK-NEXT: # in Loop: Header=BB8_2 Depth=1 233; CHECK-NEXT: vlr %v2, %v1 234; CHECK-NEXT: jl .LBB8_1 235; CHECK-NEXT: # %bb.5: # %atomicrmw.start 236; CHECK-NEXT: # in Loop: Header=BB8_2 Depth=1 237; CHECK-NEXT: vlr %v2, %v0 238; CHECK-NEXT: j .LBB8_1 239; CHECK-NEXT: .LBB8_6: # %atomicrmw.end 240; CHECK-NEXT: vst %v1, 0(%r2), 3 241; CHECK-NEXT: br %r14 242 %res = atomicrmw max ptr %src, i128 %b seq_cst 243 ret i128 %res 244} 245 246; Check unsigned minimum. 247define i128 @atomicrmw_umin(ptr %src, i128 %b) { 248; CHECK-LABEL: atomicrmw_umin: 249; CHECK: # %bb.0: 250; CHECK-NEXT: vl %v0, 0(%r4), 3 251; CHECK-NEXT: vl %v1, 0(%r3), 4 252; CHECK-NEXT: j .LBB9_2 253; CHECK-NEXT: .LBB9_1: # %atomicrmw.start 254; CHECK-NEXT: # in Loop: Header=BB9_2 Depth=1 255; CHECK-NEXT: vlgvg %r1, %v1, 1 256; CHECK-NEXT: vlgvg %r0, %v1, 0 257; CHECK-NEXT: vlgvg %r5, %v2, 1 258; CHECK-NEXT: vlgvg %r4, %v2, 0 259; CHECK-NEXT: cdsg %r0, %r4, 0(%r3) 260; CHECK-NEXT: vlvgp %v1, %r0, %r1 261; CHECK-NEXT: je .LBB9_6 262; CHECK-NEXT: .LBB9_2: # %atomicrmw.start 263; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 264; CHECK-NEXT: veclg %v0, %v1 265; CHECK-NEXT: jlh .LBB9_4 266; CHECK-NEXT: # %bb.3: # %atomicrmw.start 267; CHECK-NEXT: # in Loop: Header=BB9_2 Depth=1 268; CHECK-NEXT: vchlgs %v2, %v1, %v0 269; CHECK-NEXT: .LBB9_4: # %atomicrmw.start 270; CHECK-NEXT: # in Loop: Header=BB9_2 Depth=1 271; CHECK-NEXT: vlr %v2, %v1 272; CHECK-NEXT: jnl .LBB9_1 273; CHECK-NEXT: # %bb.5: # %atomicrmw.start 274; CHECK-NEXT: # in Loop: Header=BB9_2 Depth=1 275; CHECK-NEXT: vlr %v2, %v0 276; CHECK-NEXT: j .LBB9_1 277; CHECK-NEXT: .LBB9_6: # %atomicrmw.end 278; CHECK-NEXT: vst %v1, 0(%r2), 3 279; CHECK-NEXT: br %r14 280 %res = atomicrmw umin ptr %src, i128 %b seq_cst 281 ret i128 %res 282} 283 284; Check unsigned maximum. 285define i128 @atomicrmw_umax(ptr %src, i128 %b) { 286; CHECK-LABEL: atomicrmw_umax: 287; CHECK: # %bb.0: 288; CHECK-NEXT: vl %v0, 0(%r4), 3 289; CHECK-NEXT: vl %v1, 0(%r3), 4 290; CHECK-NEXT: j .LBB10_2 291; CHECK-NEXT: .LBB10_1: # %atomicrmw.start 292; CHECK-NEXT: # in Loop: Header=BB10_2 Depth=1 293; CHECK-NEXT: vlgvg %r1, %v1, 1 294; CHECK-NEXT: vlgvg %r0, %v1, 0 295; CHECK-NEXT: vlgvg %r5, %v2, 1 296; CHECK-NEXT: vlgvg %r4, %v2, 0 297; CHECK-NEXT: cdsg %r0, %r4, 0(%r3) 298; CHECK-NEXT: vlvgp %v1, %r0, %r1 299; CHECK-NEXT: je .LBB10_6 300; CHECK-NEXT: .LBB10_2: # %atomicrmw.start 301; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 302; CHECK-NEXT: veclg %v0, %v1 303; CHECK-NEXT: jlh .LBB10_4 304; CHECK-NEXT: # %bb.3: # %atomicrmw.start 305; CHECK-NEXT: # in Loop: Header=BB10_2 Depth=1 306; CHECK-NEXT: vchlgs %v2, %v1, %v0 307; CHECK-NEXT: .LBB10_4: # %atomicrmw.start 308; CHECK-NEXT: # in Loop: Header=BB10_2 Depth=1 309; CHECK-NEXT: vlr %v2, %v1 310; CHECK-NEXT: jl .LBB10_1 311; CHECK-NEXT: # %bb.5: # %atomicrmw.start 312; CHECK-NEXT: # in Loop: Header=BB10_2 Depth=1 313; CHECK-NEXT: vlr %v2, %v0 314; CHECK-NEXT: j .LBB10_1 315; CHECK-NEXT: .LBB10_6: # %atomicrmw.end 316; CHECK-NEXT: vst %v1, 0(%r2), 3 317; CHECK-NEXT: br %r14 318 %res = atomicrmw umax ptr %src, i128 %b seq_cst 319 ret i128 %res 320} 321 322; Check increment with wraparound. 323define i128 @atomicrmw_uinc_wrap(ptr %src, i128 %b) { 324; CHECK-LABEL: atomicrmw_uinc_wrap: 325; CHECK: # %bb.0: 326; CHECK-NEXT: larl %r1, .LCPI11_0 327; CHECK-NEXT: vl %v0, 0(%r4), 3 328; CHECK-NEXT: vl %v2, 0(%r3), 4 329; CHECK-NEXT: vl %v1, 0(%r1), 3 330; CHECK-NEXT: j .LBB11_2 331; CHECK-NEXT: .LBB11_1: # %atomicrmw.start 332; CHECK-NEXT: # in Loop: Header=BB11_2 Depth=1 333; CHECK-NEXT: vlgvg %r1, %v2, 1 334; CHECK-NEXT: vlgvg %r0, %v2, 0 335; CHECK-NEXT: vlgvg %r5, %v3, 1 336; CHECK-NEXT: vlgvg %r4, %v3, 0 337; CHECK-NEXT: cdsg %r0, %r4, 0(%r3) 338; CHECK-NEXT: vlvgp %v2, %r0, %r1 339; CHECK-NEXT: je .LBB11_6 340; CHECK-NEXT: .LBB11_2: # %atomicrmw.start 341; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 342; CHECK-NEXT: veclg %v2, %v0 343; CHECK-NEXT: jlh .LBB11_4 344; CHECK-NEXT: # %bb.3: # %atomicrmw.start 345; CHECK-NEXT: # in Loop: Header=BB11_2 Depth=1 346; CHECK-NEXT: vchlgs %v3, %v0, %v2 347; CHECK-NEXT: .LBB11_4: # %atomicrmw.start 348; CHECK-NEXT: # in Loop: Header=BB11_2 Depth=1 349; CHECK-NEXT: vgbm %v3, 0 350; CHECK-NEXT: jnl .LBB11_1 351; CHECK-NEXT: # %bb.5: # %atomicrmw.start 352; CHECK-NEXT: # in Loop: Header=BB11_2 Depth=1 353; CHECK-NEXT: vaq %v3, %v2, %v1 354; CHECK-NEXT: j .LBB11_1 355; CHECK-NEXT: .LBB11_6: # %atomicrmw.end 356; CHECK-NEXT: vst %v2, 0(%r2), 3 357; CHECK-NEXT: br %r14 358 %res = atomicrmw uinc_wrap ptr %src, i128 %b seq_cst 359 ret i128 %res 360} 361 362; Check decrement with wraparound. 363define i128 @atomicrmw_udec_wrap(ptr %src, i128 %b) { 364; CHECK-LABEL: atomicrmw_udec_wrap: 365; CHECK: # %bb.0: 366; CHECK-NEXT: vl %v0, 0(%r4), 3 367; CHECK-NEXT: vl %v3, 0(%r3), 4 368; CHECK-NEXT: vgbm %v1, 65535 369; CHECK-NEXT: vgbm %v2, 0 370; CHECK-NEXT: j .LBB12_2 371; CHECK-NEXT: .LBB12_1: # %atomicrmw.start 372; CHECK-NEXT: # in Loop: Header=BB12_2 Depth=1 373; CHECK-NEXT: vlgvg %r1, %v3, 1 374; CHECK-NEXT: vlgvg %r0, %v3, 0 375; CHECK-NEXT: vlgvg %r5, %v5, 1 376; CHECK-NEXT: vlgvg %r4, %v5, 0 377; CHECK-NEXT: cdsg %r0, %r4, 0(%r3) 378; CHECK-NEXT: vlvgp %v3, %r0, %r1 379; CHECK-NEXT: je .LBB12_8 380; CHECK-NEXT: .LBB12_2: # %atomicrmw.start 381; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 382; CHECK-NEXT: veclg %v0, %v3 383; CHECK-NEXT: jlh .LBB12_4 384; CHECK-NEXT: # %bb.3: # %atomicrmw.start 385; CHECK-NEXT: # in Loop: Header=BB12_2 Depth=1 386; CHECK-NEXT: vchlgs %v4, %v3, %v0 387; CHECK-NEXT: .LBB12_4: # %atomicrmw.start 388; CHECK-NEXT: # in Loop: Header=BB12_2 Depth=1 389; CHECK-NEXT: vlr %v4, %v0 390; CHECK-NEXT: jl .LBB12_6 391; CHECK-NEXT: # %bb.5: # %atomicrmw.start 392; CHECK-NEXT: # in Loop: Header=BB12_2 Depth=1 393; CHECK-NEXT: vaq %v4, %v3, %v1 394; CHECK-NEXT: .LBB12_6: # %atomicrmw.start 395; CHECK-NEXT: # in Loop: Header=BB12_2 Depth=1 396; CHECK-NEXT: vceqgs %v5, %v3, %v2 397; CHECK-NEXT: vlr %v5, %v0 398; CHECK-NEXT: je .LBB12_1 399; CHECK-NEXT: # %bb.7: # %atomicrmw.start 400; CHECK-NEXT: # in Loop: Header=BB12_2 Depth=1 401; CHECK-NEXT: vlr %v5, %v4 402; CHECK-NEXT: j .LBB12_1 403; CHECK-NEXT: .LBB12_8: # %atomicrmw.end 404; CHECK-NEXT: vst %v3, 0(%r2), 3 405; CHECK-NEXT: br %r14 406 %res = atomicrmw udec_wrap ptr %src, i128 %b seq_cst 407 ret i128 %res 408} 409