Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,10 @@ class VPBuilder {
const VPIRFlags &Flags = {},
const VPIRMetadata &MD = {},
DebugLoc DL = DebugLoc::getUnknown(),
const Twine &Name = "") {
const Twine &Name = "",
Type *ResultTy = nullptr) {
VPInstruction *NewVPInst = tryInsertInstruction(
new VPInstruction(Opcode, Operands, Flags, MD, DL, Name));
new VPInstruction(Opcode, Operands, Flags, MD, DL, Name, ResultTy));
NewVPInst->setUnderlyingValue(Inst);
return NewVPInst;
}
Expand All @@ -226,15 +227,19 @@ class VPBuilder {
VPInstruction *createFirstActiveLane(ArrayRef<VPValue *> Masks,
DebugLoc DL = DebugLoc::getUnknown(),
const Twine &Name = "") {
VPlan &Plan = getPlan();
Type *IndexTy = Plan.getDataLayout().getIndexType(Plan.getContext(), 0);
return tryInsertInstruction(new VPInstruction(
VPInstruction::FirstActiveLane, Masks, {}, {}, DL, Name));
VPInstruction::FirstActiveLane, Masks, {}, {}, DL, Name, IndexTy));
}

VPInstruction *createLastActiveLane(ArrayRef<VPValue *> Masks,
DebugLoc DL = DebugLoc::getUnknown(),
const Twine &Name = "") {
return tryInsertInstruction(new VPInstruction(VPInstruction::LastActiveLane,
Masks, {}, {}, DL, Name));
VPlan &Plan = getPlan();
Type *IndexTy = Plan.getDataLayout().getIndexType(Plan.getContext(), 0);
return tryInsertInstruction(new VPInstruction(
VPInstruction::LastActiveLane, Masks, {}, {}, DL, Name, IndexTy));
}

