1; RUN: llc -mtriple=armv4t-eabi %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=V4T 2; RUN: llc -mtriple=armv6t2-eabi %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=V6T2 3 4; Check for several conditions that should result in SSAT. 5; For example, the base test is equivalent to 6; x < -k ? -k : (x > k ? k : x) in C. All patterns that bound x 7; to the interval [-k, k] where k is a power of 2 can be 8; transformed into SSAT. At the end there are some tests 9; checking that conditionals are not transformed if they don't 10; match the right pattern. 11 12; 13; Base tests with different bit widths 14; 15 16; x < -k ? -k : (x > k ? k : x) 17; 32-bit base test 18define i32 @sat_base_32bit(i32 %x) #0 { 19; CHECK-LABEL: sat_base_32bit: 20; V6T2: ssat r0, #24, r0 21; V4T-NOT: ssat 22entry: 23 %cmpLow = icmp slt i32 %x, -8388608 24 %cmpUp = icmp sgt i32 %x, 8388607 25 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %x 26 %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %saturateUp 27 ret i32 %saturateLow 28} 29 30; x < -k ? -k : (x > k ? k : x) 31; 16-bit base test 32define i16 @sat_base_16bit(i16 %x) #0 { 33; CHECK-LABEL: sat_base_16bit: 34; V6T2: ssat r0, #12, r0 35; V4T-NOT: ssat 36entry: 37 %cmpLow = icmp slt i16 %x, -2048 38 %cmpUp = icmp sgt i16 %x, 2047 39 %saturateUp = select i1 %cmpUp, i16 2047, i16 %x 40 %saturateLow = select i1 %cmpLow, i16 -2048, i16 %saturateUp 41 ret i16 %saturateLow 42} 43 44; x < -k ? -k : (x > k ? k : x) 45; 8-bit base test 46define i8 @sat_base_8bit(i8 %x) #0 { 47; CHECK-LABEL: sat_base_8bit: 48; V6T2: ssat r0, #6, r0 49; V4T-NOT: ssat 50entry: 51 %cmpLow = icmp slt i8 %x, -32 52 %cmpUp = icmp sgt i8 %x, 31 53 %saturateUp = select i1 %cmpUp, i8 31, i8 %x 54 %saturateLow = select i1 %cmpLow, i8 -32, i8 %saturateUp 55 ret i8 %saturateLow 56} 57 58; 59; Tests where the conditionals that check for upper and lower bounds, 60; or the < and > operators, are arranged in different ways. Only some 61; of the possible combinations that lead to SSAT are tested. 62; 63 64; x < -k ? -k : (x < k ? x : k) 65define i32 @sat_lower_upper_1(i32 %x) #0 { 66; CHECK-LABEL: sat_lower_upper_1: 67; V6T2: ssat r0, #24, r0 68; V4T-NOT: ssat 69entry: 70 %cmpLow = icmp slt i32 %x, -8388608 71 %cmpUp = icmp slt i32 %x, 8388607 72 %saturateUp = select i1 %cmpUp, i32 %x, i32 8388607 73 %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %saturateUp 74 ret i32 %saturateLow 75} 76 77; x > -k ? (x > k ? k : x) : -k 78define i32 @sat_lower_upper_2(i32 %x) #0 { 79; CHECK-LABEL: sat_lower_upper_2: 80; V6T2: ssat r0, #24, r0 81; V4T-NOT: ssat 82entry: 83 %cmpLow = icmp sgt i32 %x, -8388608 84 %cmpUp = icmp sgt i32 %x, 8388607 85 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %x 86 %saturateLow = select i1 %cmpLow, i32 %saturateUp, i32 -8388608 87 ret i32 %saturateLow 88} 89 90; x < k ? (x < -k ? -k : x) : k 91define i32 @sat_upper_lower_1(i32 %x) #0 { 92; CHECK-LABEL: sat_upper_lower_1: 93; V6T2: ssat r0, #24, r0 94; V4T-NOT: ssat 95entry: 96 %cmpUp = icmp slt i32 %x, 8388607 97 %cmpLow = icmp slt i32 %x, -8388608 98 %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x 99 %saturateUp = select i1 %cmpUp, i32 %saturateLow, i32 8388607 100 ret i32 %saturateUp 101} 102 103; x > k ? k : (x < -k ? -k : x) 104define i32 @sat_upper_lower_2(i32 %x) #0 { 105; CHECK-LABEL: sat_upper_lower_2: 106; V6T2: ssat r0, #24, r0 107; V4T-NOT: ssat 108entry: 109 %cmpUp = icmp sgt i32 %x, 8388607 110 %cmpLow = icmp slt i32 %x, -8388608 111 %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x 112 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 113 ret i32 %saturateUp 114} 115 116; k < x ? k : (x > -k ? x : -k) 117define i32 @sat_upper_lower_3(i32 %x) #0 { 118; CHECK-LABEL: sat_upper_lower_3: 119; V6T2: ssat r0, #24, r0 120; V4T-NOT: ssat 121entry: 122 %cmpUp = icmp slt i32 8388607, %x 123 %cmpLow = icmp sgt i32 %x, -8388608 124 %saturateLow = select i1 %cmpLow, i32 %x, i32 -8388608 125 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 126 ret i32 %saturateUp 127} 128 129; 130; Miscellanea 131; 132 133; Check that >= and <= work the same as > and < 134; k <= x ? k : (x >= -k ? x : -k) 135define i32 @sat_le_ge(i32 %x) #0 { 136; CHECK-LABEL: sat_le_ge: 137; V6T2: ssat r0, #24, r0 138; V4T-NOT: ssat 139entry: 140 %cmpUp = icmp sle i32 8388607, %x 141 %cmpLow = icmp sge i32 %x, -8388608 142 %saturateLow = select i1 %cmpLow, i32 %x, i32 -8388608 143 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 144 ret i32 %saturateUp 145} 146 147; 148; The following tests check for patterns that should not transform 149; into SSAT but are similar enough that could confuse the selector. 150; 151 152; x > k ? k : (x > -k ? -k : x) 153; First condition upper-saturates, second doesn't lower-saturate. 154define i32 @no_sat_missing_lower(i32 %x) #0 { 155; CHECK-LABEL: no_sat_missing_lower 156; CHECK-NOT: ssat 157entry: 158 %cmpUp = icmp sgt i32 %x, 8388607 159 %cmpLow = icmp sgt i32 %x, -8388608 160 %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x 161 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 162 ret i32 %saturateUp 163} 164 165; x < k ? k : (x < -k ? -k : x) 166; Second condition lower-saturates, first doesn't upper-saturate. 167define i32 @no_sat_missing_upper(i32 %x) #0 { 168; CHECK-LABEL: no_sat_missing_upper: 169; CHECK-NOT: ssat 170entry: 171 %cmpUp = icmp slt i32 %x, 8388607 172 %cmpLow = icmp slt i32 %x, -8388608 173 %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x 174 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 175 ret i32 %saturateUp 176} 177 178; Lower constant is different in the select and in the compare 179define i32 @no_sat_incorrect_constant(i32 %x) #0 { 180; CHECK-LABEL: no_sat_incorrect_constant: 181; CHECK-NOT: ssat 182entry: 183 %cmpUp = icmp sgt i32 %x, 8388607 184 %cmpLow = icmp slt i32 %x, -8388608 185 %saturateLow = select i1 %cmpLow, i32 -8388607, i32 %x 186 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 187 ret i32 %saturateUp 188} 189 190; The interval is not [k, ~k] 191define i32 @no_sat_incorrect_interval(i32 %x) #0 { 192; CHECK-LABEL: no_sat_incorrect_interval: 193; CHECK-NOT: ssat 194entry: 195 %cmpUp = icmp sgt i32 %x, 8388607 196 %cmpLow = icmp slt i32 %x, -19088744 197 %saturateLow = select i1 %cmpLow, i32 -19088744, i32 %x 198 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 199 ret i32 %saturateUp 200} 201 202; The returned value (y) is not the same as the tested value (x). 203define i32 @no_sat_incorrect_return(i32 %x, i32 %y) #0 { 204; CHECK-LABEL: no_sat_incorrect_return: 205; CHECK-NOT: ssat 206entry: 207 %cmpUp = icmp sgt i32 %x, 8388607 208 %cmpLow = icmp slt i32 %x, -8388608 209 %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %y 210 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 211 ret i32 %saturateUp 212} 213 214; One of the values in a compare (y) is not the same as the rest 215; of the compare and select values (x). 216define i32 @no_sat_incorrect_compare(i32 %x, i32 %y) #0 { 217; CHECK-LABEL: no_sat_incorrect_compare: 218; CHECK-NOT: ssat 219entry: 220 %cmpUp = icmp sgt i32 %x, 8388607 221 %cmpLow = icmp slt i32 %y, -8388608 222 %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x 223 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 224 ret i32 %saturateUp 225} 226