1 ; Test transactional-execution intrinsics. 2 ; 3 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 | FileCheck %s 4 5 declare i32 @llvm.s390.tbegin(i8 *, i32) 6 declare i32 @llvm.s390.tbegin.nofloat(i8 *, i32) 7 declare void @llvm.s390.tbeginc(i8 *, i32) 8 declare i32 @llvm.s390.tend() 9 declare void @llvm.s390.tabort(i64) 10 declare void @llvm.s390.ntstg(i64, i64 *) 11 declare i32 @llvm.s390.etnd() 12 declare void @llvm.s390.ppa.txassist(i32) 13 14 ; TBEGIN. 15 define 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). 41 define 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. 52 define 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. 65 define 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: jnh {{\.L*}} 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 77 if.then: ; preds = %entry 78 store i32 0, i32* %ptr, align 4 79 br label %if.end 80 81 if.end: ; preds = %if.then, %entry 82 ret void 83 } 84 85 ; TBEGIN (nofloat) with dual CC use. 86 define 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: cijlh %r2, 2, {{\.L*}} 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 100 if.then: ; preds = %entry 101 store i32 0, i32* %ptr, align 4 102 br label %if.end 103 104 if.end: ; preds = %if.then, %entry 105 ret i32 %res 106 } 107 108 ; TBEGIN (nofloat) with register. 109 define 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. 120 define 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. 131 define 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. 142 define 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. 153 define 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. 164 define 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. 176 define 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. 187 define 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. 198 define void @test_tend3(i32 *%ptr) { 199 ; CHECK-LABEL: test_tend3: 200 ; CHECK: tend 201 ; CHECK: je {{\.L*}} 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 208 if.then: ; preds = %entry 209 store i32 0, i32* %ptr, align 4 210 br label %if.end 211 212 if.end: ; preds = %if.then, %entry 213 ret void 214 } 215 216 ; TEND with dual CC use. 217 define 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: cijlh %r2, 2, {{\.L*}} 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 229 if.then: ; preds = %entry 230 store i32 0, i32* %ptr, align 4 231 br label %if.end 232 233 if.end: ; preds = %if.then, %entry 234 ret i32 %res 235 } 236 237 ; TABORT with register only. 238 define 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. 247 define 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. 256 define 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. 266 define 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. 275 define 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. 285 define 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. 296 define 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. 306 define 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. 316 define 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. 326 define 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. 336 define 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) 345 define 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