1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=instcombine %s -S -o - | FileCheck %s 3 4; Clamp positive to allOnes: 5; E.g., clamp255 implemented in a shifty way, could be optimized as v > 255 ? 255 : v, where sub hasNoSignedWrap. 6; int32 clamp255(int32 v) { 7; return (((255 - (v)) >> 31) | (v)) & 255; 8; } 9; 10 11; Scalar Types 12 13define i32 @clamp255_i32(i32 %x) { 14; CHECK-LABEL: @clamp255_i32( 15; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.smin.i32(i32 [[X:%.*]], i32 255) 16; CHECK-NEXT: [[AND:%.*]] = and i32 [[OR]], 255 17; CHECK-NEXT: ret i32 [[AND]] 18; 19 %sub = sub nsw i32 255, %x 20 %shr = ashr i32 %sub, 31 21 %or = or i32 %shr, %x 22 %and = and i32 %or, 255 23 ret i32 %and 24} 25 26define i8 @sub_ashr_or_i8(i8 %x, i8 %y) { 27; CHECK-LABEL: @sub_ashr_or_i8( 28; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[Y:%.*]], [[X:%.*]] 29; CHECK-NEXT: [[OR:%.*]] = select i1 [[TMP1]], i8 -1, i8 [[X]] 30; CHECK-NEXT: ret i8 [[OR]] 31; 32 %sub = sub nsw i8 %y, %x 33 %shr = ashr i8 %sub, 7 34 %or = or i8 %shr, %x 35 ret i8 %or 36} 37 38define i16 @sub_ashr_or_i16(i16 %x, i16 %y) { 39; CHECK-LABEL: @sub_ashr_or_i16( 40; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i16 [[Y:%.*]], [[X:%.*]] 41; CHECK-NEXT: [[OR:%.*]] = select i1 [[TMP1]], i16 -1, i16 [[X]] 42; CHECK-NEXT: ret i16 [[OR]] 43; 44 %sub = sub nsw i16 %y, %x 45 %shr = ashr i16 %sub, 15 46 %or = or i16 %shr, %x 47 ret i16 %or 48} 49 50define i32 @sub_ashr_or_i32(i32 %x, i32 %y) { 51; CHECK-LABEL: @sub_ashr_or_i32( 52; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[Y:%.*]], [[X:%.*]] 53; CHECK-NEXT: [[OR:%.*]] = select i1 [[TMP1]], i32 -1, i32 [[X]] 54; CHECK-NEXT: ret i32 [[OR]] 55; 56 %sub = sub nsw i32 %y, %x 57 %shr = ashr i32 %sub, 31 58 %or = or i32 %shr, %x 59 ret i32 %or 60} 61 62define i64 @sub_ashr_or_i64(i64 %x, i64 %y) { 63; CHECK-LABEL: @sub_ashr_or_i64( 64; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[Y:%.*]], [[X:%.*]] 65; CHECK-NEXT: [[OR:%.*]] = select i1 [[TMP1]], i64 -1, i64 [[X]] 66; CHECK-NEXT: ret i64 [[OR]] 67; 68 %sub = sub nsw i64 %y, %x 69 %shr = ashr i64 %sub, 63 70 %or = or i64 %shr, %x 71 ret i64 %or 72} 73 74define i32 @neg_or_ashr_i32(i32 %x) { 75; CHECK-LABEL: @neg_or_ashr_i32( 76; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], 0 77; CHECK-NEXT: [[SHR:%.*]] = sext i1 [[TMP1]] to i32 78; CHECK-NEXT: ret i32 [[SHR]] 79; 80 %neg = sub i32 0, %x 81 %or = or i32 %neg, %x 82 %shr = ashr i32 %or, 31 83 ret i32 %shr 84} 85 86; nuw nsw 87 88define i32 @sub_ashr_or_i32_nuw_nsw(i32 %x, i32 %y) { 89; CHECK-LABEL: @sub_ashr_or_i32_nuw_nsw( 90; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[Y:%.*]], [[X:%.*]] 91; CHECK-NEXT: [[OR:%.*]] = select i1 [[TMP1]], i32 -1, i32 [[X]] 92; CHECK-NEXT: ret i32 [[OR]] 93; 94 %sub = sub nuw nsw i32 %y, %x 95 %shr = ashr i32 %sub, 31 96 %or = or i32 %shr, %x 97 ret i32 %or 98} 99 100; Commute 101 102define i32 @sub_ashr_or_i32_commute(i32 %x, i32 %y) { 103; CHECK-LABEL: @sub_ashr_or_i32_commute( 104; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[Y:%.*]], [[X:%.*]] 105; CHECK-NEXT: [[OR:%.*]] = select i1 [[TMP1]], i32 -1, i32 [[X]] 106; CHECK-NEXT: ret i32 [[OR]] 107; 108 %sub = sub nsw i32 %y, %x 109 %shr = ashr i32 %sub, 31 110 %or = or i32 %x, %shr ; commute %shr and %x 111 ret i32 %or 112} 113 114define i32 @neg_or_ashr_i32_commute(i32 %x0) { 115; CHECK-LABEL: @neg_or_ashr_i32_commute( 116; CHECK-NEXT: [[X:%.*]] = sdiv i32 42, [[X0:%.*]] 117; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X]], 0 118; CHECK-NEXT: [[SHR:%.*]] = sext i1 [[TMP1]] to i32 119; CHECK-NEXT: ret i32 [[SHR]] 120; 121 %x = sdiv i32 42, %x0 ; thwart complexity-based canonicalization 122 %neg = sub i32 0, %x 123 %or = or i32 %x, %neg 124 %shr = ashr i32 %or, 31 125 ret i32 %shr 126} 127 128; Vector Types 129 130define <4 x i32> @sub_ashr_or_i32_vec(<4 x i32> %x, <4 x i32> %y) { 131; CHECK-LABEL: @sub_ashr_or_i32_vec( 132; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <4 x i32> [[Y:%.*]], [[X:%.*]] 133; CHECK-NEXT: [[OR:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> splat (i32 -1), <4 x i32> [[X]] 134; CHECK-NEXT: ret <4 x i32> [[OR]] 135; 136 %sub = sub nsw <4 x i32> %y, %x 137 %shr = ashr <4 x i32> %sub, <i32 31, i32 31, i32 31, i32 31> 138 %or = or <4 x i32> %shr, %x 139 ret <4 x i32> %or 140} 141 142define <4 x i32> @sub_ashr_or_i32_vec_nuw_nsw(<4 x i32> %x, <4 x i32> %y) { 143; CHECK-LABEL: @sub_ashr_or_i32_vec_nuw_nsw( 144; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <4 x i32> [[Y:%.*]], [[X:%.*]] 145; CHECK-NEXT: [[OR:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> splat (i32 -1), <4 x i32> [[X]] 146; CHECK-NEXT: ret <4 x i32> [[OR]] 147; 148 %sub = sub nuw nsw <4 x i32> %y, %x 149 %shr = ashr <4 x i32> %sub, <i32 31, i32 31, i32 31, i32 31> 150 %or = or <4 x i32> %shr, %x 151 ret <4 x i32> %or 152} 153 154define <4 x i32> @neg_or_ashr_i32_vec(<4 x i32> %x) { 155; CHECK-LABEL: @neg_or_ashr_i32_vec( 156; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <4 x i32> [[X:%.*]], zeroinitializer 157; CHECK-NEXT: [[SHR:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32> 158; CHECK-NEXT: ret <4 x i32> [[SHR]] 159; 160 %neg = sub <4 x i32> zeroinitializer, %x 161 %or = or <4 x i32> %neg, %x 162 %shr = ashr <4 x i32> %or, <i32 31, i32 31, i32 31, i32 31> 163 ret <4 x i32> %shr 164} 165 166define <4 x i32> @sub_ashr_or_i32_vec_commute(<4 x i32> %x, <4 x i32> %y) { 167; CHECK-LABEL: @sub_ashr_or_i32_vec_commute( 168; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <4 x i32> [[Y:%.*]], [[X:%.*]] 169; CHECK-NEXT: [[OR:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> splat (i32 -1), <4 x i32> [[X]] 170; CHECK-NEXT: ret <4 x i32> [[OR]] 171; 172 %sub = sub nsw <4 x i32> %y, %x 173 %shr = ashr <4 x i32> %sub, <i32 31, i32 31, i32 31, i32 31> 174 %or = or <4 x i32> %x, %shr 175 ret <4 x i32> %or 176} 177 178define <4 x i32> @neg_or_ashr_i32_vec_commute(<4 x i32> %x0) { 179; CHECK-LABEL: @neg_or_ashr_i32_vec_commute( 180; CHECK-NEXT: [[X:%.*]] = sdiv <4 x i32> splat (i32 42), [[X0:%.*]] 181; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <4 x i32> [[X]], zeroinitializer 182; CHECK-NEXT: [[SHR:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32> 183; CHECK-NEXT: ret <4 x i32> [[SHR]] 184; 185 %x = sdiv <4 x i32> <i32 42, i32 42, i32 42, i32 42>, %x0 ; thwart complexity-based canonicalization 186 %neg = sub <4 x i32> zeroinitializer, %x 187 %or = or <4 x i32> %x, %neg 188 %shr = ashr <4 x i32> %or, <i32 31, i32 31, i32 31, i32 31> 189 ret <4 x i32> %shr 190} 191 192; Extra uses 193 194define i32 @sub_ashr_or_i32_extra_use_sub(i32 %x, i32 %y, ptr %p) { 195; CHECK-LABEL: @sub_ashr_or_i32_extra_use_sub( 196; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[Y:%.*]], [[X:%.*]] 197; CHECK-NEXT: store i32 [[SUB]], ptr [[P:%.*]], align 4 198; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[X]], [[Y]] 199; CHECK-NEXT: [[OR:%.*]] = select i1 [[TMP1]], i32 -1, i32 [[X]] 200; CHECK-NEXT: ret i32 [[OR]] 201; 202 %sub = sub nsw i32 %y, %x 203 store i32 %sub, ptr %p 204 %shr = ashr i32 %sub, 31 205 %or = or i32 %shr, %x 206 ret i32 %or 207} 208 209define i32 @sub_ashr_or_i32_extra_use_or(i32 %x, i32 %y, ptr %p) { 210; CHECK-LABEL: @sub_ashr_or_i32_extra_use_or( 211; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[Y:%.*]], [[X:%.*]] 212; CHECK-NEXT: [[OR:%.*]] = select i1 [[TMP1]], i32 -1, i32 [[X]] 213; CHECK-NEXT: store i32 [[OR]], ptr [[P:%.*]], align 4 214; CHECK-NEXT: ret i32 [[OR]] 215; 216 %sub = sub nsw i32 %y, %x 217 %shr = ashr i32 %sub, 31 218 %or = or i32 %shr, %x 219 store i32 %or, ptr %p 220 ret i32 %or 221} 222 223define i32 @neg_extra_use_or_ashr_i32(i32 %x, ptr %p) { 224; CHECK-LABEL: @neg_extra_use_or_ashr_i32( 225; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]] 226; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X]], 0 227; CHECK-NEXT: [[SHR:%.*]] = sext i1 [[TMP1]] to i32 228; CHECK-NEXT: store i32 [[NEG]], ptr [[P:%.*]], align 4 229; CHECK-NEXT: ret i32 [[SHR]] 230; 231 %neg = sub i32 0, %x 232 %or = or i32 %neg, %x 233 %shr = ashr i32 %or, 31 234 store i32 %neg, ptr %p 235 ret i32 %shr 236} 237 238; Negative Tests 239 240define i32 @sub_ashr_or_i32_extra_use_ashr(i32 %x, i32 %y, ptr %p) { 241; CHECK-LABEL: @sub_ashr_or_i32_extra_use_ashr( 242; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[Y:%.*]], [[X:%.*]] 243; CHECK-NEXT: [[SHR:%.*]] = sext i1 [[TMP1]] to i32 244; CHECK-NEXT: store i32 [[SHR]], ptr [[P:%.*]], align 4 245; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[SHR]] 246; CHECK-NEXT: ret i32 [[OR]] 247; 248 %sub = sub nsw i32 %y, %x 249 %shr = ashr i32 %sub, 31 250 store i32 %shr, ptr %p 251 %or = or i32 %shr, %x 252 ret i32 %or 253} 254 255define i32 @sub_ashr_or_i32_no_nsw_nuw(i32 %x, i32 %y) { 256; CHECK-LABEL: @sub_ashr_or_i32_no_nsw_nuw( 257; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[Y:%.*]], [[X:%.*]] 258; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[SUB]], 31 259; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHR]], [[X]] 260; CHECK-NEXT: ret i32 [[OR]] 261; 262 %sub = sub i32 %y, %x 263 %shr = ashr i32 %sub, 31 264 %or = or i32 %shr, %x 265 ret i32 %or 266} 267 268define i32 @neg_or_extra_use_ashr_i32(i32 %x, ptr %p) { 269; CHECK-LABEL: @neg_or_extra_use_ashr_i32( 270; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]] 271; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[NEG]] 272; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[OR]], 31 273; CHECK-NEXT: store i32 [[OR]], ptr [[P:%.*]], align 4 274; CHECK-NEXT: ret i32 [[SHR]] 275; 276 %neg = sub i32 0, %x 277 %or = or i32 %neg, %x 278 %shr = ashr i32 %or, 31 279 store i32 %or, ptr %p 280 ret i32 %shr 281} 282 283define <4 x i32> @sub_ashr_or_i32_vec_undef1(<4 x i32> %x) { 284; CHECK-LABEL: @sub_ashr_or_i32_vec_undef1( 285; CHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> <i32 255, i32 255, i32 undef, i32 255>, [[X:%.*]] 286; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i32> [[SUB]], splat (i32 31) 287; CHECK-NEXT: [[OR:%.*]] = or <4 x i32> [[SHR]], [[X]] 288; CHECK-NEXT: ret <4 x i32> [[OR]] 289; 290 %sub = sub <4 x i32> <i32 255, i32 255, i32 undef, i32 255>, %x 291 %shr = ashr <4 x i32> %sub, <i32 31, i32 31, i32 31, i32 31> 292 %or = or <4 x i32> %shr, %x 293 ret <4 x i32> %or 294} 295 296define <4 x i32> @sub_ashr_or_i32_vec_undef2(<4 x i32> %x) { 297; CHECK-LABEL: @sub_ashr_or_i32_vec_undef2( 298; CHECK-NEXT: [[SUB:%.*]] = sub nsw <4 x i32> splat (i32 255), [[X:%.*]] 299; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i32> [[SUB]], <i32 undef, i32 31, i32 31, i32 31> 300; CHECK-NEXT: [[OR:%.*]] = or <4 x i32> [[SHR]], [[X]] 301; CHECK-NEXT: ret <4 x i32> [[OR]] 302; 303 %sub = sub nsw <4 x i32> <i32 255, i32 255, i32 255, i32 255>, %x 304 %shr = ashr <4 x i32> %sub, <i32 undef, i32 31, i32 31, i32 31> 305 %or = or <4 x i32> %shr, %x 306 ret <4 x i32> %or 307} 308 309define i32 @sub_ashr_or_i32_shift_wrong_bit(i32 %x, i32 %y) { 310; CHECK-LABEL: @sub_ashr_or_i32_shift_wrong_bit( 311; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[Y:%.*]], [[X:%.*]] 312; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[SUB]], 11 313; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHR]], [[X]] 314; CHECK-NEXT: ret i32 [[OR]] 315; 316 %sub = sub nsw i32 %y, %x 317 %shr = ashr i32 %sub, 11 318 %or = or i32 %shr, %x 319 ret i32 %or 320} 321