LLVM 19.0.0git
VPlanAnalysis.cpp
Go to the documentation of this file.
1//===- VPlanAnalysis.cpp - Various Analyses working on VPlan ----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "VPlanAnalysis.h"
10#include "VPlan.h"
11#include "llvm/ADT/TypeSwitch.h"
12#include "llvm/IR/Instruction.h"
13
14using namespace llvm;
15
16#define DEBUG_TYPE "vplan"
17
18Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPBlendRecipe *R) {
19 Type *ResTy = inferScalarType(R->getIncomingValue(0));
20 for (unsigned I = 1, E = R->getNumIncomingValues(); I != E; ++I) {
21 VPValue *Inc = R->getIncomingValue(I);
22 assert(inferScalarType(Inc) == ResTy &&
23 "different types inferred for different incoming values");
24 CachedTypes[Inc] = ResTy;
25 }
26 return ResTy;
27}
28
29Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPInstruction *R) {
30 // Set the result type from the first operand, check if the types for all
31 // other operands match and cache them.
32 auto SetResultTyFromOp = [this, R]() {
33 Type *ResTy = inferScalarType(R->getOperand(0));
34 for (unsigned Op = 1; Op != R->getNumOperands(); ++Op) {
35 VPValue *OtherV = R->getOperand(Op);
36 assert(inferScalarType(OtherV) == ResTy &&
37 "different types inferred for different operands");
38 CachedTypes[OtherV] = ResTy;
39 }
40 return ResTy;
41 };
42
43 unsigned Opcode = R->getOpcode();
45 return SetResultTyFromOp();
46
47 switch (Opcode) {
48 case Instruction::Select: {
49 Type *ResTy = inferScalarType(R->getOperand(1));
50 VPValue *OtherV = R->getOperand(2);
51 assert(inferScalarType(OtherV) == ResTy &&
52 "different types inferred for different operands");
53 CachedTypes[OtherV] = ResTy;
54 return ResTy;
55 }
56 case Instruction::ICmp:
59 return SetResultTyFromOp();
61 Type *BaseTy = inferScalarType(R->getOperand(0));
62 if (auto *VecTy = dyn_cast<VectorType>(BaseTy))
63 return VecTy->getElementType();
64 return BaseTy;
65 }
67 return IntegerType::get(Ctx, 1);
69 // Return the type based on the pointer argument (i.e. first operand).
70 return inferScalarType(R->getOperand(0));
71 default:
72 break;
73 }
74 // Type inference not implemented for opcode.
76 dbgs() << "LV: Found unhandled opcode for: ";
77 R->getVPSingleValue()->dump();
78 });
79 llvm_unreachable("Unhandled opcode!");
80}
81
82Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenRecipe *R) {
83 unsigned Opcode = R->getOpcode();
84 switch (Opcode) {
85 case Instruction::ICmp:
86 case Instruction::FCmp:
87 return IntegerType::get(Ctx, 1);
88 case Instruction::UDiv:
89 case Instruction::SDiv:
90 case Instruction::SRem:
91 case Instruction::URem:
92 case Instruction::Add:
93 case Instruction::FAdd:
94 case Instruction::Sub:
95 case Instruction::FSub:
96 case Instruction::Mul:
97 case Instruction::FMul:
98 case Instruction::FDiv:
99 case Instruction::FRem:
100 case Instruction::Shl:
101 case Instruction::LShr:
102 case Instruction::AShr:
103 case Instruction::And:
104 case Instruction::Or:
105 case Instruction::Xor: {
106 Type *ResTy = inferScalarType(R->getOperand(0));
107 assert(ResTy == inferScalarType(R->getOperand(1)) &&
108 "types for both operands must match for binary op");
109 CachedTypes[R->getOperand(1)] = ResTy;
110 return ResTy;
111 }
112 case Instruction::FNeg:
113 case Instruction::Freeze:
114 return inferScalarType(R->getOperand(0));
115 default:
116 break;
117 }
118
119 // Type inference not implemented for opcode.
120 LLVM_DEBUG({
121 dbgs() << "LV: Found unhandled opcode for: ";
122 R->getVPSingleValue()->dump();
123 });
124 llvm_unreachable("Unhandled opcode!");
125}
126
127Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenCallRecipe *R) {
128 auto &CI = *cast<CallInst>(R->getUnderlyingInstr());
129 return CI.getType();
130}
131
132Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenMemoryRecipe *R) {
133 assert((isa<VPWidenLoadRecipe>(R) || isa<VPWidenLoadEVLRecipe>(R)) &&
134 "Store recipes should not define any values");
135 return cast<LoadInst>(&R->getIngredient())->getType();
136}
137
138Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenSelectRecipe *R) {
139 Type *ResTy = inferScalarType(R->getOperand(1));
140 VPValue *OtherV = R->getOperand(2);
141 assert(inferScalarType(OtherV) == ResTy &&
142 "different types inferred for different operands");
143 CachedTypes[OtherV] = ResTy;
144 return ResTy;
145}
146
147Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPReplicateRecipe *R) {
148 switch (R->getUnderlyingInstr()->getOpcode()) {
149 case Instruction::Call: {
150 unsigned CallIdx = R->getNumOperands() - (R->isPredicated() ? 2 : 1);
151 return cast<Function>(R->getOperand(CallIdx)->getLiveInIRValue())
152 ->getReturnType();
153 }
154 case Instruction::UDiv:
155 case Instruction::SDiv:
156 case Instruction::SRem:
157 case Instruction::URem:
158 case Instruction::Add:
159 case Instruction::FAdd:
160 case Instruction::Sub:
161 case Instruction::FSub:
162 case Instruction::Mul:
163 case Instruction::FMul:
164 case Instruction::FDiv:
165 case Instruction::FRem:
166 case Instruction::Shl:
167 case Instruction::LShr:
168 case Instruction::AShr:
169 case Instruction::And:
170 case Instruction::Or:
171 case Instruction::Xor: {
172 Type *ResTy = inferScalarType(R->getOperand(0));
173 assert(ResTy == inferScalarType(R->getOperand(1)) &&
174 "inferred types for operands of binary op don't match");
175 CachedTypes[R->getOperand(1)] = ResTy;
176 return ResTy;
177 }
178 case Instruction::Select: {
179 Type *ResTy = inferScalarType(R->getOperand(1));
180 assert(ResTy == inferScalarType(R->getOperand(2)) &&
181 "inferred types for operands of select op don't match");
182 CachedTypes[R->getOperand(2)] = ResTy;
183 return ResTy;
184 }
185 case Instruction::ICmp:
186 case Instruction::FCmp:
187 return IntegerType::get(Ctx, 1);
188 case Instruction::AddrSpaceCast:
189 case Instruction::Alloca:
190 case Instruction::BitCast:
191 case Instruction::Trunc:
192 case Instruction::SExt:
193 case Instruction::ZExt:
194 case Instruction::FPExt:
195 case Instruction::FPTrunc:
196 case Instruction::ExtractValue:
197 case Instruction::SIToFP:
198 case Instruction::UIToFP:
199 case Instruction::FPToSI:
200 case Instruction::FPToUI:
201 case Instruction::PtrToInt:
202 case Instruction::IntToPtr:
203 return R->getUnderlyingInstr()->getType();
204 case Instruction::Freeze:
205 case Instruction::FNeg:
206 case Instruction::GetElementPtr:
207 return inferScalarType(R->getOperand(0));
208 case Instruction::Load:
209 return cast<LoadInst>(R->getUnderlyingInstr())->getType();
210 case Instruction::Store:
211 // FIXME: VPReplicateRecipes with store opcodes still define a result
212 // VPValue, so we need to handle them here. Remove the code here once this
213 // is modeled accurately in VPlan.
214 return Type::getVoidTy(Ctx);
215 default:
216 break;
217 }
218 // Type inference not implemented for opcode.
219 LLVM_DEBUG({
220 dbgs() << "LV: Found unhandled opcode for: ";
221 R->getVPSingleValue()->dump();
222 });
223 llvm_unreachable("Unhandled opcode");
224}
225
227 if (Type *CachedTy = CachedTypes.lookup(V))
228 return CachedTy;
229
230 if (V->isLiveIn()) {
231 if (auto *IRValue = V->getLiveInIRValue())
232 return IRValue->getType();
233 // All VPValues without any underlying IR value (like the vector trip count
234 // or the backedge-taken count) have the same type as the canonical IV.
235 return CanonicalIVTy;
236 }
237
238 Type *ResultTy =
239 TypeSwitch<const VPRecipeBase *, Type *>(V->getDefiningRecipe())
242 VPEVLBasedIVPHIRecipe>([this](const auto *R) {
243 // Handle header phi recipes, except VPWidenIntOrFpInduction
244 // which needs special handling due it being possibly truncated.
245 // TODO: consider inferring/caching type of siblings, e.g.,
246 // backedge value, here and in cases below.
247 return inferScalarType(R->getStartValue());
248 })
249 .Case<VPWidenIntOrFpInductionRecipe, VPDerivedIVRecipe>(
250 [](const auto *R) { return R->getScalarType(); })
252 VPWidenGEPRecipe>([this](const VPRecipeBase *R) {
253 return inferScalarType(R->getOperand(0));
254 })
257 [this](const auto *R) { return inferScalarTypeForRecipe(R); })
258 .Case<VPInterleaveRecipe>([V](const VPInterleaveRecipe *R) {
259 // TODO: Use info from interleave group.
260 return V->getUnderlyingValue()->getType();
261 })
262 .Case<VPWidenCastRecipe>(
263 [](const VPWidenCastRecipe *R) { return R->getResultType(); })
264 .Case<VPScalarCastRecipe>(
265 [](const VPScalarCastRecipe *R) { return R->getResultType(); })
266 .Case<VPExpandSCEVRecipe>([](const VPExpandSCEVRecipe *R) {
267 return R->getSCEV()->getType();
268 });
269
270 assert(ResultTy && "could not infer type for the given VPValue");
271 CachedTypes[V] = ResultTy;
272 return ResultTy;
273}
#define LLVM_DEBUG(X)
Definition: Debug.h:101
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the TypeSwitch template, which mimics a switch() statement whose cases are type ...
This file contains the declarations of the Vectorization Plan base classes:
This class represents an Operation in the Expression.
bool isBinaryOp() const
Definition: Instruction.h:279
bool isUnaryOp() const
Definition: Instruction.h:278
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition: Type.cpp:278
This class implements a switch-like dispatch statement for a value of 'T' using dyn_cast functionalit...
Definition: TypeSwitch.h:87
TypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
Definition: TypeSwitch.h:96
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
static Type * getVoidTy(LLVMContext &C)
A recipe for vectorizing a phi-node as a sequence of mask-based select instructions.
Definition: VPlan.h:1967
Canonical scalar induction phi of the vector loop.
Definition: VPlan.h:2583
A recipe for generating the phi node for the current index of elements, adjusted in accordance with E...
Definition: VPlan.h:2672
Recipe to expand a SCEV expression.
Definition: VPlan.h:2551
This is a concrete Recipe that models a single VPlan-level instruction.
Definition: VPlan.h:1180
@ FirstOrderRecurrenceSplice
Definition: VPlan.h:1186
VPInterleaveRecipe is a recipe for transforming an interleave group of load or stores into one wide l...
Definition: VPlan.h:2024
VPPredInstPHIRecipe is a recipe for generating the phi nodes needed when control converges back from ...
Definition: VPlan.h:2285
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition: VPlan.h:726
A recipe for handling reduction phis.
Definition: VPlan.h:1908
VPReplicateRecipe replicates a given instruction producing multiple scalar copies of the original sca...
Definition: VPlan.h:2161
VPScalarCastRecipe is a recipe to create scalar cast instructions.
Definition: VPlan.h:1429
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
Definition: VPlan.h:2794
Type * inferScalarType(const VPValue *V)
Infer the type of V. Returns the scalar type of V.
A recipe for widening Call instructions.
Definition: VPlan.h:1468
VPWidenCastRecipe is a recipe to create vector cast instructions.
Definition: VPlan.h:1379
A recipe for handling GEP instructions.
Definition: VPlan.h:1555
A common base class for widening memory operations.
Definition: VPlan.h:2318
A recipe for handling phis that are widened in the vector loop.
Definition: VPlan.h:1836
VPWidenRecipe is a recipe for producing a copy of vector type its ingredient.
Definition: VPlan.h:1347
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
DWARFExpression::Operation Op
A recipe for handling first-order recurrence phis.
Definition: VPlan.h:1881
A recipe for widening select instructions.
Definition: VPlan.h:1521