#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/InstructionCost.h"
namespace llvm {
extern cl::opt<unsigned> SCEVCheapExpansionBudget;
return true; // by always claiming to be high-cost.
SmallVector<SCEVOperand, 8> Worklist;
SmallPtrSet<const SCEV *, 8> Processed;
- int BudgetRemaining = Budget * TargetTransformInfo::TCC_Basic;
+ InstructionCost Cost = 0;
+ unsigned ScaledBudget = Budget * TargetTransformInfo::TCC_Basic;
Worklist.emplace_back(-1, -1, Expr);
while (!Worklist.empty()) {
const SCEVOperand WorkItem = Worklist.pop_back_val();
- if (isHighCostExpansionHelper(WorkItem, L, *At, BudgetRemaining,
- *TTI, Processed, Worklist))
+ if (isHighCostExpansionHelper(WorkItem, L, *At, Cost, ScaledBudget, *TTI,
+ Processed, Worklist))
return true;
}
- assert(BudgetRemaining >= 0 && "Should have returned from inner loop.");
+ assert(Cost <= ScaledBudget && "Should have returned from inner loop.");
return false;
}
Value *expandCodeForImpl(const SCEV *SH, Type *Ty, Instruction *I, bool Root);
/// Recursive helper function for isHighCostExpansion.
- bool isHighCostExpansionHelper(
- const SCEVOperand &WorkItem, Loop *L, const Instruction &At,
- int &BudgetRemaining, const TargetTransformInfo &TTI,
- SmallPtrSetImpl<const SCEV *> &Processed,
- SmallVectorImpl<SCEVOperand> &Worklist);
+ bool isHighCostExpansionHelper(const SCEVOperand &WorkItem, Loop *L,
+ const Instruction &At, InstructionCost &Cost,
+ unsigned Budget,
+ const TargetTransformInfo &TTI,
+ SmallPtrSetImpl<const SCEV *> &Processed,
+ SmallVectorImpl<SCEVOperand> &Worklist);
/// Insert the specified binary operator, doing a small amount of work to
/// avoid inserting an obviously redundant operation, and hoisting to an
return None;
}
-template<typename T> static int costAndCollectOperands(
+template<typename T> static InstructionCost costAndCollectOperands(
const SCEVOperand &WorkItem, const TargetTransformInfo &TTI,
TargetTransformInfo::TargetCostKind CostKind,
SmallVectorImpl<SCEVOperand> &Worklist) {
const T *S = cast<T>(WorkItem.S);
- int Cost = 0;
+ InstructionCost Cost = 0;
// Object to help map SCEV operands to expanded IR instructions.
struct OperationIndices {
OperationIndices(unsigned Opc, size_t min, size_t max) :
// we know what the generated user(s) will be.
SmallVector<OperationIndices, 2> Operations;
- auto CastCost = [&](unsigned Opcode) {
+ auto CastCost = [&](unsigned Opcode) -> InstructionCost {
Operations.emplace_back(Opcode, 0, 0);
return TTI.getCastInstrCost(Opcode, S->getType(),
S->getOperand(0)->getType(),
};
auto ArithCost = [&](unsigned Opcode, unsigned NumRequired,
- unsigned MinIdx = 0, unsigned MaxIdx = 1) {
+ unsigned MinIdx = 0,
+ unsigned MaxIdx = 1) -> InstructionCost {
Operations.emplace_back(Opcode, MinIdx, MaxIdx);
return NumRequired *
TTI.getArithmeticInstrCost(Opcode, S->getType(), CostKind);
};
- auto CmpSelCost = [&](unsigned Opcode, unsigned NumRequired,
- unsigned MinIdx, unsigned MaxIdx) {
+ auto CmpSelCost = [&](unsigned Opcode, unsigned NumRequired, unsigned MinIdx,
+ unsigned MaxIdx) -> InstructionCost {
Operations.emplace_back(Opcode, MinIdx, MaxIdx);
Type *OpType = S->getOperand(0)->getType();
return NumRequired * TTI.getCmpSelInstrCost(
// Much like with normal add expr, the polynominal will require
// one less addition than the number of it's terms.
- int AddCost = ArithCost(Instruction::Add, NumTerms - 1,
- /*MinIdx*/1, /*MaxIdx*/1);
+ InstructionCost AddCost = ArithCost(Instruction::Add, NumTerms - 1,
+ /*MinIdx*/ 1, /*MaxIdx*/ 1);
// Here, *each* one of those will require a multiplication.
- int MulCost = ArithCost(Instruction::Mul, NumNonZeroDegreeNonOneTerms);
+ InstructionCost MulCost =
+ ArithCost(Instruction::Mul, NumNonZeroDegreeNonOneTerms);
Cost = AddCost + MulCost;
// What is the degree of this polynominal?
bool SCEVExpander::isHighCostExpansionHelper(
const SCEVOperand &WorkItem, Loop *L, const Instruction &At,
- int &BudgetRemaining, const TargetTransformInfo &TTI,
+ InstructionCost &Cost, unsigned Budget, const TargetTransformInfo &TTI,
SmallPtrSetImpl<const SCEV *> &Processed,
SmallVectorImpl<SCEVOperand> &Worklist) {
- if (BudgetRemaining < 0)
+ if (Cost > Budget)
return true; // Already run out of budget, give up.
const SCEV *S = WorkItem.S;
return 0;
const APInt &Imm = cast<SCEVConstant>(S)->getAPInt();
Type *Ty = S->getType();
- BudgetRemaining -= TTI.getIntImmCostInst(
+ Cost += TTI.getIntImmCostInst(
WorkItem.ParentOpcode, WorkItem.OperandIdx, Imm, Ty, CostKind);
- return BudgetRemaining < 0;
+ return Cost > Budget;
}
case scTruncate:
case scPtrToInt:
case scZeroExtend:
case scSignExtend: {
- int Cost =
+ Cost +=
costAndCollectOperands<SCEVCastExpr>(WorkItem, TTI, CostKind, Worklist);
- BudgetRemaining -= Cost;
return false; // Will answer upon next entry into this function.
}
case scUDivExpr: {
SE.getAddExpr(S, SE.getConstant(S->getType(), 1)), &At, L))
return false; // Consider it to be free.
- int Cost =
+ Cost +=
costAndCollectOperands<SCEVUDivExpr>(WorkItem, TTI, CostKind, Worklist);
- // Need to count the cost of this UDiv.
- BudgetRemaining -= Cost;
return false; // Will answer upon next entry into this function.
}
case scAddExpr:
"Nary expr should have more than 1 operand.");
// The simple nary expr will require one less op (or pair of ops)
// than the number of it's terms.
- int Cost =
+ Cost +=
costAndCollectOperands<SCEVNAryExpr>(WorkItem, TTI, CostKind, Worklist);
- BudgetRemaining -= Cost;
- return BudgetRemaining < 0;
+ return Cost > Budget;
}
case scAddRecExpr: {
assert(cast<SCEVAddRecExpr>(S)->getNumOperands() >= 2 &&
"Polynomial should be at least linear");
- BudgetRemaining -= costAndCollectOperands<SCEVAddRecExpr>(
+ Cost += costAndCollectOperands<SCEVAddRecExpr>(
WorkItem, TTI, CostKind, Worklist);
- return BudgetRemaining < 0;
+ return Cost > Budget;
}
}
llvm_unreachable("Unknown SCEV kind!");