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