-
Notifications
You must be signed in to change notification settings - Fork 11.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[VPlan] Add initial anlysis to infer scalar type of VPValues. #69013
Changes from 2 commits
22b23c7
30a8968
58b145e
d89b7d8
4ed3b6d
529805c
a75c562
1483f63
79bcce9
532d75e
5bbd764
74525ad
722cc3d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -1167,6 +1167,8 @@ class VPWidenRecipe : public VPRecipeWithIRFlags, public VPValue { | |||||
/// Produce widened copies of all Ingredients. | ||||||
void execute(VPTransformState &State) override; | ||||||
|
||||||
unsigned getOpcode() const { return Opcode; } | ||||||
|
||||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | ||||||
/// Print the recipe. | ||||||
void print(raw_ostream &O, const Twine &Indent, | ||||||
|
@@ -1458,7 +1460,7 @@ class VPWidenIntOrFpInductionRecipe : public VPHeaderPHIRecipe { | |||||
bool isCanonical() const; | ||||||
|
||||||
/// Returns the scalar type of the induction. | ||||||
const Type *getScalarType() const { | ||||||
Type *getScalarType() const { | ||||||
return Trunc ? Trunc->getType() : IV->getType(); | ||||||
} | ||||||
}; | ||||||
|
@@ -2080,7 +2082,7 @@ class VPCanonicalIVPHIRecipe : public VPHeaderPHIRecipe { | |||||
#endif | ||||||
|
||||||
/// Returns the scalar type of the induction. | ||||||
const Type *getScalarType() const { | ||||||
Type *getScalarType() const { | ||||||
return getOperand(0)->getLiveInIRValue()->getType(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
while we're here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adjusted, thanks |
||||||
} | ||||||
|
||||||
|
@@ -2149,7 +2151,7 @@ class VPWidenCanonicalIVRecipe : public VPRecipeBase, public VPValue { | |||||
#endif | ||||||
|
||||||
/// Returns the scalar type of the induction. | ||||||
const Type *getScalarType() const { | ||||||
Type *getScalarType() const { | ||||||
return cast<VPCanonicalIVPHIRecipe>(getOperand(0)->getDefiningRecipe()) | ||||||
->getScalarType(); | ||||||
} | ||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,221 @@ | ||||||
//===- VPlanAnalysis.cpp - Various Analyses working on VPlan ----*- C++ -*-===// | ||||||
// | ||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||||
// See https://llvm.org/LICENSE.txt for license information. | ||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||||
// | ||||||
//===----------------------------------------------------------------------===// | ||||||
|
||||||
#include "VPlanAnalysis.h" | ||||||
#include "VPlan.h" | ||||||
|
||||||
using namespace llvm; | ||||||
|
||||||
#define DEBUG_TYPE "vplan" | ||||||
|
||||||
Type *VPTypeAnalysis::inferType(const VPBlendRecipe *R) { | ||||||
return inferType(R->getIncomingValue(0)); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cache types of all other incoming values? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, thanks! |
||||||
} | ||||||
|
||||||
Type *VPTypeAnalysis::inferType(const VPInstruction *R) { | ||||||
switch (R->getOpcode()) { | ||||||
case Instruction::Select: | ||||||
return inferType(R->getOperand(1)); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cache type of operand 2? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, thanks! |
||||||
case VPInstruction::FirstOrderRecurrenceSplice: | ||||||
return inferType(R->getOperand(0)); | ||||||
default: | ||||||
llvm_unreachable("Unhandled instruction!"); | ||||||
} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, this works w/o return nor unreachable at the end? Very well. Perhaps worth a comment. Switch below should be consistent, i.e., with an unreachable default but no return at the unreachable end. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I updated it to move the unreachable out of the switch here as well |
||||||
} | ||||||
|
||||||
Type *VPTypeAnalysis::inferType(const VPInterleaveRecipe *R) { return nullptr; } | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove? Mark unreachable? Document somewhere what returning null means - no valid type could be inferred? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed for now as this is handled in the caller There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Null should never be returned, added an assert |
||||||
|
||||||
Type *VPTypeAnalysis::inferType(const VPReductionPHIRecipe *R) { | ||||||
return R->getOperand(0)->getLiveInIRValue()->getType(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated, thanks! |
||||||
} | ||||||
|
||||||
Type *VPTypeAnalysis::inferType(const VPWidenRecipe *R) { | ||||||
unsigned Opcode = R->getOpcode(); | ||||||
switch (Opcode) { | ||||||
case Instruction::ICmp: | ||||||
case Instruction::FCmp: | ||||||
return IntegerType::get(Ctx, 1); | ||||||
case Instruction::UDiv: | ||||||
case Instruction::SDiv: | ||||||
case Instruction::SRem: | ||||||
case Instruction::URem: | ||||||
case Instruction::Add: | ||||||
case Instruction::FAdd: | ||||||
case Instruction::Sub: | ||||||
case Instruction::FSub: | ||||||
case Instruction::FNeg: | ||||||
case Instruction::Mul: | ||||||
case Instruction::FMul: | ||||||
case Instruction::FDiv: | ||||||
case Instruction::FRem: | ||||||
case Instruction::Shl: | ||||||
case Instruction::LShr: | ||||||
case Instruction::AShr: | ||||||
case Instruction::And: | ||||||
case Instruction::Or: | ||||||
case Instruction::Xor: { | ||||||
Type *ResTy = inferType(R->getOperand(0)); | ||||||
if (Opcode != Instruction::FNeg) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Deal with FNeg as a separate case, along with Freeze? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adjusted, thanks! |
||||||
assert(ResTy == inferType(R->getOperand(1))); | ||||||
CachedTypes[R->getOperand(1)] = ResTy; | ||||||
} | ||||||
return ResTy; | ||||||
} | ||||||
case Instruction::Freeze: | ||||||
return inferType(R->getOperand(0)); | ||||||
default: | ||||||
// This instruction is not vectorized by simple widening. | ||||||
// LLVM_DEBUG(dbgs() << "LV: Found an unhandled instruction: " << I); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Commented out code? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated to work with opcode, thanks! |
||||||
llvm_unreachable("Unhandled instruction!"); | ||||||
} | ||||||
|
||||||
return nullptr; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mark unreachable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sunk unreachable out of switch |
||||||
} | ||||||
|
||||||
Type *VPTypeAnalysis::inferType(const VPWidenCallRecipe *R) { | ||||||
auto &CI = *cast<CallInst>(R->getUnderlyingInstr()); | ||||||
return CI.getType(); | ||||||
} | ||||||
|
||||||
Type *VPTypeAnalysis::inferType(const VPWidenIntOrFpInductionRecipe *R) { | ||||||
return R->getScalarType(); | ||||||
} | ||||||
|
||||||
Type *VPTypeAnalysis::inferType(const VPWidenMemoryInstructionRecipe *R) { | ||||||
if (R->isStore()) | ||||||
return cast<StoreInst>(&R->getIngredient())->getValueOperand()->getType(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Independent Thought) Should VPWidenMemoryInstructionRecipe use Underlying instead of |
||||||
|
||||||
return cast<LoadInst>(&R->getIngredient())->getType(); | ||||||
} | ||||||
|
||||||
Type *VPTypeAnalysis::inferType(const VPWidenSelectRecipe *R) { | ||||||
return inferType(R->getOperand(1)); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cache type of operand 2. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adjusted, thanks! |
||||||
} | ||||||
|
||||||
Type *VPTypeAnalysis::inferType(const VPReplicateRecipe *R) { | ||||||
switch (R->getUnderlyingInstr()->getOpcode()) { | ||||||
case Instruction::Call: { | ||||||
unsigned CallIdx = R->getNumOperands() - (R->isPredicated() ? 2 : 1); | ||||||
return cast<Function>(R->getOperand(CallIdx)->getLiveInIRValue()) | ||||||
->getReturnType(); | ||||||
} | ||||||
case Instruction::UDiv: | ||||||
case Instruction::SDiv: | ||||||
case Instruction::SRem: | ||||||
case Instruction::URem: | ||||||
case Instruction::Add: | ||||||
case Instruction::FAdd: | ||||||
case Instruction::Sub: | ||||||
case Instruction::FSub: | ||||||
case Instruction::FNeg: | ||||||
case Instruction::Mul: | ||||||
case Instruction::FMul: | ||||||
case Instruction::FDiv: | ||||||
case Instruction::FRem: | ||||||
case Instruction::Shl: | ||||||
case Instruction::LShr: | ||||||
case Instruction::AShr: | ||||||
case Instruction::And: | ||||||
case Instruction::Or: | ||||||
case Instruction::Xor: | ||||||
case Instruction::ICmp: | ||||||
case Instruction::FCmp: { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the inferred type always i1 for ICmp/FCmp? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the type inference is for the scalar type only, which always should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be good to clarify that the type inferred is that of scalars/vector-elements. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Renamed, thanks! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ICmp and FCmp should return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I missed this here,. updated, thanks! I also added a few other missing cases here, including GetElementPtr and added the type verification also the |
||||||
Type *ResTy = inferType(R->getOperand(0)); | ||||||
assert(ResTy == inferType(R->getOperand(1))); | ||||||
CachedTypes[R->getOperand(1)] = ResTy; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Excuse unary FNeg, ICmp and FCmp from dealing with operand 1? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, thanks! |
||||||
return ResTy; | ||||||
} | ||||||
case Instruction::Trunc: | ||||||
case Instruction::SExt: | ||||||
case Instruction::ZExt: | ||||||
case Instruction::FPExt: | ||||||
case Instruction::FPTrunc: | ||||||
return R->getUnderlyingInstr()->getType(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fall through? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, thanks! |
||||||
case Instruction::ExtractValue: { | ||||||
return R->getUnderlyingValue()->getType(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it matter if we get the underlying value as a Value or Instr? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated to use |
||||||
} | ||||||
case Instruction::Freeze: | ||||||
return inferType(R->getOperand(0)); | ||||||
case Instruction::Load: | ||||||
return cast<LoadInst>(R->getUnderlyingInstr())->getType(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it matter that the underlying value is a LoadInst? Also supply the type of values being stored? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It's an extra consistency check.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
LoadInst deserves an extra consistency check that truncation and extends do not?
Stores cannot be reached indirectly, but one can query their type directly, and one did provide support for querying the type of a widened stores above and interleaved stored below. Treatment should be consistent regardless of how stores are handled (replicated, widened, interleaved). If querying the type of stores is forbidden, it should be documented. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The interface returns the type of the defined value of the inputs (the public interface computes the type for a VPValue). As stores won't define a result, no type can be queried for them. Does that make sense? |
||||||
default: | ||||||
llvm_unreachable("Unhandled instruction"); | ||||||
} | ||||||
|
||||||
return nullptr; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mark unreachable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sunk unreachable from above |
||||||
} | ||||||
|
||||||
Type *VPTypeAnalysis::inferType(const VPValue *V) { | ||||||
auto Iter = CachedTypes.find(V); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lookup? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. updated, thanks! |
||||||
if (Iter != CachedTypes.end()) | ||||||
return Iter->second; | ||||||
|
||||||
Type *ResultTy = nullptr; | ||||||
if (V->isLiveIn()) | ||||||
ResultTy = V->getLiveInIRValue()->getType(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Worth early exiting. Possibly even w/o polluting the cache with such immediate values. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done,thanks! |
||||||
else { | ||||||
const VPRecipeBase *Def = V->getDefiningRecipe(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indent/clang-format? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Applied clang-format to file, as clang-format-diff was missing this, thanks! |
||||||
switch (Def->getVPDefID()) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would TypeSwitch work better? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure, I think with TypeSwich we would not be able to use fallthroughs, which reduce the duplication a bit here (I've not used TypeSwitch before, so perhaps I missed a way to handle fallthroughs). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated to use typeswitch, helps to reduce some duplication |
||||||
case VPDef::VPBlendSC: | ||||||
ResultTy = inferType(cast<VPBlendRecipe>(Def)); | ||||||
break; | ||||||
case VPDef::VPCanonicalIVPHISC: | ||||||
ResultTy = cast<VPCanonicalIVPHIRecipe>(Def)->getScalarType(); | ||||||
break; | ||||||
case VPDef::VPFirstOrderRecurrencePHISC: | ||||||
ResultTy = Def->getOperand(0)->getLiveInIRValue()->getType(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consistency: this was outlined for Reduction PHI below. Handle both inline together? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved together and to the top, thanks! |
||||||
break; | ||||||
case VPDef::VPInstructionSC: | ||||||
ResultTy = inferType(cast<VPInstruction>(Def)); | ||||||
break; | ||||||
case VPDef::VPInterleaveSC: | ||||||
ResultTy = V->getUnderlyingValue() | ||||||
->getType(); // inferType(cast<VPInterleaveRecipe>(Def)); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Commented out code? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed, thanks! Also added a TODO to use the info from the interleave group directly. |
||||||
break; | ||||||
case VPDef::VPPredInstPHISC: | ||||||
ResultTy = inferType(Def->getOperand(0)); | ||||||
break; | ||||||
case VPDef::VPReductionPHISC: | ||||||
ResultTy = inferType(cast<VPReductionPHIRecipe>(Def)); | ||||||
break; | ||||||
case VPDef::VPReplicateSC: | ||||||
ResultTy = inferType(cast<VPReplicateRecipe>(Def)); | ||||||
break; | ||||||
case VPDef::VPScalarIVStepsSC: | ||||||
return inferType(Def->getOperand(0)); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Collect all cases returning inferType() of their first operand together? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. collected them and also made sure they are added to the cache. |
||||||
break; | ||||||
case VPDef::VPWidenSC: | ||||||
ResultTy = inferType(cast<VPWidenRecipe>(Def)); | ||||||
break; | ||||||
case VPDef::VPWidenPHISC: | ||||||
return inferType(Def->getOperand(0)); | ||||||
case VPDef::VPWidenPointerInductionSC: | ||||||
return inferType(Def->getOperand(0)); | ||||||
case VPDef::VPWidenCallSC: | ||||||
ResultTy = inferType(cast<VPWidenCallRecipe>(Def)); | ||||||
break; | ||||||
case VPDef::VPWidenCastSC: | ||||||
ResultTy = cast<VPWidenCastRecipe>(Def)->getResultType(); | ||||||
break; | ||||||
case VPDef::VPWidenGEPSC: | ||||||
ResultTy = PointerType::get(Ctx, 0); | ||||||
break; | ||||||
case VPDef::VPWidenIntOrFpInductionSC: | ||||||
ResultTy = inferType(cast<VPWidenIntOrFpInductionRecipe>(Def)); | ||||||
break; | ||||||
case VPDef::VPWidenMemoryInstructionSC: | ||||||
ResultTy = inferType(cast<VPWidenMemoryInstructionRecipe>(Def)); | ||||||
break; | ||||||
case VPDef::VPWidenSelectSC: | ||||||
ResultTy = inferType(cast<VPWidenSelectRecipe>(Def)); | ||||||
break; | ||||||
} | ||||||
} | ||||||
CachedTypes[V] = ResultTy; | ||||||
return ResultTy; | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
//===- VPlanAnalysis.h - Various Analyses working on VPlan ------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANANALYSIS_H | ||
#define LLVM_TRANSFORMS_VECTORIZE_VPLANANALYSIS_H | ||
|
||
#include "llvm/ADT/DenseMap.h" | ||
|
||
namespace llvm { | ||
|
||
class LLVMContext; | ||
class VPValue; | ||
class VPBlendRecipe; | ||
class VPInterleaveRecipe; | ||
class VPInstruction; | ||
class VPReductionPHIRecipe; | ||
class VPWidenRecipe; | ||
class VPWidenCallRecipe; | ||
class VPWidenCastRecipe; | ||
class VPWidenIntOrFpInductionRecipe; | ||
class VPWidenMemoryInstructionRecipe; | ||
struct VPWidenSelectRecipe; | ||
class VPReplicateRecipe; | ||
class Type; | ||
|
||
/// An analysis for type-inferrence for VPValues. | ||
fhahn marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Worth saying some more, e.g., on-demand cached bottom-up use-def analysis. Rerun if any recipes are changed to invalidate the cache? |
||
class VPTypeAnalysis { | ||
DenseMap<const VPValue *, Type *> CachedTypes; | ||
LLVMContext &Ctx; | ||
|
||
Type *inferType(const VPBlendRecipe *R); | ||
Type *inferType(const VPInstruction *R); | ||
Type *inferType(const VPInterleaveRecipe *R); | ||
Type *inferType(const VPWidenCallRecipe *R); | ||
Type *inferType(const VPReductionPHIRecipe *R); | ||
Type *inferType(const VPWidenRecipe *R); | ||
Type *inferType(const VPWidenIntOrFpInductionRecipe *R); | ||
Type *inferType(const VPWidenMemoryInstructionRecipe *R); | ||
Type *inferType(const VPWidenSelectRecipe *R); | ||
Type *inferType(const VPReplicateRecipe *R); | ||
|
||
public: | ||
VPTypeAnalysis(LLVMContext &Ctx) : Ctx(Ctx) {} | ||
|
||
/// Infer the type of \p V. Returns the scalar type of \p V. | ||
Type *inferType(const VPValue *V); | ||
}; | ||
|
||
} // end namespace llvm | ||
|
||
#endif // LLVM_TRANSFORMS_VECTORIZE_VPLANANALYSIS_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
//===----------------------------------------------------------------------===// | ||
|
||
#include "VPlan.h" | ||
#include "VPlanAnalysis.h" | ||
#include "llvm/ADT/STLExtras.h" | ||
#include "llvm/ADT/SmallVector.h" | ||
#include "llvm/ADT/Twine.h" | ||
|
@@ -738,7 +739,18 @@ void VPWidenRecipe::execute(VPTransformState &State) { | |
<< Instruction::getOpcodeName(Opcode)); | ||
llvm_unreachable("Unhandled instruction!"); | ||
} // end of switch. | ||
|
||
#if !defined(NDEBUG) | ||
// Verify that VPlan type infererrence results agree with the type of the | ||
fhahn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// generated values. | ||
VPTypeAnalysis A(State.Builder.GetInsertBlock()->getContext()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Caching types is unhelpful and even harmful time-wise if a VPTypeAnalysis is built for every call of inferScalarType(). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will do! |
||
for (unsigned Part = 0; Part < State.UF; ++Part) { | ||
assert(VectorType::get(A.inferType(getVPSingleValue()), State.VF) == | ||
State.get(this, Part)->getType()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. assert is missing a message. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added, thanks! |
||
} | ||
#endif | ||
} | ||
|
||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | ||
void VPWidenRecipe::print(raw_ostream &O, const Twine &Indent, | ||
VPSlotTracker &SlotTracker) const { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can wait for separate subsequent patch: type of all header phi's should arguably be derived from their start value. If it gets truncated, let the start value be truncated in VPlan. Similar for DerivedIV.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed!