Index: lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1067,10 +1067,21 @@ if (SimplifyDemandedInstructionBits(I)) return &I; - // zext(bool) + C -> bool ? C + 1 : C - if (ZExtInst *ZI = dyn_cast(LHS)) - if (ZI->getSrcTy()->isIntegerTy(1)) - return SelectInst::Create(ZI->getOperand(0), AddOne(CI), CI); + // add (zext (icmp Pred X, Y)), -1 --> sext (icmp Pred' X, Y) + // In general, we prefer to have zext rather than sext for better + // value-tracking potential, but in this case, we get to eliminate an add. + Instruction *ZextOp; + ICmpInst::Predicate Pred; + Value *X, *Y; + if (CI->getSExtValue() == -1 && match(LHS, m_ZExt(m_Instruction(ZextOp))) && + match(ZextOp, m_OneUse(m_ICmp(Pred, m_Value(X), m_Value(Y))))) { + // We have this pattern: if the compare is true, return 0; + // if the compare is false, return -1. + // Transform it to: if the inverse compare is true, return -1; + // if the inverse compare is false, return 0. + auto *Cmp = Builder->CreateICmp(CmpInst::getInversePredicate(Pred), X, Y); + return CastInst::Create(Instruction::SExt, Cmp, I.getType()); + } Value *XorLHS = nullptr; ConstantInt *XorRHS = nullptr; if (match(LHS, m_Xor(m_Value(XorLHS), m_ConstantInt(XorRHS)))) { Index: test/Transforms/InstCombine/icmp-div-constant.ll =================================================================== --- test/Transforms/InstCombine/icmp-div-constant.ll +++ test/Transforms/InstCombine/icmp-div-constant.ll @@ -12,8 +12,8 @@ ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 %a, 0 ; CHECK-NEXT: br i1 [[TOBOOL]], label %then, label %exit ; CHECK: then: -; CHECK-NEXT: [[NOT_CMP:%.*]] = icmp eq i16 %c, 0 -; CHECK-NEXT: [[PHITMP1:%.*]] = sext i1 [[NOT_CMP]] to i32 +; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i16 %c, 0 +; CHECK-NEXT: [[PHITMP1:%.*]] = sext i1 [[TMP0]] to i32 ; CHECK-NEXT: br label %exit ; CHECK: exit: ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, %entry ], [ [[PHITMP1]], %then ] @@ -68,8 +68,8 @@ ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 %a, 0 ; CHECK-NEXT: br i1 [[TOBOOL]], label %then, label %exit ; CHECK: then: -; CHECK-NEXT: [[NOT_CMP:%.*]] = icmp eq i16 %c, 0 -; CHECK-NEXT: [[PHITMP1:%.*]] = sext i1 [[NOT_CMP]] to i32 +; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i16 %c, 0 +; CHECK-NEXT: [[PHITMP1:%.*]] = sext i1 [[TMP0]] to i32 ; CHECK-NEXT: br label %exit ; CHECK: exit: ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, %entry ], [ [[PHITMP1]], %then ] Index: test/Transforms/InstCombine/zext-bool-add-sub.ll =================================================================== --- test/Transforms/InstCombine/zext-bool-add-sub.ll +++ test/Transforms/InstCombine/zext-bool-add-sub.ll @@ -5,8 +5,9 @@ define i32 @a(i1 zeroext %x, i1 zeroext %y) { ; CHECK-LABEL: @a( +; CHECK-NEXT: [[CONV:%.*]] = zext i1 %x to i32 ; CHECK-NEXT: [[CONV3_NEG:%.*]] = sext i1 %y to i32 -; CHECK-NEXT: [[SUB:%.*]] = select i1 %x, i32 2, i32 1 +; CHECK-NEXT: [[SUB:%.*]] = add nuw nsw i32 [[CONV]], 1 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[SUB]], [[CONV3_NEG]] ; CHECK-NEXT: ret i32 [[ADD]] ; @@ -47,8 +48,8 @@ define i32 @PR30273_three_bools(i1 %x, i1 %y, i1 %z) { ; CHECK-LABEL: @PR30273_three_bools( ; CHECK-NEXT: [[FROMBOOL:%.*]] = zext i1 %x to i32 -; CHECK-NEXT: [[ADD1:%.*]] = select i1 %x, i32 2, i32 1 -; CHECK-NEXT: [[SEL1:%.*]] = select i1 %y, i32 [[ADD1]], i32 [[FROMBOOL]] +; CHECK-NEXT: [[ADD1:%.*]] = zext i1 %y to i32 +; CHECK-NEXT: [[SEL1:%.*]] = add nuw nsw i32 [[FROMBOOL]], [[ADD1]] ; CHECK-NEXT: [[ADD2:%.*]] = zext i1 %z to i32 ; CHECK-NEXT: [[SEL2:%.*]] = add nuw nsw i32 [[SEL1]], [[ADD2]] ; CHECK-NEXT: ret i32 [[SEL2]]