1; Test 128-bit compare and swap. 2; 3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z10 4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z13 5 6; Check CDSG without a displacement. 7define i128 @f1(i128 %cmp, i128 %swap, ptr %src) { 8; CHECK-LABEL: f1: 9; CHECK-DAG: lg %r1, 8(%r4) 10; CHECK-DAG: lg %r0, 0(%r4) 11; CHECK-DAG: lg %r13, 8(%r3) 12; CHECK-DAG: lg %r12, 0(%r3) 13; CHECK: cdsg %r12, %r0, 0(%r5) 14; CHECK-DAG: stg %r13, 8(%r2) 15; CHECK-DAG: stg %r12, 0(%r2) 16; CHECK: br %r14 17 %pairval = cmpxchg ptr %src, i128 %cmp, i128 %swap seq_cst seq_cst 18 %val = extractvalue { i128, i1 } %pairval, 0 19 ret i128 %val 20} 21 22; Check the high end of the aligned CDSG range. 23define i128 @f2(i128 %cmp, i128 %swap, ptr %src) { 24; CHECK-LABEL: f2: 25; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 524272(%r5) 26; CHECK: br %r14 27 %ptr = getelementptr i128, ptr %src, i128 32767 28 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 %swap seq_cst seq_cst 29 %val = extractvalue { i128, i1 } %pairval, 0 30 ret i128 %val 31} 32 33; Check the next doubleword up, which needs separate address logic. 34; Other sequences besides this one would be OK. 35define i128 @f3(i128 %cmp, i128 %swap, ptr %src) { 36; CHECK-LABEL: f3: 37; CHECK: agfi %r5, 524288 38; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5) 39; CHECK: br %r14 40 %ptr = getelementptr i128, ptr %src, i128 32768 41 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 %swap seq_cst seq_cst 42 %val = extractvalue { i128, i1 } %pairval, 0 43 ret i128 %val 44} 45 46; Check the high end of the negative aligned CDSG range. 47define i128 @f4(i128 %cmp, i128 %swap, ptr %src) { 48; CHECK-LABEL: f4: 49; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, -16(%r5) 50; CHECK: br %r14 51 %ptr = getelementptr i128, ptr %src, i128 -1 52 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 %swap seq_cst seq_cst 53 %val = extractvalue { i128, i1 } %pairval, 0 54 ret i128 %val 55} 56 57; Check the low end of the CDSG range. 58define i128 @f5(i128 %cmp, i128 %swap, ptr %src) { 59; CHECK-LABEL: f5: 60; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, -524288(%r5) 61; CHECK: br %r14 62 %ptr = getelementptr i128, ptr %src, i128 -32768 63 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 %swap seq_cst seq_cst 64 %val = extractvalue { i128, i1 } %pairval, 0 65 ret i128 %val 66} 67 68; Check the next doubleword down, which needs separate address logic. 69; Other sequences besides this one would be OK. 70define i128 @f6(i128 %cmp, i128 %swap, ptr %src) { 71; CHECK-LABEL: f6: 72; CHECK: agfi %r5, -524304 73; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5) 74; CHECK: br %r14 75 %ptr = getelementptr i128, ptr %src, i128 -32769 76 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 %swap seq_cst seq_cst 77 %val = extractvalue { i128, i1 } %pairval, 0 78 ret i128 %val 79} 80 81; Check that CDSG does not allow an index. 82define i128 @f7(i128 %cmp, i128 %swap, i64 %src, i64 %index) { 83; CHECK-LABEL: f7: 84; CHECK: agr %r5, %r6 85; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5) 86; CHECK: br %r14 87 %add1 = add i64 %src, %index 88 %ptr = inttoptr i64 %add1 to ptr 89 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 %swap seq_cst seq_cst 90 %val = extractvalue { i128, i1 } %pairval, 0 91 ret i128 %val 92} 93 94; Check that a constant %cmp value is loaded into a register first. 95define i128 @f8(i128 %swap, ptr %ptr) { 96; CHECK-LABEL: f8: 97; CHECK: lghi {{%r[0-9]+}}, 1001 98; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r4) 99; CHECK: br %r14 100 %pairval = cmpxchg ptr %ptr, i128 1001, i128 %swap seq_cst seq_cst 101 %val = extractvalue { i128, i1 } %pairval, 0 102 ret i128 %val 103} 104 105; Check that a constant %swap value is loaded into a register first. 106define i128 @f9(i128 %cmp, ptr %ptr) { 107; CHECK-LABEL: f9: 108; CHECK: lghi {{%r[0-9]+}}, 1002 109; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r4) 110; CHECK: br %r14 111 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 1002 seq_cst seq_cst 112 %val = extractvalue { i128, i1 } %pairval, 0 113 ret i128 %val 114} 115 116; Check generating the comparison result. 117; CHECK-LABEL: f10 118; CHECK-DAG: lg %r1, 8(%r3) 119; CHECK-DAG: lg %r0, 0(%r3) 120; CHECK-DAG: lg %r13, 8(%r2) 121; CHECK-DAG: lg %r12, 0(%r2) 122; CHECK-Z13: lhi %r2, 0 123; CHECK: cdsg %r12, %r0, 0(%r4) 124; CHECK-Z10-NEXT: ipm %r2 125; CHECK-Z10-NEXT: afi %r2, -268435456 126; CHECK-Z10-NEXT: srl %r2, 31 127; CHECK-Z13-NEXT: lochie %r2, 1 128; CHECK: br %r14 129define i32 @f10(i128 %cmp, i128 %swap, ptr %src) { 130 %pairval = cmpxchg ptr %src, i128 %cmp, i128 %swap seq_cst seq_cst 131 %val = extractvalue { i128, i1 } %pairval, 1 132 %res = zext i1 %val to i32 133 ret i32 %res 134} 135 136declare void @g() 137 138; Check using the comparison result for a branch. 139; CHECK-LABEL: f11 140; CHECK-DAG: lg %r1, 8(%r3) 141; CHECK-DAG: lg %r0, 0(%r3) 142; CHECK-DAG: lg %r13, 8(%r2) 143; CHECK-DAG: lg %r12, 0(%r2) 144; CHECK: cdsg %r12, %r0, 0(%r4) 145; CHECK-NEXT: jl [[LABEL:\.[^ ]*]] 146; CHECK: jg g 147; CHECK: [[LABEL]]: 148; CHECK: br %r14 149define void @f11(i128 %cmp, i128 %swap, ptr %src) { 150 %pairval = cmpxchg ptr %src, i128 %cmp, i128 %swap seq_cst seq_cst 151 %cond = extractvalue { i128, i1 } %pairval, 1 152 br i1 %cond, label %call, label %exit 153 154call: 155 tail call void @g() 156 br label %exit 157 158exit: 159 ret void 160} 161 162; ... and the same with the inverted direction. 163; CHECK-LABEL: f12 164; CHECK-DAG: lg %r1, 8(%r3) 165; CHECK-DAG: lg %r0, 0(%r3) 166; CHECK-DAG: lg %r13, 8(%r2) 167; CHECK-DAG: lg %r12, 0(%r2) 168; CHECK: cdsg %r12, %r0, 0(%r4) 169; CHECK-NEXT: jl [[LABEL:\.[^ ]*]] 170; CHECK: br %r14 171; CHECK: [[LABEL]]: 172; CHECK: jg g 173define void @f12(i128 %cmp, i128 %swap, ptr %src) { 174 %pairval = cmpxchg ptr %src, i128 %cmp, i128 %swap seq_cst seq_cst 175 %cond = extractvalue { i128, i1 } %pairval, 1 176 br i1 %cond, label %exit, label %call 177 178call: 179 tail call void @g() 180 br label %exit 181 182exit: 183 ret void 184} 185 186