Home | History | Annotate | Download | only in SystemZ
      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