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