849 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 4; If we have an smax feeding a signed or equality icmp that shares an5; operand with the smax, the compare should always be folded.6; Test all 4 foldable predicates (eq,ne,sgt,sle) * 4 commutation7; possibilities for each predicate. Note that folds to true/false8; (predicate = sge/slt) or folds to an existing instruction should be9; handled by InstSimplify.10 11; smax(X, Y) == X --> X >= Y12 13define i1 @eq_smax1(i32 %x, i32 %y) {14; CHECK-LABEL: @eq_smax1(15; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i32 [[X:%.*]], [[Y:%.*]]16; CHECK-NEXT: ret i1 [[CMP2]]17;18 %cmp1 = icmp sgt i32 %x, %y19 %sel = select i1 %cmp1, i32 %x, i32 %y20 %cmp2 = icmp eq i32 %sel, %x21 ret i1 %cmp222}23 24; Commute max operands.25 26define i1 @eq_smax2(i32 %x, i32 %y) {27; CHECK-LABEL: @eq_smax2(28; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i32 [[X:%.*]], [[Y:%.*]]29; CHECK-NEXT: ret i1 [[CMP2]]30;31 %cmp1 = icmp sgt i32 %y, %x32 %sel = select i1 %cmp1, i32 %y, i32 %x33 %cmp2 = icmp eq i32 %sel, %x34 ret i1 %cmp235}36 37; Disguise the icmp predicate by commuting the max op to the RHS.38 39define i1 @eq_smax3(i32 %a, i32 %y) {40; CHECK-LABEL: @eq_smax3(41; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 342; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i32 [[X]], [[Y:%.*]]43; CHECK-NEXT: ret i1 [[CMP2]]44;45 %x = add i32 %a, 3 ; thwart complexity-based canonicalization46 %cmp1 = icmp sgt i32 %x, %y47 %sel = select i1 %cmp1, i32 %x, i32 %y48 %cmp2 = icmp eq i32 %x, %sel49 ret i1 %cmp250}51 52; Commute max operands.53 54define i1 @eq_smax4(i32 %a, i32 %y) {55; CHECK-LABEL: @eq_smax4(56; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 357; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i32 [[X]], [[Y:%.*]]58; CHECK-NEXT: ret i1 [[CMP2]]59;60 %x = add i32 %a, 3 ; thwart complexity-based canonicalization61 %cmp1 = icmp sgt i32 %y, %x62 %sel = select i1 %cmp1, i32 %y, i32 %x63 %cmp2 = icmp eq i32 %x, %sel64 ret i1 %cmp265}66 67; smax(X, Y) <= X --> Y <= X68 69define i1 @sle_smax1(i32 %x, i32 %y) {70; CHECK-LABEL: @sle_smax1(71; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[Y:%.*]], [[X:%.*]]72; CHECK-NEXT: ret i1 [[CMP2]]73;74 %cmp1 = icmp sgt i32 %x, %y75 %sel = select i1 %cmp1, i32 %x, i32 %y76 %cmp2 = icmp sle i32 %sel, %x77 ret i1 %cmp278}79 80; Commute max operands.81 82define i1 @sle_smax2(i32 %x, i32 %y) {83; CHECK-LABEL: @sle_smax2(84; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[Y:%.*]], [[X:%.*]]85; CHECK-NEXT: ret i1 [[CMP2]]86;87 %cmp1 = icmp sgt i32 %y, %x88 %sel = select i1 %cmp1, i32 %y, i32 %x89 %cmp2 = icmp sle i32 %sel, %x90 ret i1 %cmp291}92 93; Disguise the icmp predicate by commuting the max op to the RHS.94 95define i1 @sle_smax3(i32 %a, i32 %y) {96; CHECK-LABEL: @sle_smax3(97; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 398; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[Y:%.*]], [[X]]99; CHECK-NEXT: ret i1 [[CMP2]]100;101 %x = add i32 %a, 3 ; thwart complexity-based canonicalization102 %cmp1 = icmp sgt i32 %x, %y103 %sel = select i1 %cmp1, i32 %x, i32 %y104 %cmp2 = icmp sge i32 %x, %sel105 ret i1 %cmp2106}107 108; Commute max operands.109 110define i1 @sle_smax4(i32 %a, i32 %y) {111; CHECK-LABEL: @sle_smax4(112; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 3113; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[Y:%.*]], [[X]]114; CHECK-NEXT: ret i1 [[CMP2]]115;116 %x = add i32 %a, 3 ; thwart complexity-based canonicalization117 %cmp1 = icmp sgt i32 %y, %x118 %sel = select i1 %cmp1, i32 %y, i32 %x119 %cmp2 = icmp sge i32 %x, %sel120 ret i1 %cmp2121}122 123; smax(X, Y) != X --> X < Y124 125define i1 @ne_smax1(i32 %x, i32 %y) {126; CHECK-LABEL: @ne_smax1(127; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]128; CHECK-NEXT: ret i1 [[CMP2]]129;130 %cmp1 = icmp sgt i32 %x, %y131 %sel = select i1 %cmp1, i32 %x, i32 %y132 %cmp2 = icmp ne i32 %sel, %x133 ret i1 %cmp2134}135 136; Commute max operands.137 138define i1 @ne_smax2(i32 %x, i32 %y) {139; CHECK-LABEL: @ne_smax2(140; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]141; CHECK-NEXT: ret i1 [[CMP2]]142;143 %cmp1 = icmp sgt i32 %y, %x144 %sel = select i1 %cmp1, i32 %y, i32 %x145 %cmp2 = icmp ne i32 %sel, %x146 ret i1 %cmp2147}148 149; Disguise the icmp predicate by commuting the max op to the RHS.150 151define i1 @ne_smax3(i32 %a, i32 %y) {152; CHECK-LABEL: @ne_smax3(153; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 3154; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], [[Y:%.*]]155; CHECK-NEXT: ret i1 [[CMP2]]156;157 %x = add i32 %a, 3 ; thwart complexity-based canonicalization158 %cmp1 = icmp sgt i32 %x, %y159 %sel = select i1 %cmp1, i32 %x, i32 %y160 %cmp2 = icmp ne i32 %x, %sel161 ret i1 %cmp2162}163 164; Commute max operands.165 166define i1 @ne_smax4(i32 %a, i32 %y) {167; CHECK-LABEL: @ne_smax4(168; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 3169; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], [[Y:%.*]]170; CHECK-NEXT: ret i1 [[CMP2]]171;172 %x = add i32 %a, 3 ; thwart complexity-based canonicalization173 %cmp1 = icmp sgt i32 %y, %x174 %sel = select i1 %cmp1, i32 %y, i32 %x175 %cmp2 = icmp ne i32 %x, %sel176 ret i1 %cmp2177}178 179; smax(X, Y) > X --> Y > X180 181define i1 @sgt_smax1(i32 %x, i32 %y) {182; CHECK-LABEL: @sgt_smax1(183; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[Y:%.*]], [[X:%.*]]184; CHECK-NEXT: ret i1 [[CMP2]]185;186 %cmp1 = icmp sgt i32 %x, %y187 %sel = select i1 %cmp1, i32 %x, i32 %y188 %cmp2 = icmp sgt i32 %sel, %x189 ret i1 %cmp2190}191 192; Commute max operands.193 194define i1 @sgt_smax2(i32 %x, i32 %y) {195; CHECK-LABEL: @sgt_smax2(196; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[Y:%.*]], [[X:%.*]]197; CHECK-NEXT: ret i1 [[CMP2]]198;199 %cmp1 = icmp sgt i32 %y, %x200 %sel = select i1 %cmp1, i32 %y, i32 %x201 %cmp2 = icmp sgt i32 %sel, %x202 ret i1 %cmp2203}204 205; Disguise the icmp predicate by commuting the max op to the RHS.206 207define i1 @sgt_smax3(i32 %a, i32 %y) {208; CHECK-LABEL: @sgt_smax3(209; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 3210; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[Y:%.*]], [[X]]211; CHECK-NEXT: ret i1 [[CMP2]]212;213 %x = add i32 %a, 3 ; thwart complexity-based canonicalization214 %cmp1 = icmp sgt i32 %x, %y215 %sel = select i1 %cmp1, i32 %x, i32 %y216 %cmp2 = icmp slt i32 %x, %sel217 ret i1 %cmp2218}219 220; Commute max operands.221 222define i1 @sgt_smax4(i32 %a, i32 %y) {223; CHECK-LABEL: @sgt_smax4(224; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 3225; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[Y:%.*]], [[X]]226; CHECK-NEXT: ret i1 [[CMP2]]227;228 %x = add i32 %a, 3 ; thwart complexity-based canonicalization229 %cmp1 = icmp sgt i32 %y, %x230 %sel = select i1 %cmp1, i32 %y, i32 %x231 %cmp2 = icmp slt i32 %x, %sel232 ret i1 %cmp2233}234 235declare void @use(i1 %c)236 237define void @eq_smax_contextual(i32 %x, i32 %y, i32 %z) {238; CHECK-LABEL: @eq_smax_contextual(239; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]240; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]241; CHECK: if:242; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])243; CHECK-NEXT: call void @use(i1 false)244; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]245; CHECK-NEXT: call void @use(i1 [[CMP2]])246; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]247; CHECK-NEXT: call void @use(i1 [[CMP3]])248; CHECK-NEXT: call void @use(i1 true)249; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]250; CHECK-NEXT: call void @use(i1 [[CMP5]])251; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]252; CHECK-NEXT: call void @use(i1 [[CMP6]])253; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]254; CHECK-NEXT: call void @use(i1 [[CMP7]])255; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]256; CHECK-NEXT: call void @use(i1 [[CMP8]])257; CHECK-NEXT: [[CMP9:%.*]] = icmp sge i32 [[X]], [[Y]]258; CHECK-NEXT: call void @use(i1 [[CMP9]])259; CHECK-NEXT: [[CMP10:%.*]] = icmp slt i32 [[X]], [[Y]]260; CHECK-NEXT: call void @use(i1 [[CMP10]])261; CHECK-NEXT: ret void262; CHECK: end:263; CHECK-NEXT: ret void264;265 %cmp = icmp eq i32 %x, %z266 br i1 %cmp, label %if, label %end267if:268 %cond = call i32 @llvm.smax.i32(i32 %x, i32 %y)269 %cmp1 = icmp slt i32 %cond, %z270 call void @use(i1 %cmp1)271 %cmp2 = icmp sle i32 %cond, %z272 call void @use(i1 %cmp2)273 %cmp3 = icmp sgt i32 %cond, %z274 call void @use(i1 %cmp3)275 %cmp4 = icmp sge i32 %cond, %z276 call void @use(i1 %cmp4)277 %cmp5 = icmp ult i32 %cond, %z278 call void @use(i1 %cmp5)279 %cmp6 = icmp ule i32 %cond, %z280 call void @use(i1 %cmp6)281 %cmp7 = icmp ugt i32 %cond, %z282 call void @use(i1 %cmp7)283 %cmp8 = icmp uge i32 %cond, %z284 call void @use(i1 %cmp8)285 %cmp9 = icmp eq i32 %cond, %z286 call void @use(i1 %cmp9)287 %cmp10 = icmp ne i32 %cond, %z288 call void @use(i1 %cmp10)289 ret void290end:291 ret void292}293 294define void @eq_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {295; CHECK-LABEL: @eq_smax_contextual_commuted(296; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]297; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]298; CHECK: if:299; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])300; CHECK-NEXT: call void @use(i1 false)301; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]302; CHECK-NEXT: call void @use(i1 [[CMP2]])303; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]304; CHECK-NEXT: call void @use(i1 [[CMP3]])305; CHECK-NEXT: call void @use(i1 true)306; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]307; CHECK-NEXT: call void @use(i1 [[CMP5]])308; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]309; CHECK-NEXT: call void @use(i1 [[CMP6]])310; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]311; CHECK-NEXT: call void @use(i1 [[CMP7]])312; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]313; CHECK-NEXT: call void @use(i1 [[CMP8]])314; CHECK-NEXT: [[CMP9:%.*]] = icmp sge i32 [[X]], [[Y]]315; CHECK-NEXT: call void @use(i1 [[CMP9]])316; CHECK-NEXT: [[CMP10:%.*]] = icmp slt i32 [[X]], [[Y]]317; CHECK-NEXT: call void @use(i1 [[CMP10]])318; CHECK-NEXT: ret void319; CHECK: end:320; CHECK-NEXT: ret void321;322 %cmp = icmp eq i32 %x, %z323 br i1 %cmp, label %if, label %end324if:325 %cond = call i32 @llvm.smax.i32(i32 %y, i32 %x)326 %cmp1 = icmp slt i32 %cond, %z327 call void @use(i1 %cmp1)328 %cmp2 = icmp sle i32 %cond, %z329 call void @use(i1 %cmp2)330 %cmp3 = icmp sgt i32 %cond, %z331 call void @use(i1 %cmp3)332 %cmp4 = icmp sge i32 %cond, %z333 call void @use(i1 %cmp4)334 %cmp5 = icmp ult i32 %cond, %z335 call void @use(i1 %cmp5)336 %cmp6 = icmp ule i32 %cond, %z337 call void @use(i1 %cmp6)338 %cmp7 = icmp ugt i32 %cond, %z339 call void @use(i1 %cmp7)340 %cmp8 = icmp uge i32 %cond, %z341 call void @use(i1 %cmp8)342 %cmp9 = icmp eq i32 %cond, %z343 call void @use(i1 %cmp9)344 %cmp10 = icmp ne i32 %cond, %z345 call void @use(i1 %cmp10)346 ret void347end:348 ret void349}350 351define void @slt_smax_contextual(i32 %x, i32 %y, i32 %z) {352; CHECK-LABEL: @slt_smax_contextual(353; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]]354; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]355; CHECK: if:356; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])357; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]]358; CHECK-NEXT: call void @use(i1 [[CMP1]])359; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]360; CHECK-NEXT: call void @use(i1 [[CMP2]])361; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]362; CHECK-NEXT: call void @use(i1 [[CMP3]])363; CHECK-NEXT: [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]]364; CHECK-NEXT: call void @use(i1 [[CMP4]])365; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]366; CHECK-NEXT: call void @use(i1 [[CMP5]])367; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]368; CHECK-NEXT: call void @use(i1 [[CMP6]])369; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]370; CHECK-NEXT: call void @use(i1 [[CMP7]])371; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]372; CHECK-NEXT: call void @use(i1 [[CMP8]])373; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i32 [[Y]], [[Z]]374; CHECK-NEXT: call void @use(i1 [[CMP9]])375; CHECK-NEXT: [[CMP10:%.*]] = icmp ne i32 [[Y]], [[Z]]376; CHECK-NEXT: call void @use(i1 [[CMP10]])377; CHECK-NEXT: ret void378; CHECK: end:379; CHECK-NEXT: ret void380;381 %cmp = icmp slt i32 %x, %z382 br i1 %cmp, label %if, label %end383if:384 %cond = call i32 @llvm.smax.i32(i32 %x, i32 %y)385 %cmp1 = icmp slt i32 %cond, %z386 call void @use(i1 %cmp1)387 %cmp2 = icmp sle i32 %cond, %z388 call void @use(i1 %cmp2)389 %cmp3 = icmp sgt i32 %cond, %z390 call void @use(i1 %cmp3)391 %cmp4 = icmp sge i32 %cond, %z392 call void @use(i1 %cmp4)393 %cmp5 = icmp ult i32 %cond, %z394 call void @use(i1 %cmp5)395 %cmp6 = icmp ule i32 %cond, %z396 call void @use(i1 %cmp6)397 %cmp7 = icmp ugt i32 %cond, %z398 call void @use(i1 %cmp7)399 %cmp8 = icmp uge i32 %cond, %z400 call void @use(i1 %cmp8)401 %cmp9 = icmp eq i32 %cond, %z402 call void @use(i1 %cmp9)403 %cmp10 = icmp ne i32 %cond, %z404 call void @use(i1 %cmp10)405 ret void406end:407 ret void408}409 410define void @slt_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {411; CHECK-LABEL: @slt_smax_contextual_commuted(412; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]]413; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]414; CHECK: if:415; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])416; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]]417; CHECK-NEXT: call void @use(i1 [[CMP1]])418; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]419; CHECK-NEXT: call void @use(i1 [[CMP2]])420; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]421; CHECK-NEXT: call void @use(i1 [[CMP3]])422; CHECK-NEXT: [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]]423; CHECK-NEXT: call void @use(i1 [[CMP4]])424; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]425; CHECK-NEXT: call void @use(i1 [[CMP5]])426; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]427; CHECK-NEXT: call void @use(i1 [[CMP6]])428; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]429; CHECK-NEXT: call void @use(i1 [[CMP7]])430; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]431; CHECK-NEXT: call void @use(i1 [[CMP8]])432; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i32 [[Y]], [[Z]]433; CHECK-NEXT: call void @use(i1 [[CMP9]])434; CHECK-NEXT: [[CMP10:%.*]] = icmp ne i32 [[Y]], [[Z]]435; CHECK-NEXT: call void @use(i1 [[CMP10]])436; CHECK-NEXT: ret void437; CHECK: end:438; CHECK-NEXT: ret void439;440 %cmp = icmp slt i32 %x, %z441 br i1 %cmp, label %if, label %end442if:443 %cond = call i32 @llvm.smax.i32(i32 %y, i32 %x)444 %cmp1 = icmp slt i32 %cond, %z445 call void @use(i1 %cmp1)446 %cmp2 = icmp sle i32 %cond, %z447 call void @use(i1 %cmp2)448 %cmp3 = icmp sgt i32 %cond, %z449 call void @use(i1 %cmp3)450 %cmp4 = icmp sge i32 %cond, %z451 call void @use(i1 %cmp4)452 %cmp5 = icmp ult i32 %cond, %z453 call void @use(i1 %cmp5)454 %cmp6 = icmp ule i32 %cond, %z455 call void @use(i1 %cmp6)456 %cmp7 = icmp ugt i32 %cond, %z457 call void @use(i1 %cmp7)458 %cmp8 = icmp uge i32 %cond, %z459 call void @use(i1 %cmp8)460 %cmp9 = icmp eq i32 %cond, %z461 call void @use(i1 %cmp9)462 %cmp10 = icmp ne i32 %cond, %z463 call void @use(i1 %cmp10)464 ret void465end:466 ret void467}468 469define void @sle_smax_contextual(i32 %x, i32 %y, i32 %z) {470; CHECK-LABEL: @sle_smax_contextual(471; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]]472; CHECK-NEXT: br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]473; CHECK: if:474; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])475; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]476; CHECK-NEXT: call void @use(i1 [[CMP1]])477; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]478; CHECK-NEXT: call void @use(i1 [[CMP2]])479; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]480; CHECK-NEXT: call void @use(i1 [[CMP3]])481; CHECK-NEXT: [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]482; CHECK-NEXT: call void @use(i1 [[CMP4]])483; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]484; CHECK-NEXT: call void @use(i1 [[CMP5]])485; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]486; CHECK-NEXT: call void @use(i1 [[CMP6]])487; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]488; CHECK-NEXT: call void @use(i1 [[CMP7]])489; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]490; CHECK-NEXT: call void @use(i1 [[CMP8]])491; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]492; CHECK-NEXT: call void @use(i1 [[CMP9]])493; CHECK-NEXT: [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]494; CHECK-NEXT: call void @use(i1 [[CMP10]])495; CHECK-NEXT: ret void496; CHECK: end:497; CHECK-NEXT: ret void498;499 %cmp = icmp sle i32 %x, %z500 br i1 %cmp, label %if, label %end501if:502 %cond = call i32 @llvm.smax.i32(i32 %x, i32 %y)503 %cmp1 = icmp slt i32 %cond, %z504 call void @use(i1 %cmp1)505 %cmp2 = icmp sle i32 %cond, %z506 call void @use(i1 %cmp2)507 %cmp3 = icmp sgt i32 %cond, %z508 call void @use(i1 %cmp3)509 %cmp4 = icmp sge i32 %cond, %z510 call void @use(i1 %cmp4)511 %cmp5 = icmp ult i32 %cond, %z512 call void @use(i1 %cmp5)513 %cmp6 = icmp ule i32 %cond, %z514 call void @use(i1 %cmp6)515 %cmp7 = icmp ugt i32 %cond, %z516 call void @use(i1 %cmp7)517 %cmp8 = icmp uge i32 %cond, %z518 call void @use(i1 %cmp8)519 %cmp9 = icmp eq i32 %cond, %z520 call void @use(i1 %cmp9)521 %cmp10 = icmp ne i32 %cond, %z522 call void @use(i1 %cmp10)523 ret void524end:525 ret void526}527 528define void @sle_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {529; CHECK-LABEL: @sle_smax_contextual_commuted(530; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]]531; CHECK-NEXT: br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]532; CHECK: if:533; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])534; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]]535; CHECK-NEXT: call void @use(i1 [[CMP1]])536; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]]537; CHECK-NEXT: call void @use(i1 [[CMP2]])538; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]]539; CHECK-NEXT: call void @use(i1 [[CMP3]])540; CHECK-NEXT: [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]]541; CHECK-NEXT: call void @use(i1 [[CMP4]])542; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]543; CHECK-NEXT: call void @use(i1 [[CMP5]])544; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]545; CHECK-NEXT: call void @use(i1 [[CMP6]])546; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]547; CHECK-NEXT: call void @use(i1 [[CMP7]])548; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]549; CHECK-NEXT: call void @use(i1 [[CMP8]])550; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]551; CHECK-NEXT: call void @use(i1 [[CMP9]])552; CHECK-NEXT: [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]553; CHECK-NEXT: call void @use(i1 [[CMP10]])554; CHECK-NEXT: ret void555; CHECK: end:556; CHECK-NEXT: ret void557;558 %cmp = icmp sle i32 %x, %z559 br i1 %cmp, label %if, label %end560if:561 %cond = call i32 @llvm.smax.i32(i32 %y, i32 %x)562 %cmp1 = icmp slt i32 %cond, %z563 call void @use(i1 %cmp1)564 %cmp2 = icmp sle i32 %cond, %z565 call void @use(i1 %cmp2)566 %cmp3 = icmp sgt i32 %cond, %z567 call void @use(i1 %cmp3)568 %cmp4 = icmp sge i32 %cond, %z569 call void @use(i1 %cmp4)570 %cmp5 = icmp ult i32 %cond, %z571 call void @use(i1 %cmp5)572 %cmp6 = icmp ule i32 %cond, %z573 call void @use(i1 %cmp6)574 %cmp7 = icmp ugt i32 %cond, %z575 call void @use(i1 %cmp7)576 %cmp8 = icmp uge i32 %cond, %z577 call void @use(i1 %cmp8)578 %cmp9 = icmp eq i32 %cond, %z579 call void @use(i1 %cmp9)580 %cmp10 = icmp ne i32 %cond, %z581 call void @use(i1 %cmp10)582 ret void583end:584 ret void585}586 587define void @sgt_smax_contextual(i32 %x, i32 %y, i32 %z) {588; CHECK-LABEL: @sgt_smax_contextual(589; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]]590; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]591; CHECK: if:592; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])593; CHECK-NEXT: call void @use(i1 false)594; CHECK-NEXT: call void @use(i1 false)595; CHECK-NEXT: call void @use(i1 true)596; CHECK-NEXT: call void @use(i1 true)597; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]598; CHECK-NEXT: call void @use(i1 [[CMP5]])599; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]600; CHECK-NEXT: call void @use(i1 [[CMP6]])601; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]602; CHECK-NEXT: call void @use(i1 [[CMP7]])603; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]604; CHECK-NEXT: call void @use(i1 [[CMP8]])605; CHECK-NEXT: call void @use(i1 false)606; CHECK-NEXT: call void @use(i1 true)607; CHECK-NEXT: ret void608; CHECK: end:609; CHECK-NEXT: ret void610;611 %cmp = icmp sgt i32 %x, %z612 br i1 %cmp, label %if, label %end613if:614 %cond = call i32 @llvm.smax.i32(i32 %x, i32 %y)615 %cmp1 = icmp slt i32 %cond, %z616 call void @use(i1 %cmp1)617 %cmp2 = icmp sle i32 %cond, %z618 call void @use(i1 %cmp2)619 %cmp3 = icmp sgt i32 %cond, %z620 call void @use(i1 %cmp3)621 %cmp4 = icmp sge i32 %cond, %z622 call void @use(i1 %cmp4)623 %cmp5 = icmp ult i32 %cond, %z624 call void @use(i1 %cmp5)625 %cmp6 = icmp ule i32 %cond, %z626 call void @use(i1 %cmp6)627 %cmp7 = icmp ugt i32 %cond, %z628 call void @use(i1 %cmp7)629 %cmp8 = icmp uge i32 %cond, %z630 call void @use(i1 %cmp8)631 %cmp9 = icmp eq i32 %cond, %z632 call void @use(i1 %cmp9)633 %cmp10 = icmp ne i32 %cond, %z634 call void @use(i1 %cmp10)635 ret void636end:637 ret void638}639 640define void @sgt_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {641; CHECK-LABEL: @sgt_smax_contextual_commuted(642; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]]643; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]644; CHECK: if:645; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])646; CHECK-NEXT: call void @use(i1 false)647; CHECK-NEXT: call void @use(i1 false)648; CHECK-NEXT: call void @use(i1 true)649; CHECK-NEXT: call void @use(i1 true)650; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]651; CHECK-NEXT: call void @use(i1 [[CMP5]])652; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]653; CHECK-NEXT: call void @use(i1 [[CMP6]])654; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]655; CHECK-NEXT: call void @use(i1 [[CMP7]])656; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]657; CHECK-NEXT: call void @use(i1 [[CMP8]])658; CHECK-NEXT: call void @use(i1 false)659; CHECK-NEXT: call void @use(i1 true)660; CHECK-NEXT: ret void661; CHECK: end:662; CHECK-NEXT: ret void663;664 %cmp = icmp sgt i32 %x, %z665 br i1 %cmp, label %if, label %end666if:667 %cond = call i32 @llvm.smax.i32(i32 %y, i32 %x)668 %cmp1 = icmp slt i32 %cond, %z669 call void @use(i1 %cmp1)670 %cmp2 = icmp sle i32 %cond, %z671 call void @use(i1 %cmp2)672 %cmp3 = icmp sgt i32 %cond, %z673 call void @use(i1 %cmp3)674 %cmp4 = icmp sge i32 %cond, %z675 call void @use(i1 %cmp4)676 %cmp5 = icmp ult i32 %cond, %z677 call void @use(i1 %cmp5)678 %cmp6 = icmp ule i32 %cond, %z679 call void @use(i1 %cmp6)680 %cmp7 = icmp ugt i32 %cond, %z681 call void @use(i1 %cmp7)682 %cmp8 = icmp uge i32 %cond, %z683 call void @use(i1 %cmp8)684 %cmp9 = icmp eq i32 %cond, %z685 call void @use(i1 %cmp9)686 %cmp10 = icmp ne i32 %cond, %z687 call void @use(i1 %cmp10)688 ret void689end:690 ret void691}692 693define void @sge_smax_contextual(i32 %x, i32 %y, i32 %z) {694; CHECK-LABEL: @sge_smax_contextual(695; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]]696; CHECK-NEXT: br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]697; CHECK: if:698; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Y:%.*]])699; CHECK-NEXT: call void @use(i1 false)700; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]701; CHECK-NEXT: call void @use(i1 [[CMP2]])702; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]703; CHECK-NEXT: call void @use(i1 [[CMP3]])704; CHECK-NEXT: call void @use(i1 true)705; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]706; CHECK-NEXT: call void @use(i1 [[CMP5]])707; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]708; CHECK-NEXT: call void @use(i1 [[CMP6]])709; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]710; CHECK-NEXT: call void @use(i1 [[CMP7]])711; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]712; CHECK-NEXT: call void @use(i1 [[CMP8]])713; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]714; CHECK-NEXT: call void @use(i1 [[CMP9]])715; CHECK-NEXT: [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]716; CHECK-NEXT: call void @use(i1 [[CMP10]])717; CHECK-NEXT: ret void718; CHECK: end:719; CHECK-NEXT: ret void720;721 %cmp = icmp sge i32 %x, %z722 br i1 %cmp, label %if, label %end723if:724 %cond = call i32 @llvm.smax.i32(i32 %x, i32 %y)725 %cmp1 = icmp slt i32 %cond, %z726 call void @use(i1 %cmp1)727 %cmp2 = icmp sle i32 %cond, %z728 call void @use(i1 %cmp2)729 %cmp3 = icmp sgt i32 %cond, %z730 call void @use(i1 %cmp3)731 %cmp4 = icmp sge i32 %cond, %z732 call void @use(i1 %cmp4)733 %cmp5 = icmp ult i32 %cond, %z734 call void @use(i1 %cmp5)735 %cmp6 = icmp ule i32 %cond, %z736 call void @use(i1 %cmp6)737 %cmp7 = icmp ugt i32 %cond, %z738 call void @use(i1 %cmp7)739 %cmp8 = icmp uge i32 %cond, %z740 call void @use(i1 %cmp8)741 %cmp9 = icmp eq i32 %cond, %z742 call void @use(i1 %cmp9)743 %cmp10 = icmp ne i32 %cond, %z744 call void @use(i1 %cmp10)745 ret void746end:747 ret void748}749 750define void @sge_smax_contextual_commuted(i32 %x, i32 %y, i32 %z) {751; CHECK-LABEL: @sge_smax_contextual_commuted(752; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]]753; CHECK-NEXT: br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]]754; CHECK: if:755; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[Y:%.*]], i32 [[X]])756; CHECK-NEXT: call void @use(i1 false)757; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]]758; CHECK-NEXT: call void @use(i1 [[CMP2]])759; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]]760; CHECK-NEXT: call void @use(i1 [[CMP3]])761; CHECK-NEXT: call void @use(i1 true)762; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]]763; CHECK-NEXT: call void @use(i1 [[CMP5]])764; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]]765; CHECK-NEXT: call void @use(i1 [[CMP6]])766; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]]767; CHECK-NEXT: call void @use(i1 [[CMP7]])768; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]]769; CHECK-NEXT: call void @use(i1 [[CMP8]])770; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]]771; CHECK-NEXT: call void @use(i1 [[CMP9]])772; CHECK-NEXT: [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]]773; CHECK-NEXT: call void @use(i1 [[CMP10]])774; CHECK-NEXT: ret void775; CHECK: end:776; CHECK-NEXT: ret void777;778 %cmp = icmp sge i32 %x, %z779 br i1 %cmp, label %if, label %end780if:781 %cond = call i32 @llvm.smax.i32(i32 %y, i32 %x)782 %cmp1 = icmp slt i32 %cond, %z783 call void @use(i1 %cmp1)784 %cmp2 = icmp sle i32 %cond, %z785 call void @use(i1 %cmp2)786 %cmp3 = icmp sgt i32 %cond, %z787 call void @use(i1 %cmp3)788 %cmp4 = icmp sge i32 %cond, %z789 call void @use(i1 %cmp4)790 %cmp5 = icmp ult i32 %cond, %z791 call void @use(i1 %cmp5)792 %cmp6 = icmp ule i32 %cond, %z793 call void @use(i1 %cmp6)794 %cmp7 = icmp ugt i32 %cond, %z795 call void @use(i1 %cmp7)796 %cmp8 = icmp uge i32 %cond, %z797 call void @use(i1 %cmp8)798 %cmp9 = icmp eq i32 %cond, %z799 call void @use(i1 %cmp9)800 %cmp10 = icmp ne i32 %cond, %z801 call void @use(i1 %cmp10)802 ret void803end:804 ret void805}806 807; Tests from PR76672808 809define i1 @test_smax_ugt(i32 %a) {810; CHECK-LABEL: @test_smax_ugt(811; CHECK-NEXT: entry:812; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 1813; CHECK-NEXT: ret i1 [[CMP]]814;815entry:816 %cond.i = call i32 @llvm.smax.i32(i32 %a, i32 0)817 %cmp = icmp ugt i32 %cond.i, 1818 ret i1 %cmp819}820 821; Negative tests822 823define i1 @test_smax_ugt_neg1(i32 %a) {824; CHECK-LABEL: @test_smax_ugt_neg1(825; CHECK-NEXT: entry:826; CHECK-NEXT: ret i1 false827;828entry:829 %cond.i = call i32 @llvm.smax.i32(i32 %a, i32 0)830 %cmp = icmp ugt i32 %cond.i, -5831 ret i1 %cmp832}833 834define i1 @test_smax_ugt_neg2(i32 %a) {835; CHECK-LABEL: @test_smax_ugt_neg2(836; CHECK-NEXT: entry:837; CHECK-NEXT: [[COND_I:%.*]] = call i32 @llvm.smax.i32(i32 [[A:%.*]], i32 -5)838; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[COND_I]], 1839; CHECK-NEXT: ret i1 [[CMP]]840;841entry:842 %cond.i = call i32 @llvm.smax.i32(i32 %a, i32 -5)843 %cmp = icmp ugt i32 %cond.i, 1844 ret i1 %cmp845}846 847 848declare i32 @llvm.smax.i32(i32, i32)849