1 ; Test STOCFHs that are presented as selects. 2 ; See comments in asm-18.ll about testing high-word operations. 3 ; 4 ; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -mcpu=z13 \ 5 ; RUN: -no-integrated-as | FileCheck %s 6 7 declare void @foo(i32 *) 8 9 ; Test the simple case, with the loaded value first. 10 define void @f1(i32 *%ptr, i32 %limit) { 11 ; CHECK-LABEL: f1: 12 ; CHECK-DAG: stepa [[REG:%r[0-5]]] 13 ; CHECK-DAG: clfi %r3, 42 14 ; CHECK: stocfhhe [[REG]], 0(%r2) 15 ; CHECK: br %r14 16 %alt = call i32 asm "stepa $0", "=h"() 17 %cond = icmp ult i32 %limit, 42 18 %orig = load i32, i32 *%ptr 19 %res = select i1 %cond, i32 %orig, i32 %alt 20 store i32 %res, i32 *%ptr 21 ret void 22 } 23 24 ; ...and with the loaded value second 25 define void @f2(i32 *%ptr, i32 %limit) { 26 ; CHECK-LABEL: f2: 27 ; CHECK-DAG: stepa [[REG:%r[0-5]]] 28 ; CHECK-DAG: clfi %r3, 42 29 ; CHECK: stocfhl [[REG]], 0(%r2) 30 ; CHECK: br %r14 31 %alt = call i32 asm "stepa $0", "=h"() 32 %cond = icmp ult i32 %limit, 42 33 %orig = load i32, i32 *%ptr 34 %res = select i1 %cond, i32 %alt, i32 %orig 35 store i32 %res, i32 *%ptr 36 ret void 37 } 38 39 ; Check the high end of the aligned STOC range. 40 define void @f3(i32 *%base, i32 %limit) { 41 ; CHECK-LABEL: f3: 42 ; CHECK-DAG: stepa [[REG:%r[0-5]]] 43 ; CHECK-DAG: clfi %r3, 42 44 ; CHECK: stocfhhe [[REG]], 524284(%r2) 45 ; CHECK: br %r14 46 %alt = call i32 asm "stepa $0", "=h"() 47 %ptr = getelementptr i32, i32 *%base, i64 131071 48 %cond = icmp ult i32 %limit, 42 49 %orig = load i32, i32 *%ptr 50 %res = select i1 %cond, i32 %orig, i32 %alt 51 store i32 %res, i32 *%ptr 52 ret void 53 } 54 55 ; Check the next word up. Other sequences besides this one would be OK. 56 define void @f4(i32 *%base, i32 %limit) { 57 ; CHECK-LABEL: f4: 58 ; CHECK-DAG: stepa [[REG:%r[0-5]]] 59 ; CHECK-DAG: agfi %r2, 524288 60 ; CHECK-DAG: clfi %r3, 42 61 ; CHECK: stocfhhe [[REG]], 0(%r2) 62 ; CHECK: br %r14 63 %alt = call i32 asm "stepa $0", "=h"() 64 %ptr = getelementptr i32, i32 *%base, i64 131072 65 %cond = icmp ult i32 %limit, 42 66 %orig = load i32, i32 *%ptr 67 %res = select i1 %cond, i32 %orig, i32 %alt 68 store i32 %res, i32 *%ptr 69 ret void 70 } 71 72 ; Check the low end of the STOC range. 73 define void @f5(i32 *%base, i32 %limit) { 74 ; CHECK-LABEL: f5: 75 ; CHECK-DAG: stepa [[REG:%r[0-5]]] 76 ; CHECK-DAG: clfi %r3, 42 77 ; CHECK: stocfhhe [[REG]], -524288(%r2) 78 ; CHECK: br %r14 79 %alt = call i32 asm "stepa $0", "=h"() 80 %ptr = getelementptr i32, i32 *%base, i64 -131072 81 %cond = icmp ult i32 %limit, 42 82 %orig = load i32, i32 *%ptr 83 %res = select i1 %cond, i32 %orig, i32 %alt 84 store i32 %res, i32 *%ptr 85 ret void 86 } 87 88 ; Check the next word down, with the same comments as f8. 89 define void @f6(i32 *%base, i32 %limit) { 90 ; CHECK-LABEL: f6: 91 ; CHECK-DAG: stepa [[REG:%r[0-5]]] 92 ; CHECK-DAG: agfi %r2, -524292 93 ; CHECK-DAG: clfi %r3, 42 94 ; CHECK: stocfhhe [[REG]], 0(%r2) 95 ; CHECK: br %r14 96 %alt = call i32 asm "stepa $0", "=h"() 97 %ptr = getelementptr i32, i32 *%base, i64 -131073 98 %cond = icmp ult i32 %limit, 42 99 %orig = load i32, i32 *%ptr 100 %res = select i1 %cond, i32 %orig, i32 %alt 101 store i32 %res, i32 *%ptr 102 ret void 103 } 104 105 ; Try a frame index base. 106 define void @f7(i32 %limit) { 107 ; CHECK-LABEL: f7: 108 ; CHECK: brasl %r14, foo@PLT 109 ; CHECK: stepa [[REG:%r[0-5]]] 110 ; CHECK: stocfhhe [[REG]], {{[0-9]+}}(%r15) 111 ; CHECK: brasl %r14, foo@PLT 112 ; CHECK: br %r14 113 %ptr = alloca i32 114 call void @foo(i32 *%ptr) 115 %alt = call i32 asm "stepa $0", "=h"() 116 %cond = icmp ult i32 %limit, 42 117 %orig = load i32, i32 *%ptr 118 %res = select i1 %cond, i32 %orig, i32 %alt 119 store i32 %res, i32 *%ptr 120 call void @foo(i32 *%ptr) 121 ret void 122 } 123 124 ; Test that conditionally-executed stores do not use STOC, since STOC 125 ; is allowed to trap even when the condition is false. 126 define void @f8(i32 %a, i32 %b, i32 *%dest) { 127 ; CHECK-LABEL: f8: 128 ; CHECK-NOT: stoc 129 ; CHECK: stfh 130 ; CHECK: br %r14 131 entry: 132 %val = call i32 asm "stepa $0", "=h"() 133 %cmp = icmp ule i32 %a, %b 134 br i1 %cmp, label %store, label %exit 135 136 store: 137 store i32 %val, i32 *%dest 138 br label %exit 139 140 exit: 141 ret void 142 } 143