Index: lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineSelect.cpp +++ lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -506,9 +506,51 @@ return true; } +/// If this is an integer min/max where the select's 'true' operand is a +/// constant, canonicalize that constant to the 'false' operand: +/// select (icmp Pred X, C), C, X --> select (icmp Pred' X, C), X, C +static Instruction * +canonicalizeMinMaxWithConstant(SelectInst &Sel, ICmpInst &Cmp, + InstCombiner::BuilderTy &Builder) { + // TODO: We should also canonicalize min/max when the select has a different + // constant value than the cmp constant, but we need to fix the backend first. + if (!Cmp.hasOneUse() || !isa(Cmp.getOperand(1)) || + !isa(Sel.getTrueValue()) || + isa(Sel.getFalseValue()) || + Cmp.getOperand(1) != Sel.getTrueValue()) + return nullptr; + + // Canonicalize the compare predicate based on whether we have min or max. + Value *LHS, *RHS; + ICmpInst::Predicate NewPred; + SelectPatternResult SPR = matchSelectPattern(&Sel, LHS, RHS); + switch (SPR.Flavor) { + case SPF_SMIN: NewPred = ICmpInst::ICMP_SLT; break; + case SPF_UMIN: NewPred = ICmpInst::ICMP_ULT; break; + case SPF_SMAX: NewPred = ICmpInst::ICMP_SGT; break; + case SPF_UMAX: NewPred = ICmpInst::ICMP_UGT; break; + default: return nullptr; + } + + // Canonicalize the constant to the right side. + if (isa(LHS)) + std::swap(LHS, RHS); + + Value *NewCmp = Builder.CreateICmp(NewPred, LHS, RHS); + SelectInst *NewSel = SelectInst::Create(NewCmp, LHS, RHS); + NewSel->copyMetadata(Sel); + + // We swapped the select operands, so swap the metadata too. + NewSel->swapProfMetadata(); + return NewSel; +} + /// Visit a SelectInst that has an ICmpInst as its first operand. Instruction *InstCombiner::foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI) { + if (Instruction *NewSel = canonicalizeMinMaxWithConstant(SI, *ICI, *Builder)) + return NewSel; + bool Changed = adjustMinMax(SI, *ICI); ICmpInst::Predicate Pred = ICI->getPredicate(); Index: test/Transforms/InstCombine/adjust-for-minmax.ll =================================================================== --- test/Transforms/InstCombine/adjust-for-minmax.ll +++ test/Transforms/InstCombine/adjust-for-minmax.ll @@ -29,7 +29,7 @@ ret i32 %m } -; Canonicalize icmp predicate. +; Canonicalize min/max. define i32 @smax2(i32 %n) { ; CHECK-LABEL: @smax2( @@ -42,7 +42,7 @@ ret i32 %m } -; Canonicalize icmp predicate. +; Canonicalize min/max. define i32 @smin2(i32 %n) { ; CHECK-LABEL: @smin2( @@ -55,12 +55,12 @@ ret i32 %m } -; Swap signed pred and select ops. +; Canonicalize min/max. define i32 @smax3(i32 %n) { ; CHECK-LABEL: @smax3( -; CHECK-NEXT: [[T:%.*]] = icmp slt i32 %n, 0 -; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 0, i32 %n +; CHECK-NEXT: [[T:%.*]] = icmp sgt i32 %n, 0 +; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 %n, i32 0 ; CHECK-NEXT: ret i32 [[M]] ; %t = icmp sgt i32 %n, -1 @@ -68,12 +68,12 @@ ret i32 %m } -; Swap vector signed pred and select ops. +; Canonicalize min/max. define <2 x i32> @smax3_vec(<2 x i32> %n) { ; CHECK-LABEL: @smax3_vec( -; CHECK-NEXT: [[T:%.*]] = icmp slt <2 x i32> %n, zeroinitializer -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> zeroinitializer, <2 x i32> %n +; CHECK-NEXT: [[T:%.*]] = icmp sgt <2 x i32> %n, zeroinitializer +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> zeroinitializer ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp sgt <2 x i32> %n, @@ -81,12 +81,12 @@ ret <2 x i32> %m } -; Swap signed pred and select ops. +; Canonicalize min/max. define i32 @smin3(i32 %n) { ; CHECK-LABEL: @smin3( -; CHECK-NEXT: [[T:%.*]] = icmp sgt i32 %n, 0 -; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 0, i32 %n +; CHECK-NEXT: [[T:%.*]] = icmp slt i32 %n, 0 +; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 %n, i32 0 ; CHECK-NEXT: ret i32 [[M]] ; %t = icmp slt i32 %n, 1 @@ -94,12 +94,12 @@ ret i32 %m } -; Swap vector signed pred and select ops. +; Canonicalize min/max. define <2 x i32> @smin3_vec(<2 x i32> %n) { ; CHECK-LABEL: @smin3_vec( -; CHECK-NEXT: [[T:%.*]] = icmp sgt <2 x i32> %n, zeroinitializer -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> zeroinitializer, <2 x i32> %n +; CHECK-NEXT: [[T:%.*]] = icmp slt <2 x i32> %n, zeroinitializer +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> zeroinitializer ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp slt <2 x i32> %n, @@ -107,12 +107,12 @@ ret <2 x i32> %m } -; Swap unsigned pred and select ops. +; Canonicalize min/max. define i32 @umax3(i32 %n) { ; CHECK-LABEL: @umax3( -; CHECK-NEXT: [[T:%.*]] = icmp ult i32 %n, 5 -; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 5, i32 %n +; CHECK-NEXT: [[T:%.*]] = icmp ugt i32 %n, 5 +; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 %n, i32 5 ; CHECK-NEXT: ret i32 [[M]] ; %t = icmp ugt i32 %n, 4 @@ -120,12 +120,12 @@ ret i32 %m } -; Swap vector unsigned pred and select ops. +; Canonicalize min/max. define <2 x i32> @umax3_vec(<2 x i32> %n) { ; CHECK-LABEL: @umax3_vec( -; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> %n, -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> , <2 x i32> %n +; CHECK-NEXT: [[T:%.*]] = icmp ugt <2 x i32> %n, +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp ugt <2 x i32> %n, @@ -133,12 +133,12 @@ ret <2 x i32> %m } -; Swap unsigned pred and select ops. +; Canonicalize min/max. define i32 @umin3(i32 %n) { ; CHECK-LABEL: @umin3( -; CHECK-NEXT: [[T:%.*]] = icmp ugt i32 %n, 6 -; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 6, i32 %n +; CHECK-NEXT: [[T:%.*]] = icmp ult i32 %n, 6 +; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 %n, i32 6 ; CHECK-NEXT: ret i32 [[M]] ; %t = icmp ult i32 %n, 7 @@ -146,12 +146,12 @@ ret i32 %m } -; Swap vector unsigned pred and select ops. +; Canonicalize min/max. define <2 x i32> @umin3_vec(<2 x i32> %n) { ; CHECK-LABEL: @umin3_vec( -; CHECK-NEXT: [[T:%.*]] = icmp ugt <2 x i32> %n, -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> , <2 x i32> %n +; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> %n, +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp ult <2 x i32> %n, @@ -159,12 +159,12 @@ ret <2 x i32> %m } -; Canonicalize signed pred and swap pred and select ops. +; Canonicalize min/max. define i32 @smax4(i32 %n) { ; CHECK-LABEL: @smax4( -; CHECK-NEXT: [[T:%.*]] = icmp slt i32 %n, 0 -; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 0, i32 %n +; CHECK-NEXT: [[T:%.*]] = icmp sgt i32 %n, 0 +; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 %n, i32 0 ; CHECK-NEXT: ret i32 [[M]] ; %t = icmp sge i32 %n, 0 @@ -172,12 +172,12 @@ ret i32 %m } -; Canonicalize vector signed pred and swap pred and select ops. +; Canonicalize min/max. define <2 x i32> @smax4_vec(<2 x i32> %n) { ; CHECK-LABEL: @smax4_vec( -; CHECK-NEXT: [[T:%.*]] = icmp slt <2 x i32> %n, zeroinitializer -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> zeroinitializer, <2 x i32> %n +; CHECK-NEXT: [[T:%.*]] = icmp sgt <2 x i32> %n, zeroinitializer +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> zeroinitializer ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp sge <2 x i32> %n, zeroinitializer @@ -185,12 +185,12 @@ ret <2 x i32> %m } -; Canonicalize signed pred and swap pred and select ops. +; Canonicalize min/max. define i32 @smin4(i32 %n) { ; CHECK-LABEL: @smin4( -; CHECK-NEXT: [[T:%.*]] = icmp sgt i32 %n, 0 -; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 0, i32 %n +; CHECK-NEXT: [[T:%.*]] = icmp slt i32 %n, 0 +; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 %n, i32 0 ; CHECK-NEXT: ret i32 [[M]] ; %t = icmp sle i32 %n, 0 @@ -198,12 +198,12 @@ ret i32 %m } -; Canonicalize vector signed pred and swap pred and select ops. +; Canonicalize min/max. define <2 x i32> @smin4_vec(<2 x i32> %n) { ; CHECK-LABEL: @smin4_vec( -; CHECK-NEXT: [[T:%.*]] = icmp sgt <2 x i32> %n, zeroinitializer -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> zeroinitializer, <2 x i32> %n +; CHECK-NEXT: [[T:%.*]] = icmp slt <2 x i32> %n, zeroinitializer +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> zeroinitializer ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp sle <2 x i32> %n, zeroinitializer @@ -211,12 +211,12 @@ ret <2 x i32> %m } -; Canonicalize unsigned pred and swap pred and select ops. +; Canonicalize min/max. define i32 @umax4(i32 %n) { ; CHECK-LABEL: @umax4( -; CHECK-NEXT: [[T:%.*]] = icmp ult i32 %n, 8 -; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 8, i32 %n +; CHECK-NEXT: [[T:%.*]] = icmp ugt i32 %n, 8 +; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 %n, i32 8 ; CHECK-NEXT: ret i32 [[M]] ; %t = icmp uge i32 %n, 8 @@ -224,12 +224,12 @@ ret i32 %m } -; Canonicalize vector unsigned pred and swap pred and select ops. +; Canonicalize min/max. define <2 x i32> @umax4_vec(<2 x i32> %n) { ; CHECK-LABEL: @umax4_vec( -; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> %n, -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> , <2 x i32> %n +; CHECK-NEXT: [[T:%.*]] = icmp ugt <2 x i32> %n, +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp uge <2 x i32> %n, @@ -237,12 +237,12 @@ ret <2 x i32> %m } -; Canonicalize unsigned pred and swap pred and select ops. +; Canonicalize min/max. define i32 @umin4(i32 %n) { ; CHECK-LABEL: @umin4( -; CHECK-NEXT: [[T:%.*]] = icmp ugt i32 %n, 9 -; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 9, i32 %n +; CHECK-NEXT: [[T:%.*]] = icmp ult i32 %n, 9 +; CHECK-NEXT: [[M:%.*]] = select i1 [[T]], i32 %n, i32 9 ; CHECK-NEXT: ret i32 [[M]] ; %t = icmp ule i32 %n, 9 @@ -250,12 +250,12 @@ ret i32 %m } -; Canonicalize vector unsigned pred and swap pred and select ops. +; Canonicalize min/max. define <2 x i32> @umin4_vec(<2 x i32> %n) { ; CHECK-LABEL: @umin4_vec( -; CHECK-NEXT: [[T:%.*]] = icmp ugt <2 x i32> %n, -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> , <2 x i32> %n +; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> %n, +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp ule <2 x i32> %n, @@ -266,8 +266,8 @@ define i64 @smax_sext(i32 %a) { ; CHECK-LABEL: @smax_sext( ; CHECK-NEXT: [[A_EXT:%.*]] = sext i32 %a to i64 -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[A_EXT]], 0 -; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP]], i64 0, i64 [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[A_EXT]], 0 +; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP]], i64 [[A_EXT]], i64 0 ; CHECK-NEXT: ret i64 [[MAX]] ; %a_ext = sext i32 %a to i64 @@ -279,8 +279,8 @@ define <2 x i64> @smax_sext_vec(<2 x i32> %a) { ; CHECK-LABEL: @smax_sext_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = sext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i64> [[A_EXT]], zeroinitializer -; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[CMP]], <2 x i64> zeroinitializer, <2 x i64> [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i64> [[A_EXT]], zeroinitializer +; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> zeroinitializer ; CHECK-NEXT: ret <2 x i64> [[MAX]] ; %a_ext = sext <2 x i32> %a to <2 x i64> @@ -292,8 +292,8 @@ define i64 @smin_sext(i32 %a) { ; CHECK-LABEL: @smin_sext( ; CHECK-NEXT: [[A_EXT:%.*]] = sext i32 %a to i64 -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[A_EXT]], 0 -; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP]], i64 0, i64 [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[A_EXT]], 0 +; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP]], i64 [[A_EXT]], i64 0 ; CHECK-NEXT: ret i64 [[MIN]] ; %a_ext = sext i32 %a to i64 @@ -305,8 +305,8 @@ define <2 x i64>@smin_sext_vec(<2 x i32> %a) { ; CHECK-LABEL: @smin_sext_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = sext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i64> [[A_EXT]], zeroinitializer -; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> zeroinitializer, <2 x i64> [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i64> [[A_EXT]], zeroinitializer +; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> zeroinitializer ; CHECK-NEXT: ret <2 x i64> [[MIN]] ; %a_ext = sext <2 x i32> %a to <2 x i64> @@ -318,8 +318,8 @@ define i64 @umax_sext(i32 %a) { ; CHECK-LABEL: @umax_sext( ; CHECK-NEXT: [[A_EXT:%.*]] = sext i32 %a to i64 -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[A_EXT]], 3 -; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP]], i64 3, i64 [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[A_EXT]], 3 +; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP]], i64 [[A_EXT]], i64 3 ; CHECK-NEXT: ret i64 [[MAX]] ; %a_ext = sext i32 %a to i64 @@ -331,8 +331,8 @@ define <2 x i64> @umax_sext_vec(<2 x i32> %a) { ; CHECK-LABEL: @umax_sext_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = sext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i64> [[A_EXT]], -; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[CMP]], <2 x i64> , <2 x i64> [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i64> [[A_EXT]], +; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[MAX]] ; %a_ext = sext <2 x i32> %a to <2 x i64> @@ -344,8 +344,8 @@ define i64 @umin_sext(i32 %a) { ; CHECK-LABEL: @umin_sext( ; CHECK-NEXT: [[A_EXT:%.*]] = sext i32 %a to i64 -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[A_EXT]], 2 -; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP]], i64 2, i64 [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[A_EXT]], 2 +; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP]], i64 [[A_EXT]], i64 2 ; CHECK-NEXT: ret i64 [[MIN]] ; %a_ext = sext i32 %a to i64 @@ -357,8 +357,8 @@ define <2 x i64> @umin_sext_vec(<2 x i32> %a) { ; CHECK-LABEL: @umin_sext_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = sext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i64> [[A_EXT]], -; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> , <2 x i64> [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i64> [[A_EXT]], +; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[MIN]] ; %a_ext = sext <2 x i32> %a to <2 x i64> @@ -422,8 +422,8 @@ define i64 @umax_zext(i32 %a) { ; CHECK-LABEL: @umax_zext( ; CHECK-NEXT: [[A_EXT:%.*]] = zext i32 %a to i64 -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[A_EXT]], 3 -; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP]], i64 3, i64 [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[A_EXT]], 3 +; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP]], i64 [[A_EXT]], i64 3 ; CHECK-NEXT: ret i64 [[MAX]] ; %a_ext = zext i32 %a to i64 @@ -435,8 +435,8 @@ define <2 x i64> @umax_zext_vec(<2 x i32> %a) { ; CHECK-LABEL: @umax_zext_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = zext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i64> [[A_EXT]], -; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[CMP]], <2 x i64> , <2 x i64> [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i64> [[A_EXT]], +; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[MAX]] ; %a_ext = zext <2 x i32> %a to <2 x i64> @@ -448,8 +448,8 @@ define i64 @umin_zext(i32 %a) { ; CHECK-LABEL: @umin_zext( ; CHECK-NEXT: [[A_EXT:%.*]] = zext i32 %a to i64 -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[A_EXT]], 2 -; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP]], i64 2, i64 [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[A_EXT]], 2 +; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP]], i64 [[A_EXT]], i64 2 ; CHECK-NEXT: ret i64 [[MIN]] ; %a_ext = zext i32 %a to i64 @@ -461,8 +461,8 @@ define <2 x i64> @umin_zext_vec(<2 x i32> %a) { ; CHECK-LABEL: @umin_zext_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = zext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i64> [[A_EXT]], -; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> , <2 x i64> [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i64> [[A_EXT]], +; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[MIN]] ; %a_ext = zext <2 x i32> %a to <2 x i64> Index: test/Transforms/InstCombine/div-shift.ll =================================================================== --- test/Transforms/InstCombine/div-shift.ll +++ test/Transforms/InstCombine/div-shift.ll @@ -45,8 +45,8 @@ define i32 @t4(i32 %x, i32 %y) { ; CHECK-LABEL: @t4( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 %y, 5 -; CHECK-NEXT: [[DOTV:%.*]] = select i1 [[TMP1]], i32 5, i32 %y +; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 %y, 5 +; CHECK-NEXT: [[DOTV:%.*]] = select i1 [[TMP1]], i32 %y, i32 5 ; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 %x, [[DOTV]] ; CHECK-NEXT: ret i32 [[TMP2]] ; Index: test/Transforms/InstCombine/minmax-fold.ll =================================================================== --- test/Transforms/InstCombine/minmax-fold.ll +++ test/Transforms/InstCombine/minmax-fold.ll @@ -200,8 +200,8 @@ ; SMIN(SMIN(X, 11), 92) -> SMIN(X, 11) define i32 @test68(i32 %x) { ; CHECK-LABEL: @test68( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, 11 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 11, i32 %x +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 %x, 11 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP1]], i32 %x, i32 11 ; CHECK-NEXT: ret i32 [[COND]] ; %cmp = icmp slt i32 11, %x @@ -213,8 +213,8 @@ define <2 x i32> @test68vec(<2 x i32> %x) { ; CHECK-LABEL: @test68vec( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> %x, -; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> , <2 x i32> %x +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i32> %x, +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> %x, <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[COND]] ; %cmp = icmp slt <2 x i32> , %x @@ -227,8 +227,8 @@ ; MIN(MIN(X, 24), 83) -> MIN(X, 24) define i32 @test69(i32 %x) { ; CHECK-LABEL: @test69( -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 %x, 24 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 24, i32 %x +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 %x, 24 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP1]], i32 %x, i32 24 ; CHECK-NEXT: ret i32 [[COND]] ; %cmp = icmp ult i32 24, %x @@ -241,8 +241,8 @@ ; SMAX(SMAX(X, 75), 36) -> SMAX(X, 75) define i32 @test70(i32 %x) { ; CHECK-LABEL: @test70( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 %x, 75 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 75, i32 %x +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 %x, 75 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP1]], i32 %x, i32 75 ; CHECK-NEXT: ret i32 [[COND]] ; %cmp = icmp slt i32 %x, 75 @@ -255,8 +255,8 @@ ; MAX(MAX(X, 68), 47) -> MAX(X, 68) define i32 @test71(i32 %x) { ; CHECK-LABEL: @test71( -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 %x, 68 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 68, i32 %x +; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 %x, 68 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP1]], i32 %x, i32 68 ; CHECK-NEXT: ret i32 [[COND]] ; %cmp = icmp ult i32 %x, 68 @@ -269,8 +269,8 @@ ; SMIN(SMIN(X, 92), 11) -> SMIN(X, 11) define i32 @test72(i32 %x) { ; CHECK-LABEL: @test72( -; CHECK-NEXT: [[CMP31:%.*]] = icmp sgt i32 %x, 11 -; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[CMP31]], i32 11, i32 %x +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 %x, 11 +; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[TMP1]], i32 %x, i32 11 ; CHECK-NEXT: ret i32 [[RETVAL]] ; %cmp = icmp sgt i32 %x, 92 @@ -280,14 +280,14 @@ ret i32 %retval } -; FIXME - vector neglect: FoldOrOfICmps() +; FIXME - vector neglect: FoldAndOfICmps() / FoldOrOfICmps() define <2 x i32> @test72vec(<2 x i32> %x) { ; CHECK-LABEL: @test72vec( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> %x, -; CHECK-NEXT: [[CMP31:%.*]] = icmp sgt <2 x i32> %x, -; CHECK-NEXT: [[CMP3:%.*]] = or <2 x i1> [[CMP]], [[CMP31:%.*]] -; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[CMP3]], <2 x i32> , <2 x i32> %x +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i32> %x, +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt <2 x i32> %x, +; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i1> [[TMP1]], [[TMP2]] +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> %x, <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[RETVAL]] ; %cmp = icmp sgt <2 x i32> %x, @@ -300,8 +300,8 @@ ; MIN(MIN(X, 83), 24) -> MIN(X, 24) define i32 @test73(i32 %x) { ; CHECK-LABEL: @test73( -; CHECK-NEXT: [[CMP31:%.*]] = icmp ugt i32 %x, 24 -; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[CMP31]], i32 24, i32 %x +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 %x, 24 +; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[TMP1]], i32 %x, i32 24 ; CHECK-NEXT: ret i32 [[RETVAL]] ; %cmp = icmp ugt i32 %x, 83 @@ -314,8 +314,8 @@ ; SMAX(SMAX(X, 36), 75) -> SMAX(X, 75) define i32 @test74(i32 %x) { ; CHECK-LABEL: @test74( -; CHECK-NEXT: [[CMP31:%.*]] = icmp slt i32 %x, 75 -; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[CMP31]], i32 75, i32 %x +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 %x, 75 +; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[TMP1]], i32 %x, i32 75 ; CHECK-NEXT: ret i32 [[RETVAL]] ; %cmp = icmp slt i32 %x, 36 @@ -328,8 +328,8 @@ ; MAX(MAX(X, 47), 68) -> MAX(X, 68) define i32 @test75(i32 %x) { ; CHECK-LABEL: @test75( -; CHECK-NEXT: [[CMP31:%.*]] = icmp ult i32 %x, 68 -; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[CMP31]], i32 68, i32 %x +; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 %x, 68 +; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[TMP1]], i32 %x, i32 68 ; CHECK-NEXT: ret i32 [[RETVAL]] ; %cmp = icmp ult i32 %x, 47 Index: test/Transforms/InstCombine/pr27236.ll =================================================================== --- test/Transforms/InstCombine/pr27236.ll +++ test/Transforms/InstCombine/pr27236.ll @@ -3,8 +3,8 @@ define float @test1(i32 %scale) { ; CHECK-LABEL: @test1( -; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 %scale, 1 -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 1, i32 %scale +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 %scale, 1 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 %scale, i32 1 ; CHECK-NEXT: [[TMP3:%.*]] = sitofp i32 [[TMP2]] to float ; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP2]], 0 ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP4]], float [[TMP3]], float 0.000000e+00 Index: test/Transforms/InstCombine/select_meta.ll =================================================================== --- test/Transforms/InstCombine/select_meta.ll +++ test/Transforms/InstCombine/select_meta.ll @@ -1,4 +1,6 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py and enhanced to include metadata checking. +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; and enhanced to include metadata checking. + ; RUN: opt < %s -instcombine -S | FileCheck %s define i32 @foo(i32) local_unnamed_addr #0 { @@ -51,12 +53,11 @@ ret i32 %6 } -; condition swapped define i64 @test43(i32 %a) nounwind { ; CHECK-LABEL: @test43( ; CHECK-NEXT: [[A_EXT:%.*]] = sext i32 %a to i64 -; CHECK-NEXT: [[IS_A_NONNEGATIVE:%.*]] = icmp slt i64 [[A_EXT]], 0 -; CHECK-NEXT: [[MAX:%.*]] = select i1 [[IS_A_NONNEGATIVE]], i64 0, i64 [[A_EXT]], !prof ![[MD3:[0-9]+]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[A_EXT]], 0 +; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 [[A_EXT]], i64 0, !prof ![[MD1]] ; CHECK-NEXT: ret i64 [[MAX]] ; %a_ext = sext i32 %a to i64 @@ -136,10 +137,12 @@ ret i32 %retval } +; Swap predicate / metadata order +; SMAX(SMAX(X, 75), 36) -> SMAX(X, 75) define i32 @test70(i32 %x) { ; CHECK-LABEL: @test70( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 %x, 75 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 75, i32 %x, !prof ![[MD1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 %x, 75 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP1]], i32 %x, i32 75, !prof ![[MD3:[0-9]+]] ; CHECK-NEXT: ret i32 [[COND]] ; %cmp = icmp slt i32 %x, 75 @@ -149,12 +152,12 @@ ret i32 %retval } - +; Swap predicate / metadata order ; SMIN(SMIN(X, 92), 11) -> SMIN(X, 11) define i32 @test72(i32 %x) { ; CHECK-LABEL: @test72( -; CHECK-NEXT: [[CMP31:%.*]] = icmp sgt i32 %x, 11 -; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[CMP31]], i32 11, i32 %x, !prof ![[MD2:[0-9]+]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 %x, 11 +; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[TMP1]], i32 %x, i32 11, !prof ![[MD4:[0-9]+]] ; CHECK-NEXT: ret i32 [[RETVAL]] ; %cmp = icmp sgt i32 %x, 92 @@ -164,11 +167,12 @@ ret i32 %retval } +; Swap predicate / metadata order ; SMAX(SMAX(X, 36), 75) -> SMAX(X, 75) define i32 @test74(i32 %x) { ; CHECK-LABEL: @test74( -; CHECK-NEXT: [[CMP31:%.*]] = icmp slt i32 %x, 75 -; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[CMP31]], i32 75, i32 %x, !prof ![[MD2]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 %x, 75 +; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[TMP1]], i32 %x, i32 75, !prof ![[MD4]] ; CHECK-NEXT: ret i32 [[RETVAL]] ; %cmp = icmp slt i32 %x, 36 @@ -178,10 +182,122 @@ ret i32 %retval } +; FIXME: +; The compare should change, but the metadata remains the same because the select operands are not swapped. +define i32 @smin1(i32 %x) { +; CHECK-LABEL: @smin1( +; CHECK-NEXT: [[NOT_X:%.*]] = xor i32 %x, -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, 0 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[NOT_X]], i32 -1, !prof ![[MD1]] +; CHECK-NEXT: ret i32 [[SEL]] +; + %not_x = xor i32 %x, -1 + %cmp = icmp sgt i32 %x, 0 + %sel = select i1 %cmp, i32 %not_x, i32 -1, !prof !1 + ret i32 %sel +} + +; FIXME: +; The compare should change, and the metadata is swapped because the select operands are swapped. +define i32 @smin2(i32 %x) { +; CHECK-LABEL: @smin2( +; CHECK-NEXT: [[NOT_X:%.*]] = xor i32 %x, -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 %x, 0 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 -1, i32 [[NOT_X]], !prof ![[MD1]] +; CHECK-NEXT: ret i32 [[SEL]] +; + %not_x = xor i32 %x, -1 + %cmp = icmp slt i32 %x, 0 + %sel = select i1 %cmp, i32 -1, i32 %not_x, !prof !1 + ret i32 %sel +} + +; FIXME: +; The compare should change, but the metadata remains the same because the select operands are not swapped. +define i32 @smax1(i32 %x) { +; CHECK-LABEL: @smax1( +; CHECK-NEXT: [[NOT_X:%.*]] = xor i32 %x, -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 %x, 0 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[NOT_X]], i32 -1, !prof ![[MD1]] +; CHECK-NEXT: ret i32 [[SEL]] +; + %not_x = xor i32 %x, -1 + %cmp = icmp slt i32 %x, 0 + %sel = select i1 %cmp, i32 %not_x, i32 -1, !prof !1 + ret i32 %sel +} + +; FIXME: +; The compare should change, and the metadata is swapped because the select operands are swapped. +define i32 @smax2(i32 %x) { +; CHECK-LABEL: @smax2( +; CHECK-NEXT: [[NOT_X:%.*]] = xor i32 %x, -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, 0 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 -1, i32 [[NOT_X]], !prof ![[MD1]] +; CHECK-NEXT: ret i32 [[SEL]] +; + %not_x = xor i32 %x, -1 + %cmp = icmp sgt i32 %x, 0 + %sel = select i1 %cmp, i32 -1, i32 %not_x, !prof !1 + ret i32 %sel +} + +; FIXME: +; The compare should change, but the metadata remains the same because the select operands are not swapped. +define i32 @umin1(i32 %x) { +; CHECK-LABEL: @umin1( +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, -1 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 %x, i32 -2147483648, !prof ![[MD1]] +; CHECK-NEXT: ret i32 [[SEL]] +; + %cmp = icmp sgt i32 %x, -1 + %sel = select i1 %cmp, i32 %x, i32 -2147483648, !prof !1 + ret i32 %sel +} + +; FIXME: +; The compare should change, and the metadata is swapped because the select operands are swapped. +define i32 @umin2(i32 %x) { +; CHECK-LABEL: @umin2( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 %x, 0 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 2147483647, i32 %x, !prof ![[MD1]] +; CHECK-NEXT: ret i32 [[SEL]] +; + %cmp = icmp slt i32 %x, 0 + %sel = select i1 %cmp, i32 2147483647, i32 %x, !prof !1 + ret i32 %sel +} + +; FIXME: +; The compare should change, but the metadata remains the same because the select operands are not swapped. +define i32 @umax1(i32 %x) { +; CHECK-LABEL: @umax1( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 %x, 0 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 %x, i32 2147483647, !prof ![[MD1]] +; CHECK-NEXT: ret i32 [[SEL]] +; + %cmp = icmp slt i32 %x, 0 + %sel = select i1 %cmp, i32 %x, i32 2147483647, !prof !1 + ret i32 %sel +} + +; FIXME: +; The compare should change, and the metadata is swapped because the select operands are swapped. +define i32 @umax2(i32 %x) { +; CHECK-LABEL: @umax2( +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, -1 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 -2147483648, i32 %x, !prof ![[MD1]] +; CHECK-NEXT: ret i32 [[SEL]] +; + %cmp = icmp sgt i32 %x, -1 + %sel = select i1 %cmp, i32 -2147483648, i32 %x, !prof !1 + ret i32 %sel +} + !1 = !{!"branch_weights", i32 2, i32 10} !2 = !{!"branch_weights", i32 3, i32 10} ; CHECK-DAG: ![[MD1]] = !{!"branch_weights", i32 2, i32 10} -; CHECK-DAG: ![[MD2]] = !{!"branch_weights", i32 3, i32 10} ; CHECK-DAG: ![[MD3]] = !{!"branch_weights", i32 10, i32 2} +; CHECK-DAG: ![[MD4]] = !{!"branch_weights", i32 10, i32 3} Index: test/Transforms/InstCombine/sext.ll =================================================================== --- test/Transforms/InstCombine/sext.ll +++ test/Transforms/InstCombine/sext.ll @@ -229,10 +229,10 @@ define i32 @test18(i16 %x) { ; CHECK-LABEL: @test18( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 %x, 0 -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i16 0, i16 %x -; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[SEL]] to i32 -; CHECK-NEXT: ret i32 [[TMP1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i16 %x, 0 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP1]], i16 %x, i16 0 +; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[SEL]] to i32 +; CHECK-NEXT: ret i32 [[TMP2]] ; %cmp = icmp slt i16 %x, 0 %sel = select i1 %cmp, i16 0, i16 %x