1 ; Test 32-bit compare and swap. 2 ; 3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 4 5 ; Check the low end of the CS range. 6 define i32 @f1(i32 %cmp, i32 %swap, i32 *%src) { 7 ; CHECK-LABEL: f1: 8 ; CHECK: cs %r2, %r3, 0(%r4) 9 ; CHECK: br %r14 10 %pair = cmpxchg i32 *%src, i32 %cmp, i32 %swap seq_cst seq_cst 11 %val = extractvalue { i32, i1 } %pair, 0 12 ret i32 %val 13 } 14 15 ; Check the high end of the aligned CS range. 16 define i32 @f2(i32 %cmp, i32 %swap, i32 *%src) { 17 ; CHECK-LABEL: f2: 18 ; CHECK: cs %r2, %r3, 4092(%r4) 19 ; CHECK: br %r14 20 %ptr = getelementptr i32 *%src, i64 1023 21 %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst 22 %val = extractvalue { i32, i1 } %pair, 0 23 ret i32 %val 24 } 25 26 ; Check the next word up, which should use CSY instead of CS. 27 define i32 @f3(i32 %cmp, i32 %swap, i32 *%src) { 28 ; CHECK-LABEL: f3: 29 ; CHECK: csy %r2, %r3, 4096(%r4) 30 ; CHECK: br %r14 31 %ptr = getelementptr i32 *%src, i64 1024 32 %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst 33 %val = extractvalue { i32, i1 } %pair, 0 34 ret i32 %val 35 } 36 37 ; Check the high end of the aligned CSY range. 38 define i32 @f4(i32 %cmp, i32 %swap, i32 *%src) { 39 ; CHECK-LABEL: f4: 40 ; CHECK: csy %r2, %r3, 524284(%r4) 41 ; CHECK: br %r14 42 %ptr = getelementptr i32 *%src, i64 131071 43 %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst 44 %val = extractvalue { i32, i1 } %pair, 0 45 ret i32 %val 46 } 47 48 ; Check the next word up, which needs separate address logic. 49 ; Other sequences besides this one would be OK. 50 define i32 @f5(i32 %cmp, i32 %swap, i32 *%src) { 51 ; CHECK-LABEL: f5: 52 ; CHECK: agfi %r4, 524288 53 ; CHECK: cs %r2, %r3, 0(%r4) 54 ; CHECK: br %r14 55 %ptr = getelementptr i32 *%src, i64 131072 56 %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst 57 %val = extractvalue { i32, i1 } %pair, 0 58 ret i32 %val 59 } 60 61 ; Check the high end of the negative aligned CSY range. 62 define i32 @f6(i32 %cmp, i32 %swap, i32 *%src) { 63 ; CHECK-LABEL: f6: 64 ; CHECK: csy %r2, %r3, -4(%r4) 65 ; CHECK: br %r14 66 %ptr = getelementptr i32 *%src, i64 -1 67 %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst 68 %val = extractvalue { i32, i1 } %pair, 0 69 ret i32 %val 70 } 71 72 ; Check the low end of the CSY range. 73 define i32 @f7(i32 %cmp, i32 %swap, i32 *%src) { 74 ; CHECK-LABEL: f7: 75 ; CHECK: csy %r2, %r3, -524288(%r4) 76 ; CHECK: br %r14 77 %ptr = getelementptr i32 *%src, i64 -131072 78 %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst 79 %val = extractvalue { i32, i1 } %pair, 0 80 ret i32 %val 81 } 82 83 ; Check the next word down, which needs separate address logic. 84 ; Other sequences besides this one would be OK. 85 define i32 @f8(i32 %cmp, i32 %swap, i32 *%src) { 86 ; CHECK-LABEL: f8: 87 ; CHECK: agfi %r4, -524292 88 ; CHECK: cs %r2, %r3, 0(%r4) 89 ; CHECK: br %r14 90 %ptr = getelementptr i32 *%src, i64 -131073 91 %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst 92 %val = extractvalue { i32, i1 } %pair, 0 93 ret i32 %val 94 } 95 96 ; Check that CS does not allow an index. 97 define i32 @f9(i32 %cmp, i32 %swap, i64 %src, i64 %index) { 98 ; CHECK-LABEL: f9: 99 ; CHECK: agr %r4, %r5 100 ; CHECK: cs %r2, %r3, 0(%r4) 101 ; CHECK: br %r14 102 %add1 = add i64 %src, %index 103 %ptr = inttoptr i64 %add1 to i32 * 104 %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst 105 %val = extractvalue { i32, i1 } %pair, 0 106 ret i32 %val 107 } 108 109 ; Check that CSY does not allow an index. 110 define i32 @f10(i32 %cmp, i32 %swap, i64 %src, i64 %index) { 111 ; CHECK-LABEL: f10: 112 ; CHECK: agr %r4, %r5 113 ; CHECK: csy %r2, %r3, 4096(%r4) 114 ; CHECK: br %r14 115 %add1 = add i64 %src, %index 116 %add2 = add i64 %add1, 4096 117 %ptr = inttoptr i64 %add2 to i32 * 118 %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 %swap seq_cst seq_cst 119 %val = extractvalue { i32, i1 } %pair, 0 120 ret i32 %val 121 } 122 123 ; Check that a constant %cmp value is loaded into a register first. 124 define i32 @f11(i32 %dummy, i32 %swap, i32 *%ptr) { 125 ; CHECK-LABEL: f11: 126 ; CHECK: lhi %r2, 1001 127 ; CHECK: cs %r2, %r3, 0(%r4) 128 ; CHECK: br %r14 129 %pair = cmpxchg i32 *%ptr, i32 1001, i32 %swap seq_cst seq_cst 130 %val = extractvalue { i32, i1 } %pair, 0 131 ret i32 %val 132 } 133 134 ; Check that a constant %swap value is loaded into a register first. 135 define i32 @f12(i32 %cmp, i32 *%ptr) { 136 ; CHECK-LABEL: f12: 137 ; CHECK: lhi [[SWAP:%r[0-9]+]], 1002 138 ; CHECK: cs %r2, [[SWAP]], 0(%r3) 139 ; CHECK: br %r14 140 %pair = cmpxchg i32 *%ptr, i32 %cmp, i32 1002 seq_cst seq_cst 141 %val = extractvalue { i32, i1 } %pair, 0 142 ret i32 %val 143 } 144