1; Test transactional-execution intrinsics. 2; 3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 | FileCheck %s 4 5declare i32 @llvm.s390.tbegin(i8 *, i32) 6declare i32 @llvm.s390.tbegin.nofloat(i8 *, i32) 7declare void @llvm.s390.tbeginc(i8 *, i32) 8declare i32 @llvm.s390.tend() 9declare void @llvm.s390.tabort(i64) 10declare void @llvm.s390.ntstg(i64, i64 *) 11declare i32 @llvm.s390.etnd() 12declare void @llvm.s390.ppa.txassist(i32) 13 14; TBEGIN. 15define void @test_tbegin() { 16; CHECK-LABEL: test_tbegin: 17; CHECK-NOT: stmg 18; CHECK: std %f8, 19; CHECK: std %f9, 20; CHECK: std %f10, 21; CHECK: std %f11, 22; CHECK: std %f12, 23; CHECK: std %f13, 24; CHECK: std %f14, 25; CHECK: std %f15, 26; CHECK: tbegin 0, 65292 27; CHECK: ld %f8, 28; CHECK: ld %f9, 29; CHECK: ld %f10, 30; CHECK: ld %f11, 31; CHECK: ld %f12, 32; CHECK: ld %f13, 33; CHECK: ld %f14, 34; CHECK: ld %f15, 35; CHECK: br %r14 36 call i32 @llvm.s390.tbegin(i8 *null, i32 65292) 37 ret void 38} 39 40; TBEGIN (nofloat). 41define void @test_tbegin_nofloat1() { 42; CHECK-LABEL: test_tbegin_nofloat1: 43; CHECK-NOT: stmg 44; CHECK-NOT: std 45; CHECK: tbegin 0, 65292 46; CHECK: br %r14 47 call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) 48 ret void 49} 50 51; TBEGIN (nofloat) with integer CC return value. 52define i32 @test_tbegin_nofloat2() { 53; CHECK-LABEL: test_tbegin_nofloat2: 54; CHECK-NOT: stmg 55; CHECK-NOT: std 56; CHECK: tbegin 0, 65292 57; CHECK: ipm %r2 58; CHECK: srl %r2, 28 59; CHECK: br %r14 60 %res = call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) 61 ret i32 %res 62} 63 64; TBEGIN (nofloat) with implicit CC check. 65define void @test_tbegin_nofloat3(i32 *%ptr) { 66; CHECK-LABEL: test_tbegin_nofloat3: 67; CHECK-NOT: stmg 68; CHECK-NOT: std 69; CHECK: tbegin 0, 65292 70; CHECK: bnhr %r14 71; CHECK: mvhi 0(%r2), 0 72; CHECK: br %r14 73 %res = call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) 74 %cmp = icmp eq i32 %res, 2 75 br i1 %cmp, label %if.then, label %if.end 76 77if.then: ; preds = %entry 78 store i32 0, i32* %ptr, align 4 79 br label %if.end 80 81if.end: ; preds = %if.then, %entry 82 ret void 83} 84 85; TBEGIN (nofloat) with dual CC use. 86define i32 @test_tbegin_nofloat4(i32 %pad, i32 *%ptr) { 87; CHECK-LABEL: test_tbegin_nofloat4: 88; CHECK-NOT: stmg 89; CHECK-NOT: std 90; CHECK: tbegin 0, 65292 91; CHECK: ipm %r2 92; CHECK: srl %r2, 28 93; CHECK: ciblh %r2, 2, 0(%r14) 94; CHECK: mvhi 0(%r3), 0 95; CHECK: br %r14 96 %res = call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) 97 %cmp = icmp eq i32 %res, 2 98 br i1 %cmp, label %if.then, label %if.end 99 100if.then: ; preds = %entry 101 store i32 0, i32* %ptr, align 4 102 br label %if.end 103 104if.end: ; preds = %if.then, %entry 105 ret i32 %res 106} 107 108; TBEGIN (nofloat) with register. 109define void @test_tbegin_nofloat5(i8 *%ptr) { 110; CHECK-LABEL: test_tbegin_nofloat5: 111; CHECK-NOT: stmg 112; CHECK-NOT: std 113; CHECK: tbegin 0(%r2), 65292 114; CHECK: br %r14 115 call i32 @llvm.s390.tbegin.nofloat(i8 *%ptr, i32 65292) 116 ret void 117} 118 119; TBEGIN (nofloat) with GRSM 0x0f00. 120define void @test_tbegin_nofloat6() { 121; CHECK-LABEL: test_tbegin_nofloat6: 122; CHECK: stmg %r6, %r15, 123; CHECK-NOT: std 124; CHECK: tbegin 0, 3840 125; CHECK: br %r14 126 call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 3840) 127 ret void 128} 129 130; TBEGIN (nofloat) with GRSM 0xf100. 131define void @test_tbegin_nofloat7() { 132; CHECK-LABEL: test_tbegin_nofloat7: 133; CHECK: stmg %r8, %r15, 134; CHECK-NOT: std 135; CHECK: tbegin 0, 61696 136; CHECK: br %r14 137 call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 61696) 138 ret void 139} 140 141; TBEGIN (nofloat) with GRSM 0xfe00 -- stack pointer added automatically. 142define void @test_tbegin_nofloat8() { 143; CHECK-LABEL: test_tbegin_nofloat8: 144; CHECK-NOT: stmg 145; CHECK-NOT: std 146; CHECK: tbegin 0, 65280 147; CHECK: br %r14 148 call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65024) 149 ret void 150} 151 152; TBEGIN (nofloat) with GRSM 0xfb00 -- no frame pointer needed. 153define void @test_tbegin_nofloat9() { 154; CHECK-LABEL: test_tbegin_nofloat9: 155; CHECK: stmg %r10, %r15, 156; CHECK-NOT: std 157; CHECK: tbegin 0, 64256 158; CHECK: br %r14 159 call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 64256) 160 ret void 161} 162 163; TBEGIN (nofloat) with GRSM 0xfb00 -- frame pointer added automatically. 164define void @test_tbegin_nofloat10(i64 %n) { 165; CHECK-LABEL: test_tbegin_nofloat10: 166; CHECK: stmg %r11, %r15, 167; CHECK-NOT: std 168; CHECK: tbegin 0, 65280 169; CHECK: br %r14 170 %buf = alloca i8, i64 %n 171 call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 64256) 172 ret void 173} 174 175; TBEGINC. 176define void @test_tbeginc() { 177; CHECK-LABEL: test_tbeginc: 178; CHECK-NOT: stmg 179; CHECK-NOT: std 180; CHECK: tbeginc 0, 65288 181; CHECK: br %r14 182 call void @llvm.s390.tbeginc(i8 *null, i32 65288) 183 ret void 184} 185 186; TEND with integer CC return value. 187define i32 @test_tend1() { 188; CHECK-LABEL: test_tend1: 189; CHECK: tend 190; CHECK: ipm %r2 191; CHECK: srl %r2, 28 192; CHECK: br %r14 193 %res = call i32 @llvm.s390.tend() 194 ret i32 %res 195} 196 197; TEND with implicit CC check. 198define void @test_tend3(i32 *%ptr) { 199; CHECK-LABEL: test_tend3: 200; CHECK: tend 201; CHECK: ber %r14 202; CHECK: mvhi 0(%r2), 0 203; CHECK: br %r14 204 %res = call i32 @llvm.s390.tend() 205 %cmp = icmp eq i32 %res, 2 206 br i1 %cmp, label %if.then, label %if.end 207 208if.then: ; preds = %entry 209 store i32 0, i32* %ptr, align 4 210 br label %if.end 211 212if.end: ; preds = %if.then, %entry 213 ret void 214} 215 216; TEND with dual CC use. 217define i32 @test_tend2(i32 %pad, i32 *%ptr) { 218; CHECK-LABEL: test_tend2: 219; CHECK: tend 220; CHECK: ipm %r2 221; CHECK: srl %r2, 28 222; CHECK: ciblh %r2, 2, 0(%r14) 223; CHECK: mvhi 0(%r3), 0 224; CHECK: br %r14 225 %res = call i32 @llvm.s390.tend() 226 %cmp = icmp eq i32 %res, 2 227 br i1 %cmp, label %if.then, label %if.end 228 229if.then: ; preds = %entry 230 store i32 0, i32* %ptr, align 4 231 br label %if.end 232 233if.end: ; preds = %if.then, %entry 234 ret i32 %res 235} 236 237; TABORT with register only. 238define void @test_tabort1(i64 %val) { 239; CHECK-LABEL: test_tabort1: 240; CHECK: tabort 0(%r2) 241; CHECK: br %r14 242 call void @llvm.s390.tabort(i64 %val) 243 ret void 244} 245 246; TABORT with immediate only. 247define void @test_tabort2(i64 %val) { 248; CHECK-LABEL: test_tabort2: 249; CHECK: tabort 1234 250; CHECK: br %r14 251 call void @llvm.s390.tabort(i64 1234) 252 ret void 253} 254 255; TABORT with register + immediate. 256define void @test_tabort3(i64 %val) { 257; CHECK-LABEL: test_tabort3: 258; CHECK: tabort 1234(%r2) 259; CHECK: br %r14 260 %sum = add i64 %val, 1234 261 call void @llvm.s390.tabort(i64 %sum) 262 ret void 263} 264 265; TABORT with out-of-range immediate. 266define void @test_tabort4(i64 %val) { 267; CHECK-LABEL: test_tabort4: 268; CHECK: tabort 0({{%r[1-5]}}) 269; CHECK: br %r14 270 call void @llvm.s390.tabort(i64 4096) 271 ret void 272} 273 274; NTSTG with base pointer only. 275define void @test_ntstg1(i64 *%ptr, i64 %val) { 276; CHECK-LABEL: test_ntstg1: 277; CHECK: ntstg %r3, 0(%r2) 278; CHECK: br %r14 279 call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) 280 ret void 281} 282 283; NTSTG with base and index. 284; Check that VSTL doesn't allow an index. 285define void @test_ntstg2(i64 *%base, i64 %index, i64 %val) { 286; CHECK-LABEL: test_ntstg2: 287; CHECK: sllg [[REG:%r[1-5]]], %r3, 3 288; CHECK: ntstg %r4, 0([[REG]],%r2) 289; CHECK: br %r14 290 %ptr = getelementptr i64, i64 *%base, i64 %index 291 call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) 292 ret void 293} 294 295; NTSTG with the highest in-range displacement. 296define void @test_ntstg3(i64 *%base, i64 %val) { 297; CHECK-LABEL: test_ntstg3: 298; CHECK: ntstg %r3, 524280(%r2) 299; CHECK: br %r14 300 %ptr = getelementptr i64, i64 *%base, i64 65535 301 call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) 302 ret void 303} 304 305; NTSTG with an out-of-range positive displacement. 306define void @test_ntstg4(i64 *%base, i64 %val) { 307; CHECK-LABEL: test_ntstg4: 308; CHECK: ntstg %r3, 0({{%r[1-5]}}) 309; CHECK: br %r14 310 %ptr = getelementptr i64, i64 *%base, i64 65536 311 call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) 312 ret void 313} 314 315; NTSTG with the lowest in-range displacement. 316define void @test_ntstg5(i64 *%base, i64 %val) { 317; CHECK-LABEL: test_ntstg5: 318; CHECK: ntstg %r3, -524288(%r2) 319; CHECK: br %r14 320 %ptr = getelementptr i64, i64 *%base, i64 -65536 321 call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) 322 ret void 323} 324 325; NTSTG with an out-of-range negative displacement. 326define void @test_ntstg6(i64 *%base, i64 %val) { 327; CHECK-LABEL: test_ntstg6: 328; CHECK: ntstg %r3, 0({{%r[1-5]}}) 329; CHECK: br %r14 330 %ptr = getelementptr i64, i64 *%base, i64 -65537 331 call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) 332 ret void 333} 334 335; ETND. 336define i32 @test_etnd() { 337; CHECK-LABEL: test_etnd: 338; CHECK: etnd %r2 339; CHECK: br %r14 340 %res = call i32 @llvm.s390.etnd() 341 ret i32 %res 342} 343 344; PPA (Transaction-Abort Assist) 345define void @test_ppa_txassist(i32 %val) { 346; CHECK-LABEL: test_ppa_txassist: 347; CHECK: ppa %r2, 0, 1 348; CHECK: br %r14 349 call void @llvm.s390.ppa.txassist(i32 %val) 350 ret void 351} 352 353