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
13using namespace llvm;
14
15#define DEBUG_TYPE "vplan"
16
17Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPBlendRecipe *R) {
18 Type *ResTy = inferScalarType(R->getIncomingValue(0));
19 for (unsigned I = 1, E = R->getNumIncomingValues(); I != E; ++I) {
20 VPValue *Inc = R->getIncomingValue(I);
21 assert(inferScalarType(Inc) == ResTy &&
22 "different types inferred for different incoming values");
23 CachedTypes[Inc] = ResTy;
24 }
25 return ResTy;
26}
27
28Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPInstruction *R) {
29 switch (R->getOpcode()) {
30 case Instruction::Select: {
31 Type *ResTy = inferScalarType(R->getOperand(1));
32 VPValue *OtherV = R->getOperand(2);
33 assert(inferScalarType(OtherV) == ResTy &&
34 "different types inferred for different operands");
35 CachedTypes[OtherV] = ResTy;
36 return ResTy;
37 }
38 case Instruction::ICmp:
40 Type *ResTy = inferScalarType(R->getOperand(0));
41 VPValue *OtherV = R->getOperand(1);
42 assert(inferScalarType(OtherV) == ResTy &&
43 "different types inferred for different operands");
44 CachedTypes[OtherV] = ResTy;
45 return ResTy;
46 }
47 default:
48 break;
49 }
50 // Type inference not implemented for opcode.
52 dbgs() << "LV: Found unhandled opcode for: ";
53 R->getVPSingleValue()->dump();
54 });
55 llvm_unreachable("Unhandled opcode!");
56}
57
58Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenRecipe *R) {
59 unsigned Opcode = R->getOpcode();
60 switch (Opcode) {
61 case Instruction::ICmp:
62 case Instruction::FCmp:
63 return IntegerType::get(Ctx, 1);
64 case Instruction::UDiv:
65 case Instruction::SDiv:
66 case Instruction::SRem:
67 case Instruction::URem:
68 case Instruction::Add:
69 case Instruction::FAdd:
70 case Instruction::Sub:
71 case Instruction::FSub:
72 case Instruction::Mul:
73 case Instruction::FMul:
74 case Instruction::FDiv:
75 case Instruction::FRem:
76 case Instruction::Shl:
77 case Instruction::LShr:
78 case Instruction::AShr:
79 case Instruction::And:
80 case Instruction::Or:
81 case Instruction::Xor: {
82 Type *ResTy = inferScalarType(R->getOperand(0));
83 assert(ResTy == inferScalarType(R->getOperand(1)) &&
84 "types for both operands must match for binary op");
85 CachedTypes[R->getOperand(1)] = ResTy;
86 return ResTy;
87 }
88 case Instruction::FNeg:
89 case Instruction::Freeze:
90 return inferScalarType(R->getOperand(0));
91 default:
92 break;
93 }
94
95 // Type inference not implemented for opcode.
97 dbgs() << "LV: Found unhandled opcode for: ";
98 R->getVPSingleValue()->dump();
99 });
100 llvm_unreachable("Unhandled opcode!");
101}
102
103Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenCallRecipe *R) {
104 auto &CI = *cast<CallInst>(R->getUnderlyingInstr());
105 return CI.getType();
106}
107
108Type *VPTypeAnalysis::inferScalarTypeForRecipe(
110 assert(!R->isStore() && "Store recipes should not define any values");
111 return cast<LoadInst>(&R->getIngredient())->getType();
112}
113
114Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenSelectRecipe *R) {
115 Type *ResTy = inferScalarType(R->getOperand(1));
116 VPValue *OtherV = R->getOperand(2);
117 assert(inferScalarType(OtherV) == ResTy &&
118 "different types inferred for different operands");
119 CachedTypes[OtherV] = ResTy;
120 return ResTy;
121}
122
123Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPReplicateRecipe *R) {
124 switch (R->getUnderlyingInstr()->getOpcode()) {
125 case Instruction::Call: {
126 unsigned CallIdx = R->getNumOperands() - (R->isPredicated() ? 2 : 1);
127 return cast<Function>(R->getOperand(CallIdx)->getLiveInIRValue())
128 ->getReturnType();
129 }
130 case Instruction::UDiv:
131 case Instruction::SDiv:
132 case Instruction::SRem:
133 case Instruction::URem:
134 case Instruction::Add:
135 case Instruction::FAdd:
136 case Instruction::Sub:
137 case Instruction::FSub:
138 case Instruction::Mul:
139 case Instruction::FMul:
140 case Instruction::FDiv:
141 case Instruction::FRem:
142 case Instruction::Shl:
143 case Instruction::LShr:
144 case Instruction::AShr:
145 case Instruction::And:
146 case Instruction::Or:
147 case Instruction::Xor: {
148 Type *ResTy = inferScalarType(R->getOperand(0));
149 assert(ResTy == inferScalarType(R->getOperand(1)) &&
150 "inferred types for operands of binary op don't match");
151 CachedTypes[R->getOperand(1)] = ResTy;
152 return ResTy;
153 }
154 case Instruction::Select: {
155 Type *ResTy = inferScalarType(R->getOperand(1));
156 assert(ResTy == inferScalarType(R->getOperand(2)) &&
157 "inferred types for operands of select op don't match");
158 CachedTypes[R->getOperand(2)] = ResTy;
159 return ResTy;
160 }
161 case Instruction::ICmp:
162 case Instruction::FCmp:
163 return IntegerType::get(Ctx, 1);
164 case Instruction::Alloca:
165 case Instruction::BitCast:
166 case Instruction::Trunc:
167 case Instruction::SExt:
168 case Instruction::ZExt:
169 case Instruction::FPExt:
170 case Instruction::FPTrunc:
171 case Instruction::ExtractValue:
172 case Instruction::SIToFP:
173 case Instruction::UIToFP:
174 case Instruction::FPToSI:
175 case Instruction::FPToUI:
176 case Instruction::PtrToInt:
177 case Instruction::IntToPtr:
178 return R->getUnderlyingInstr()->getType();
179 case Instruction::Freeze:
180 case Instruction::FNeg:
181 case Instruction::GetElementPtr:
182 return inferScalarType(R->getOperand(0));
183 case Instruction::Load:
184 return cast<LoadInst>(R->getUnderlyingInstr())->getType();
185 case Instruction::Store:
186 // FIXME: VPReplicateRecipes with store opcodes still define a result
187 // VPValue, so we need to handle them here. Remove the code here once this
188 // is modeled accurately in VPlan.
189 return Type::getVoidTy(Ctx);
190 default:
191 break;
192 }
193 // Type inference not implemented for opcode.
194 LLVM_DEBUG({
195 dbgs() << "LV: Found unhandled opcode for: ";
196 R->getVPSingleValue()->dump();
197 });
198 llvm_unreachable("Unhandled opcode");
199}
200
202 if (Type *CachedTy = CachedTypes.lookup(V))
203 return CachedTy;
204
205 if (V->isLiveIn()) {
206 if (auto *IRValue = V->getLiveInIRValue())
207 return IRValue->getType();
208 // All VPValues without any underlying IR value (like the vector trip count
209 // or the backedge-taken count) have the same type as the canonical IV.
210 return CanonicalIVTy;
211 }
212
213 Type *ResultTy =
214 TypeSwitch<const VPRecipeBase *, Type *>(V->getDefiningRecipe())
217 [this](const auto *R) {
218 // Handle header phi recipes, except VPWienIntOrFpInduction
219 // which needs special handling due it being possibly truncated.
220 // TODO: consider inferring/caching type of siblings, e.g.,
221 // backedge value, here and in cases below.
222 return inferScalarType(R->getStartValue());
223 })
224 .Case<VPWidenIntOrFpInductionRecipe, VPDerivedIVRecipe>(
225 [](const auto *R) { return R->getScalarType(); })
227 VPWidenGEPRecipe>([this](const VPRecipeBase *R) {
228 return inferScalarType(R->getOperand(0));
229 })
233 [this](const auto *R) { return inferScalarTypeForRecipe(R); })
234 .Case<VPInterleaveRecipe>([V](const VPInterleaveRecipe *R) {
235 // TODO: Use info from interleave group.
236 return V->getUnderlyingValue()->getType();
237 })
238 .Case<VPWidenCastRecipe>(
239 [](const VPWidenCastRecipe *R) { return R->getResultType(); })
240 .Case<VPScalarCastRecipe>(
241 [](const VPScalarCastRecipe *R) { return R->getResultType(); })
242 .Case<VPExpandSCEVRecipe>([](const VPExpandSCEVRecipe *R) {
243 return R->getSCEV()->getType();
244 });
245
246 assert(ResultTy && "could not infer type for the given VPValue");
247 CachedTypes[V] = ResultTy;
248 return ResultTy;
249}
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#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:
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:107
TypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
Definition: TypeSwitch.h:116
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:1868
Canonical scalar induction phi of the vector loop.
Definition: VPlan.h:2349
Recipe to expand a SCEV expression.
Definition: VPlan.h:2319
This is a concrete Recipe that models a single VPlan-level instruction.
Definition: VPlan.h:1132
@ FirstOrderRecurrenceSplice
Definition: VPlan.h:1138
VPInterleaveRecipe is a recipe for transforming an interleave group of load or stores into one wide l...
Definition: VPlan.h:1922
VPPredInstPHIRecipe is a recipe for generating the phi nodes needed when control converges back from ...
Definition: VPlan.h:2179
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition: VPlan.h:706
A recipe for handling reduction phis.
Definition: VPlan.h:1809
VPReplicateRecipe replicates a given instruction producing multiple scalar copies of the original sca...
Definition: VPlan.h:2057
VPScalarCastRecipe is a recipe to create scalar cast instructions.
Definition: VPlan.h:1352
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
Definition: VPlan.h:2530
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:1384
VPWidenCastRecipe is a recipe to create vector cast instructions.
Definition: VPlan.h:1302
A recipe for handling GEP instructions.
Definition: VPlan.h:1457
A Recipe for widening load/store operations.
Definition: VPlan.h:2216
A recipe for handling phis that are widened in the vector loop.
Definition: VPlan.h:1737
VPWidenRecipe is a recipe for producing a copy of vector type its ingredient.
Definition: VPlan.h:1270
#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
A recipe for handling first-order recurrence phis.
Definition: VPlan.h:1782
A recipe for widening select instructions.
Definition: VPlan.h:1423