Index: llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp =================================================================== --- llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp +++ llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp @@ -1815,6 +1815,33 @@ } Value *SCEVExpander::visitUMinExpr(const SCEVUMinExpr *S) { + if (llvm::any_of(S->operands(), [](const SCEV* S) { + return S->getType()->isIntegerTy() && S->isOne(); + })) { + SmallVector Ops; + for (const SCEV *Op : S->operands()) { + if (S->getType()->isIntegerTy() && S->isOne()) + continue; + Type *Ty = Op->getType(); + if (!Ty->isIntegerTy()) { + Ty = SE.getEffectiveSCEVType(Ty); + } + Value *V = expandCodeForImpl(Op, Ty, false); + Ops.emplace_back(V); + } + assert(!Ops.empty() && "should have constant folded?"); + Type *Ty = Ops[0]->getType(); + Value *Reduce = Builder.CreateAnd(Ops); + Value *Zero = ConstantInt::get(Ty, 0); + Value *Cmp = Builder.CreateICmpNE(Reduce, Zero); + Value *Res = Builder.CreateZExt(Cmp, Ty); + // In the case of mixed integer and pointer types, cast the + // final result back to the pointer type. + if (Res->getType() != S->getType()) + Res = InsertNoopCastOfTo(Res, S->getType()); + return Res; + } + Value *LHS = expand(S->getOperand(S->getNumOperands() - 1)); Type *Ty = LHS->getType(); for (int i = S->getNumOperands() - 2; i >= 0; --i) { @@ -2308,10 +2335,22 @@ // see SCEVExpander::visitMulExpr(), ExpandOpBinPowN(). Cost = ArithCost(Instruction::Mul, S->getNumOperands() - 1); break; + case scUMinExpr: + // umin(x1, x2, ..., xn, 1) is zero if any x1..xn is zero, and one + // otherwise. This is equivalent to zext(icmp ne and_reduce(x1..xn), 0). + if (llvm::any_of(S->operands(), [](const SCEV *S) { + return S->getType()->isIntegerTy() && S->isOne(); + })) { + if (S->getNumOperands() > 2) + Cost = ArithCost(Instruction::And, S->getNumOperands() - 2); + Cost += CmpSelCost(Instruction::ICmp, 2, 0, 1); + Cost = CastCost(Instruction::ZExt); + break; + } + LLVM_FALLTHROUGH; case scSMaxExpr: case scUMaxExpr: - case scSMinExpr: - case scUMinExpr: { + case scSMinExpr: { // FIXME: should this ask the cost for Intrinsic's? Cost += CmpSelCost(Instruction::ICmp, S->getNumOperands() - 1, 0, 1); Cost += CmpSelCost(Instruction::Select, S->getNumOperands() - 1, 0, 2);