Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1479,6 +1479,33 @@ match(RHS, m_ZExt(m_NUWSub(m_Value(B), m_Specific(A)))))) return new ZExtInst(B, LHS->getType()); + // Fold the following: + // X = select A, T_C, F_C + // Z = zext A or Z = sext A + // W = add X, Z + // => + // select A, T_C + 1, F_C (for Z = zext A) + // select A, T_C - 1, F_C (for Z = sext A) + // Take into account the negation as well. + Value *CondVal; + Constant *TrueC, *FalseC; + if ((match(RHS, m_ZExtOrSExt(m_Value(A))) && + A->getType()->getScalarSizeInBits() == 1) && + match(LHS, m_Select(m_Value(CondVal), m_ImmConstant(TrueC), + m_ImmConstant(FalseC)))) { + if (CondVal == A) { + if (isa(RHS)) + return SelectInst::Create(CondVal, InstCombiner::AddOne(TrueC), FalseC); + return SelectInst::Create(CondVal, InstCombiner::SubOne(TrueC), FalseC); + } + + if (match(A, m_Not(m_Specific(CondVal)))) { + if (isa(RHS)) + return SelectInst::Create(CondVal, TrueC, InstCombiner::AddOne(FalseC)); + return SelectInst::Create(CondVal, TrueC, InstCombiner::SubOne(FalseC)); + } + } + // A+B --> A|B iff A and B have no bits set in common. if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT)) return BinaryOperator::CreateOr(LHS, RHS); Index: llvm/test/Transforms/InstCombine/add.ll =================================================================== --- llvm/test/Transforms/InstCombine/add.ll +++ llvm/test/Transforms/InstCombine/add.ll @@ -3019,4 +3019,50 @@ ret <2 x i32> %c } +define i64 @add_select_zext(i1 %c) { +; CHECK-LABEL: @add_select_zext( +; CHECK-NEXT: [[ADD:%.*]] = select i1 [[C:%.*]], i64 65, i64 1 +; CHECK-NEXT: ret i64 [[ADD]] +; + %sel = select i1 %c, i64 64, i64 1 + %ext = zext i1 %c to i64 + %add = add i64 %sel, %ext + ret i64 %add +} + +define i64 @add_select_sext(i1 %c) { +; CHECK-LABEL: @add_select_sext( +; CHECK-NEXT: [[ADD:%.*]] = select i1 [[C:%.*]], i64 63, i64 1 +; CHECK-NEXT: ret i64 [[ADD]] +; + %sel = select i1 %c, i64 64, i64 1 + %ext = sext i1 %c to i64 + %add = add i64 %sel, %ext + ret i64 %add +} + +define i64 @add_select_not_zext(i1 %c) { +; CHECK-LABEL: @add_select_not_zext( +; CHECK-NEXT: [[ADD:%.*]] = select i1 [[C:%.*]], i64 64, i64 2 +; CHECK-NEXT: ret i64 [[ADD]] +; + %sel = select i1 %c, i64 64, i64 1 + %not.c = xor i1 %c, true + %ext = zext i1 %not.c to i64 + %add = add i64 %sel, %ext + ret i64 %add +} + +define i64 @add_select_not_sext(i1 %c) { +; CHECK-LABEL: @add_select_not_sext( +; CHECK-NEXT: [[ADD:%.*]] = select i1 [[C:%.*]], i64 64, i64 0 +; CHECK-NEXT: ret i64 [[ADD]] +; + %sel = select i1 %c, i64 64, i64 1 + %not.c = xor i1 %c, true + %ext = sext i1 %not.c to i64 + %add = add i64 %sel, %ext + ret i64 %add +} + declare void @llvm.assume(i1)