VPInstruction *createOverflowingOp(
Expand Down Expand Up @@ -359,8 +364,10 @@ class VPBuilder {

VPPhi *createScalarPhi(ArrayRef<VPValue *> IncomingValues,
DebugLoc DL = DebugLoc::getUnknown(),
const Twine &Name = "", const VPIRFlags &Flags = {}) {
return tryInsertInstruction(new VPPhi(IncomingValues, Flags, DL, Name));
const Twine &Name = "", const VPIRFlags &Flags = {},
Type *ResultTy = nullptr) {
return tryInsertInstruction(
new VPPhi(IncomingValues, Flags, DL, Name, ResultTy));
}

VPWidenPHIRecipe *createWidenPhi(ArrayRef<VPValue *> IncomingValues,
Expand Down
30 changes: 18 additions & 12 deletions llvm/lib/Transforms/Vectorize/VPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,10 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
/// types.
LLVM_ABI Type *getScalarTypeOrInfer(VPValue *V);

/// Compute the scalar result type for an IR \p Opcode given \p Operands.
LLVM_ABI Type *computeScalarTypeForInstruction(unsigned Opcode,
ArrayRef<VPValue *> Operands);

/// VPSingleDefRecipe is a base class for recipes that model a sequence of one
/// or more output IR that define a single result VPValue. Note that
/// VPSingleDefRecipe must inherit from VPRecipeBase before VPSingleDefValue.
Expand Down Expand Up @@ -1393,15 +1397,19 @@ class LLVM_ABI_FOR_TEST VPInstruction : public VPRecipeWithIRFlags,
public:
VPInstruction(unsigned Opcode, ArrayRef<VPValue *> Operands,
const VPIRFlags &Flags = {}, const VPIRMetadata &MD = {},
DebugLoc DL = DebugLoc::getUnknown(), const Twine &Name = "");
DebugLoc DL = DebugLoc::getUnknown(), const Twine &Name = "",
Type *ResultTy = nullptr);

VP_CLASSOF_IMPL(VPRecipeBase::VPInstructionSC)

VPInstruction *clone() override { return cloneWithOperands(operands()); }
VPInstruction *clone() override {
return cloneWithOperands(operands(), getScalarType());
}

VPInstruction *cloneWithOperands(ArrayRef<VPValue *> NewOperands) {
VPInstruction *cloneWithOperands(ArrayRef<VPValue *> NewOperands,
Type *ResultTy = nullptr) {
auto *New = new VPInstruction(Opcode, NewOperands, *this, *this,
getDebugLoc(), Name);
getDebugLoc(), Name, ResultTy);
if (getUnderlyingValue())
New->setUnderlyingValue(getUnderlyingInstr());
return New;
Expand Down Expand Up @@ -1521,18 +1529,15 @@ class LLVM_ABI_FOR_TEST VPInstruction : public VPRecipeWithIRFlags,
/// directly determine the result type. Note that there is no separate recipe ID
/// for VPInstructionWithType; it shares the same ID as VPInstruction and is
/// distinguished purely by the opcode.
/// TODO: Merge with VPInstruction, now that VPRecipeValue provides the type.
class VPInstructionWithType : public VPInstruction {
/// Scalar result type produced by the recipe.
Type *ResultTy;

public:
VPInstructionWithType(unsigned Opcode, ArrayRef<VPValue *> Operands,
Type *ResultTy, const VPIRFlags &Flags = {},
const VPIRMetadata &Metadata = {},
DebugLoc DL = DebugLoc::getUnknown(),
const Twine &Name = "")
: VPInstruction(Opcode, Operands, Flags, Metadata, DL, Name),
ResultTy(ResultTy) {}
: VPInstruction(Opcode, Operands, Flags, Metadata, DL, Name, ResultTy) {}

static inline bool classof(const VPRecipeBase *R) {
// VPInstructionWithType are VPInstructions with specific opcodes requiring
Expand Down Expand Up @@ -1575,7 +1580,7 @@ class VPInstructionWithType : public VPInstruction {
return 0;
}

Type *getResultType() const { return ResultTy; }
Type *getResultType() const { return getScalarType(); }

protected:
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Expand Down Expand Up @@ -1652,8 +1657,9 @@ class VPPhiAccessors {

struct LLVM_ABI_FOR_TEST VPPhi : public VPInstruction, public VPPhiAccessors {
VPPhi(ArrayRef<VPValue *> Operands, const VPIRFlags &Flags, DebugLoc DL,
const Twine &Name = "")
: VPInstruction(Instruction::PHI, Operands, Flags, {}, DL, Name) {}
const Twine &Name = "", Type *ResultTy = nullptr)
: VPInstruction(Instruction::PHI, Operands, Flags, {}, DL, Name,
ResultTy) {}

static inline bool classof(const VPUser *U) {
auto *VPI = dyn_cast<VPInstruction>(U);
Expand Down
124 changes: 3 additions & 121 deletions llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,122 +35,6 @@ Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPBlendRecipe *R) {
return ResTy;
}

Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPInstruction *R) {
// Set the result type from the first operand, check if the types for all
// other operands match and cache them.
auto SetResultTyFromOp = [this, R]() {
Type *ResTy = inferScalarType(R->getOperand(0));
unsigned NumOperands = R->getNumOperandsWithoutMask();
for (unsigned Op = 1; Op != NumOperands; ++Op) {
VPValue *OtherV = R->getOperand(Op);
assert(inferScalarType(OtherV) == ResTy &&
"different types inferred for different operands");
CachedTypes[OtherV] = ResTy;
}
return ResTy;
};

unsigned Opcode = R->getOpcode();
if (Instruction::isBinaryOp(Opcode) || Instruction::isUnaryOp(Opcode))
return SetResultTyFromOp();

switch (Opcode) {
case Instruction::PHI:
for (VPValue *Op : R->operands()) {
if (auto *VIR = dyn_cast<VPIRValue>(Op))
return VIR->getType();
if (auto *Ty = CachedTypes.lookup(Op))
return Ty;
}
LLVM_FALLTHROUGH;
case Instruction::ExtractElement:
case Instruction::InsertElement:
case Instruction::Freeze:
case VPInstruction::Broadcast:
case VPInstruction::ComputeReductionResult:
case VPInstruction::ExitingIVValue:
case VPInstruction::ExtractLastLane:
case VPInstruction::ExtractPenultimateElement:
case VPInstruction::ExtractLastPart:
case VPInstruction::ExtractLastActive:
case VPInstruction::PtrAdd:
case VPInstruction::WidePtrAdd:
case VPInstruction::ReductionStartVector:
case VPInstruction::ResumeForEpilogue:
case VPInstruction::Reverse:
return inferScalarType(R->getOperand(0));
case Instruction::Select: {
Type *ResTy = inferScalarType(R->getOperand(1));
VPValue *OtherV = R->getOperand(2);
assert(inferScalarType(OtherV) == ResTy &&
"different types inferred for different operands");
CachedTypes[OtherV] = ResTy;
return ResTy;
}
case Instruction::ICmp:
case Instruction::FCmp:
case VPInstruction::ActiveLaneMask:
assert(inferScalarType(R->getOperand(0)) ==
inferScalarType(R->getOperand(1)) &&
"different types inferred for different operands");
return IntegerType::get(Ctx, 1);
case VPInstruction::ExplicitVectorLength:
return Type::getIntNTy(Ctx, 32);
case VPInstruction::FirstOrderRecurrenceSplice:
case VPInstruction::Not:
case VPInstruction::CalculateTripCountMinusVF:
case VPInstruction::CanonicalIVIncrementForPart:
case VPInstruction::AnyOf:
case VPInstruction::BuildStructVector:
case VPInstruction::BuildVector:
case VPInstruction::Unpack:
return SetResultTyFromOp();
case VPInstruction::ExtractLane:
return inferScalarType(R->getOperand(1));
case VPInstruction::FirstActiveLane:
case VPInstruction::LastActiveLane:
// Assume that the maximum possible number of elements in a vector fits
// within the index type for the default address space.
return DL.getIndexType(Ctx, 0);
case VPInstruction::LogicalAnd:
case VPInstruction::LogicalOr:
assert(inferScalarType(R->getOperand(0))->isIntegerTy(1) &&
inferScalarType(R->getOperand(1))->isIntegerTy(1) &&
"LogicalAnd/Or operands should be bool");
return IntegerType::get(Ctx, 1);
case VPInstruction::MaskedCond:
assert(inferScalarType(R->getOperand(0))->isIntegerTy(1));
return IntegerType::get(Ctx, 1);
case VPInstruction::BranchOnCond:
case VPInstruction::BranchOnTwoConds:
case VPInstruction::BranchOnCount:
case Instruction::Store:
case Instruction::Switch:
return Type::getVoidTy(Ctx);
case Instruction::Load:
return cast<LoadInst>(R->getUnderlyingValue())->getType();
case Instruction::Alloca:
return cast<AllocaInst>(R->getUnderlyingValue())->getType();
case Instruction::Call: {
unsigned CallIdx = R->getNumOperandsWithoutMask() - 1;
return cast<Function>(R->getOperand(CallIdx)->getLiveInIRValue())
->getReturnType();
}
case Instruction::GetElementPtr:
return inferScalarType(R->getOperand(0));
case Instruction::ExtractValue:
return cast<ExtractValueInst>(R->getUnderlyingValue())->getType();
default:
break;
}
// Type inference not implemented for opcode.
LLVM_DEBUG({
dbgs() << "LV: Found unhandled opcode for: ";
R->getVPSingleValue()->dump();
});
llvm_unreachable("Unhandled opcode!");
}

Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenRecipe *R) {
unsigned Opcode = R->getOpcode();
if (Instruction::isBinaryOp(Opcode) || Instruction::isShift(Opcode) ||
Expand Down Expand Up @@ -260,18 +144,16 @@ Type *VPTypeAnalysis::inferScalarType(const VPValue *V) {
VPScalarIVStepsRecipe, VPWidenCanonicalIVRecipe, VPWidenCastRecipe,
VPWidenIntrinsicRecipe, VPWidenGEPRecipe, VPVectorPointerRecipe,
VPVectorEndPointerRecipe, VPWidenCallRecipe, VPWidenLoadRecipe,
VPWidenLoadEVLRecipe, VPDerivedIVRecipe, VPHeaderPHIRecipe>(V)) {
VPWidenLoadEVLRecipe, VPDerivedIVRecipe, VPHeaderPHIRecipe,
VPInstruction>(V)) {
Type *Ty = V->getScalarType();
assert(Ty && "Scalar type must be set by recipe construction");
return Ty;
}

Type *ResultTy =
TypeSwitch<const VPRecipeBase *, Type *>(V->getDefiningRecipe())
// VPInstructionWithType must be handled before VPInstruction.
.Case<VPInstructionWithType>(
[](const auto *R) { return R->getResultType(); })
.Case<VPBlendRecipe, VPInstruction, VPWidenRecipe, VPReplicateRecipe>(
.Case<VPBlendRecipe, VPWidenRecipe, VPReplicateRecipe>(
[this](const auto *R) { return inferScalarTypeForRecipe(R); })
.Case([this](const VPReductionRecipe *R) {
return inferScalarType(R->getChainOp());
Expand Down
2 changes: 0 additions & 2 deletions llvm/lib/Transforms/Vectorize/VPlanAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ namespace llvm {
class LLVMContext;
class VPValue;
class VPBlendRecipe;
class VPInstruction;
class VPWidenRecipe;
class VPReplicateRecipe;
class VPRecipeBase;
Expand All @@ -48,7 +47,6 @@ class VPTypeAnalysis {
const DataLayout &DL;

Type *inferScalarTypeForRecipe(const VPBlendRecipe *R);
Type *inferScalarTypeForRecipe(const VPInstruction *R);
Type *inferScalarTypeForRecipe(const VPWidenRecipe *R);
Type *inferScalarTypeForRecipe(const VPReplicateRecipe *R);

Expand Down
10 changes: 5 additions & 5 deletions llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,8 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB,
// Phi node's operands may not have been visited at this point. We create
// an empty VPInstruction that we will fix once the whole plain CFG has
// been built.
NewR =
VPIRBuilder.createScalarPhi({}, Phi->getDebugLoc(), "vec.phi", *Phi);
NewR = VPIRBuilder.createScalarPhi({}, Phi->getDebugLoc(), "vec.phi",
*Phi, Phi->getType());
NewR->setUnderlyingValue(Phi);
if (isHeaderBB(Phi->getParent(), LI->getLoopFor(Phi->getParent()))) {
// Header phis need to be fixed after the VPBB for the latch has been
Expand Down Expand Up @@ -275,9 +275,9 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB,
} else {
// Build VPInstruction for any arbitrary Instruction without specific
// representation in VPlan.
NewR =
VPIRBuilder.createNaryOp(Inst->getOpcode(), VPOperands, Inst,
VPIRFlags(*Inst), MD, Inst->getDebugLoc());
NewR = VPIRBuilder.createNaryOp(
Inst->getOpcode(), VPOperands, Inst, VPIRFlags(*Inst), MD,
Inst->getDebugLoc(), "", Inst->getType());
}
}

Expand Down
Loading