186 lines · plain
1; Test 128-bit compare and swap.2;3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z104; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z135 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 %r1417 %pairval = cmpxchg ptr %src, i128 %cmp, i128 %swap seq_cst seq_cst18 %val = extractvalue { i128, i1 } %pairval, 019 ret i128 %val20}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 %r1427 %ptr = getelementptr i128, ptr %src, i128 3276728 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 %swap seq_cst seq_cst29 %val = extractvalue { i128, i1 } %pairval, 030 ret i128 %val31}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, 52428838; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)39; CHECK: br %r1440 %ptr = getelementptr i128, ptr %src, i128 3276841 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 %swap seq_cst seq_cst42 %val = extractvalue { i128, i1 } %pairval, 043 ret i128 %val44}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 %r1451 %ptr = getelementptr i128, ptr %src, i128 -152 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 %swap seq_cst seq_cst53 %val = extractvalue { i128, i1 } %pairval, 054 ret i128 %val55}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 %r1462 %ptr = getelementptr i128, ptr %src, i128 -3276863 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 %swap seq_cst seq_cst64 %val = extractvalue { i128, i1 } %pairval, 065 ret i128 %val66}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, -52430473; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)74; CHECK: br %r1475 %ptr = getelementptr i128, ptr %src, i128 -3276976 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 %swap seq_cst seq_cst77 %val = extractvalue { i128, i1 } %pairval, 078 ret i128 %val79}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, %r685; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)86; CHECK: br %r1487 %add1 = add i64 %src, %index88 %ptr = inttoptr i64 %add1 to ptr89 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 %swap seq_cst seq_cst90 %val = extractvalue { i128, i1 } %pairval, 091 ret i128 %val92}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]+}}, 100198; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r4)99; CHECK: br %r14100 %pairval = cmpxchg ptr %ptr, i128 1001, i128 %swap seq_cst seq_cst101 %val = extractvalue { i128, i1 } %pairval, 0102 ret i128 %val103}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]+}}, 1002109; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r4)110; CHECK: br %r14111 %pairval = cmpxchg ptr %ptr, i128 %cmp, i128 1002 seq_cst seq_cst112 %val = extractvalue { i128, i1 } %pairval, 0113 ret i128 %val114}115 116; Check generating the comparison result.117; CHECK-LABEL: f10118; 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, 0123; CHECK: cdsg %r12, %r0, 0(%r4)124; CHECK-Z10-NEXT: ipm %r2125; CHECK-Z10-NEXT: afi %r2, -268435456126; CHECK-Z10-NEXT: srl %r2, 31127; CHECK-Z13-NEXT: lochie %r2, 1128; CHECK: br %r14129define i32 @f10(i128 %cmp, i128 %swap, ptr %src) {130 %pairval = cmpxchg ptr %src, i128 %cmp, i128 %swap seq_cst seq_cst131 %val = extractvalue { i128, i1 } %pairval, 1132 %res = zext i1 %val to i32133 ret i32 %res134}135 136declare void @g()137 138; Check using the comparison result for a branch.139; CHECK-LABEL: f11140; 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 g147; CHECK: [[LABEL]]:148; CHECK: br %r14149define void @f11(i128 %cmp, i128 %swap, ptr %src) {150 %pairval = cmpxchg ptr %src, i128 %cmp, i128 %swap seq_cst seq_cst151 %cond = extractvalue { i128, i1 } %pairval, 1152 br i1 %cond, label %call, label %exit153 154call:155 tail call void @g()156 br label %exit157 158exit:159 ret void160}161 162; ... and the same with the inverted direction.163; CHECK-LABEL: f12164; 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 %r14171; CHECK: [[LABEL]]:172; CHECK: jg g173define void @f12(i128 %cmp, i128 %swap, ptr %src) {174 %pairval = cmpxchg ptr %src, i128 %cmp, i128 %swap seq_cst seq_cst175 %cond = extractvalue { i128, i1 } %pairval, 1176 br i1 %cond, label %exit, label %call177 178call:179 tail call void @g()180 br label %exit181 182exit:183 ret void184}185 186