1; Test 8-bit atomic min/max operations. 2; 3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK 4; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT1 5; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s -check-prefix=CHECK-SHIFT2 6 7; Check signed minimum. 8; - CHECK is for the main loop. 9; - CHECK-SHIFT1 makes sure that the negated shift count used by the second 10; RLL is set up correctly. The negation is independent of the NILL and L 11; tested in CHECK. 12; - CHECK-SHIFT2 makes sure that %b is shifted into the high part of the word 13; before being used, and that the low bits are set to 1. This sequence is 14; independent of the other loop prologue instructions. 15define i8 @f1(i8 *%src, i8 %b) { 16; CHECK-LABEL: f1: 17; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3 18; CHECK: nill %r2, 65532 19; CHECK: l [[OLD:%r[0-9]+]], 0(%r2) 20; CHECK: [[LOOP:\.[^:]*]]: 21; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]]) 22; CHECK: crjle [[ROT]], %r3, [[KEEP:\..*]] 23; CHECK: risbg [[ROT]], %r3, 32, 39, 0 24; CHECK: [[KEEP]]: 25; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}}) 26; CHECK: cs [[OLD]], [[NEW]], 0(%r2) 27; CHECK: jl [[LOOP]] 28; CHECK: rll %r2, [[OLD]], 8([[SHIFT]]) 29; CHECK: br %r14 30; 31; CHECK-SHIFT1-LABEL: f1: 32; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3 33; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]] 34; CHECK-SHIFT1: rll 35; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]]) 36; CHECK-SHIFT1: rll 37; CHECK-SHIFT1: br %r14 38; 39; CHECK-SHIFT2-LABEL: f1: 40; CHECK-SHIFT2: sll %r3, 24 41; CHECK-SHIFT2: rll 42; CHECK-SHIFT2: crjle {{%r[0-9]+}}, %r3 43; CHECK-SHIFT2: rll 44; CHECK-SHIFT2: rll 45; CHECK-SHIFT2: br %r14 46 %res = atomicrmw min i8 *%src, i8 %b seq_cst 47 ret i8 %res 48} 49 50; Check signed maximum. 51define i8 @f2(i8 *%src, i8 %b) { 52; CHECK-LABEL: f2: 53; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3 54; CHECK: nill %r2, 65532 55; CHECK: l [[OLD:%r[0-9]+]], 0(%r2) 56; CHECK: [[LOOP:\.[^:]*]]: 57; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]]) 58; CHECK: crjhe [[ROT]], %r3, [[KEEP:\..*]] 59; CHECK: risbg [[ROT]], %r3, 32, 39, 0 60; CHECK: [[KEEP]]: 61; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}}) 62; CHECK: cs [[OLD]], [[NEW]], 0(%r2) 63; CHECK: jl [[LOOP]] 64; CHECK: rll %r2, [[OLD]], 8([[SHIFT]]) 65; CHECK: br %r14 66; 67; CHECK-SHIFT1-LABEL: f2: 68; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3 69; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]] 70; CHECK-SHIFT1: rll 71; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]]) 72; CHECK-SHIFT1: rll 73; CHECK-SHIFT1: br %r14 74; 75; CHECK-SHIFT2-LABEL: f2: 76; CHECK-SHIFT2: sll %r3, 24 77; CHECK-SHIFT2: rll 78; CHECK-SHIFT2: crjhe {{%r[0-9]+}}, %r3 79; CHECK-SHIFT2: rll 80; CHECK-SHIFT2: rll 81; CHECK-SHIFT2: br %r14 82 %res = atomicrmw max i8 *%src, i8 %b seq_cst 83 ret i8 %res 84} 85 86; Check unsigned minimum. 87define i8 @f3(i8 *%src, i8 %b) { 88; CHECK-LABEL: f3: 89; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3 90; CHECK: nill %r2, 65532 91; CHECK: l [[OLD:%r[0-9]+]], 0(%r2) 92; CHECK: [[LOOP:\.[^:]*]]: 93; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]]) 94; CHECK: clrjle [[ROT]], %r3, [[KEEP:\..*]] 95; CHECK: risbg [[ROT]], %r3, 32, 39, 0 96; CHECK: [[KEEP]]: 97; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}}) 98; CHECK: cs [[OLD]], [[NEW]], 0(%r2) 99; CHECK: jl [[LOOP]] 100; CHECK: rll %r2, [[OLD]], 8([[SHIFT]]) 101; CHECK: br %r14 102; 103; CHECK-SHIFT1-LABEL: f3: 104; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3 105; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]] 106; CHECK-SHIFT1: rll 107; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]]) 108; CHECK-SHIFT1: rll 109; CHECK-SHIFT1: br %r14 110; 111; CHECK-SHIFT2-LABEL: f3: 112; CHECK-SHIFT2: sll %r3, 24 113; CHECK-SHIFT2: rll 114; CHECK-SHIFT2: clrjle {{%r[0-9]+}}, %r3, 115; CHECK-SHIFT2: rll 116; CHECK-SHIFT2: rll 117; CHECK-SHIFT2: br %r14 118 %res = atomicrmw umin i8 *%src, i8 %b seq_cst 119 ret i8 %res 120} 121 122; Check unsigned maximum. 123define i8 @f4(i8 *%src, i8 %b) { 124; CHECK-LABEL: f4: 125; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3 126; CHECK: nill %r2, 65532 127; CHECK: l [[OLD:%r[0-9]+]], 0(%r2) 128; CHECK: [[LOOP:\.[^:]*]]: 129; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]]) 130; CHECK: clrjhe [[ROT]], %r3, [[KEEP:\..*]] 131; CHECK: risbg [[ROT]], %r3, 32, 39, 0 132; CHECK: [[KEEP]]: 133; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}}) 134; CHECK: cs [[OLD]], [[NEW]], 0(%r2) 135; CHECK: jl [[LOOP]] 136; CHECK: rll %r2, [[OLD]], 8([[SHIFT]]) 137; CHECK: br %r14 138; 139; CHECK-SHIFT1-LABEL: f4: 140; CHECK-SHIFT1: sllg [[SHIFT:%r[1-9]+]], %r2, 3 141; CHECK-SHIFT1: lcr [[NEGSHIFT:%r[1-9]+]], [[SHIFT]] 142; CHECK-SHIFT1: rll 143; CHECK-SHIFT1: rll {{%r[0-9]+}}, {{%r[0-9]+}}, 0([[NEGSHIFT]]) 144; CHECK-SHIFT1: rll 145; CHECK-SHIFT1: br %r14 146; 147; CHECK-SHIFT2-LABEL: f4: 148; CHECK-SHIFT2: sll %r3, 24 149; CHECK-SHIFT2: rll 150; CHECK-SHIFT2: clrjhe {{%r[0-9]+}}, %r3, 151; CHECK-SHIFT2: rll 152; CHECK-SHIFT2: rll 153; CHECK-SHIFT2: br %r14 154 %res = atomicrmw umax i8 *%src, i8 %b seq_cst 155 ret i8 %res 156} 157 158; Check the lowest useful signed minimum value. We need to load 0x81000000 159; into the source register. 160define i8 @f5(i8 *%src) { 161; CHECK-LABEL: f5: 162; CHECK: llilh [[SRC2:%r[0-9]+]], 33024 163; CHECK: crjle [[ROT:%r[0-9]+]], [[SRC2]] 164; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0 165; CHECK: br %r14 166; 167; CHECK-SHIFT1-LABEL: f5: 168; CHECK-SHIFT1: br %r14 169; CHECK-SHIFT2-LABEL: f5: 170; CHECK-SHIFT2: br %r14 171 %res = atomicrmw min i8 *%src, i8 -127 seq_cst 172 ret i8 %res 173} 174 175; Check the highest useful signed maximum value. We need to load 0x7e000000 176; into the source register. 177define i8 @f6(i8 *%src) { 178; CHECK-LABEL: f6: 179; CHECK: llilh [[SRC2:%r[0-9]+]], 32256 180; CHECK: crjhe [[ROT:%r[0-9]+]], [[SRC2]] 181; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0 182; CHECK: br %r14 183; 184; CHECK-SHIFT1-LABEL: f6: 185; CHECK-SHIFT1: br %r14 186; CHECK-SHIFT2-LABEL: f6: 187; CHECK-SHIFT2: br %r14 188 %res = atomicrmw max i8 *%src, i8 126 seq_cst 189 ret i8 %res 190} 191 192; Check the lowest useful unsigned minimum value. We need to load 0x01000000 193; into the source register. 194define i8 @f7(i8 *%src) { 195; CHECK-LABEL: f7: 196; CHECK: llilh [[SRC2:%r[0-9]+]], 256 197; CHECK: clrjle [[ROT:%r[0-9]+]], [[SRC2]], 198; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0 199; CHECK: br %r14 200; 201; CHECK-SHIFT1-LABEL: f7: 202; CHECK-SHIFT1: br %r14 203; CHECK-SHIFT2-LABEL: f7: 204; CHECK-SHIFT2: br %r14 205 %res = atomicrmw umin i8 *%src, i8 1 seq_cst 206 ret i8 %res 207} 208 209; Check the highest useful unsigned maximum value. We need to load 0xfe000000 210; into the source register. 211define i8 @f8(i8 *%src) { 212; CHECK-LABEL: f8: 213; CHECK: llilh [[SRC2:%r[0-9]+]], 65024 214; CHECK: clrjhe [[ROT:%r[0-9]+]], [[SRC2]], 215; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0 216; CHECK: br %r14 217; 218; CHECK-SHIFT1-LABEL: f8: 219; CHECK-SHIFT1: br %r14 220; CHECK-SHIFT2-LABEL: f8: 221; CHECK-SHIFT2: br %r14 222 %res = atomicrmw umax i8 *%src, i8 254 seq_cst 223 ret i8 %res 224} 225