/// Return information about the vector formed for the specified index
/// of a vector of (the same) instruction.
+ /// \param EnableFP - If true, check for float constants.
TargetTransformInfo::OperandValueInfo
- getOperandInfo(ArrayRef<Value *> VL, unsigned OpIdx);
+ getOperandInfo(ArrayRef<Value *> VL, unsigned OpIdx, bool EnableFP);
/// \returns the cost of the vectorizable entry.
InstructionCost getEntryCost(const TreeEntry *E,
return I->getOpcode() == AltOp->getOpcode();
}
-TTI::OperandValueInfo BoUpSLP::getOperandInfo(ArrayRef<Value *> VL, unsigned OpIdx) {
-
+TTI::OperandValueInfo BoUpSLP::getOperandInfo(ArrayRef<Value *> VL,
+ unsigned OpIdx, bool EnableFP) {
TTI::OperandValueKind VK = TTI::OK_UniformConstantValue;
TTI::OperandValueProperties VP = TTI::OP_PowerOf2;
+ // If all float operands are constants then set the operand kind to
+ // OK_NonUniformConstantValue. Otherwise, return OK_AnyValue.
+ const auto *I0 = cast<Instruction>(VL.front());
+ if (I0->getOperand(OpIdx)->getType()->isFloatingPointTy()) {
+ if (!EnableFP || any_of(VL, [OpIdx, I0](Value *V) {
+ const auto *Inst = cast<Instruction>(V);
+ assert(Inst->getOpcode() == I0->getOpcode() &&
+ "Expected same opcode");
+ return !isConstant(Inst->getOperand(OpIdx));
+ }))
+ return {TTI::OK_AnyValue, TTI::OP_None};
+ return {TTI::OK_NonUniformConstantValue, TTI::OP_None};
+ }
+
// If all operands are exactly the same ConstantInt then set the
// operand kind to OK_UniformConstantValue.
// If instead not all operands are constants, then set the operand kind
// to OK_AnyValue. If all operands are constants but not the same,
// then set the operand kind to OK_NonUniformConstantValue.
ConstantInt *CInt0 = nullptr;
- for (unsigned i = 0, e = VL.size(); i < e; ++i) {
- const Instruction *I = cast<Instruction>(VL[i]);
- assert(I->getOpcode() == cast<Instruction>(VL[0])->getOpcode());
- ConstantInt *CInt = dyn_cast<ConstantInt>(I->getOperand(OpIdx));
+ for (Value *V : VL) {
+ const auto *Inst = cast<Instruction>(V);
+ assert(Inst->getOpcode() == cast<Instruction>(VL[0])->getOpcode() &&
+ "Expected same opcode");
+ auto *CInt = dyn_cast<ConstantInt>(Inst->getOperand(OpIdx));
if (!CInt) {
VK = TTI::OK_AnyValue;
VP = TTI::OP_None;
break;
}
- if (VP == TTI::OP_PowerOf2 &&
- !CInt->getValue().isPowerOf2())
+ if (VP == TTI::OP_PowerOf2 && !CInt->getValue().isPowerOf2())
VP = TTI::OP_None;
- if (i == 0) {
+ if (!CInt0) {
CInt0 = CInt;
continue;
}
// Certain instructions can be cheaper to vectorize if they have a
// constant second vector operand.
const unsigned OpIdx = isa<BinaryOperator>(VL0) ? 1 : 0;
- auto Op2Info = getOperandInfo(VL, OpIdx);
+ // TODO: impact of enabling the analysis there is yet to be determined
+ auto Op2Info = getOperandInfo(VL, OpIdx, /*EnableFP=*/false);
SmallVector<const Value *, 4> Operands(VL0->operand_values());
InstructionCost ScalarEltCost =
auto *SI =
cast<StoreInst>(IsReorder ? VL[E->ReorderIndices.front()] : VL0);
Align Alignment = SI->getAlign();
- TTI::OperandValueInfo OpInfo = TTI::getOperandInfo(SI->getOperand(0));
+ TTI::OperandValueInfo OpInfo = getOperandInfo(VL, 0, /*EnableFP=*/true);
InstructionCost ScalarEltCost = TTI->getMemoryOpCost(
Instruction::Store, ScalarTy, Alignment, 0, CostKind, OpInfo, VL0);
InstructionCost ScalarStCost = VecTy->getNumElements() * ScalarEltCost;
TTI::OperandValueKind OpVK = TTI::OK_AnyValue;
- if (all_of(E->Scalars,
- [](Value *V) {
- return isConstant(cast<Instruction>(V)->getOperand(0));
- }) &&
- any_of(E->Scalars, [](Value *V) {
- Value *Op = cast<Instruction>(V)->getOperand(0);
- return !isa<UndefValue>(Op) && !cast<Constant>(Op)->isZeroValue();
- }))
+ if (OpInfo.isConstant())
OpVK = TTI::OK_NonUniformConstantValue;
InstructionCost VecStCost = TTI->getMemoryOpCost(
Instruction::Store, VecTy, Alignment, 0, CostKind,