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::Or:
39 case Instruction::ICmp:
41 Type *ResTy = inferScalarType(R->getOperand(0));
42 VPValue *OtherV = R->getOperand(1);
43 assert(inferScalarType(OtherV) == ResTy &&
44 "different types inferred for different operands");
45 CachedTypes[OtherV] = ResTy;
46 return ResTy;
47 }
48 case VPInstruction::Not: {
49 Type *ResTy = inferScalarType(R->getOperand(0));
50 assert(IntegerType::get(Ctx, 1) == ResTy &&
51 "unexpected scalar type inferred for operand");
52 return ResTy;
53 }
55 // Return the type based on the pointer argument (i.e. first operand).
56 return inferScalarType(R->getOperand(0));
57 default:
58 break;
59 }
60 // Type inference not implemented for opcode.
62 dbgs() << "LV: Found unhandled opcode for: ";
63 R->getVPSingleValue()->dump();
64 });
65 llvm_unreachable("Unhandled opcode!");
66}
67
68Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenRecipe *R) {
69 unsigned Opcode = R->getOpcode();
70 switch (Opcode) {
71 case Instruction::ICmp:
72 case Instruction::FCmp:
73 return IntegerType::get(Ctx, 1);
74 case Instruction::UDiv:
75 case Instruction::SDiv:
76 case Instruction::SRem:
77 case Instruction::URem:
78 case Instruction::Add:
79 case Instruction::FAdd:
80 case Instruction::Sub:
81 case Instruction::FSub:
82 case Instruction::Mul:
83 case Instruction::FMul:
84 case Instruction::FDiv:
85 case Instruction::FRem:
86 case Instruction::Shl:
87 case Instruction::LShr:
88 case Instruction::AShr:
89 case Instruction::And:
90 case Instruction::Or:
91 case Instruction::Xor: {
92 Type *ResTy = inferScalarType(R->getOperand(0));
93 assert(ResTy == inferScalarType(R->getOperand(1)) &&
94 "types for both operands must match for binary op");
95 CachedTypes[R->getOperand(1)] = ResTy;
96 return ResTy;
97 }
98 case Instruction::FNeg:
99 case Instruction::Freeze:
100 return inferScalarType(R->getOperand(0));
101 default:
102 break;
103 }
104
105 // Type inference not implemented for opcode.
106 LLVM_DEBUG({
107 dbgs() << "LV: Found unhandled opcode for: ";
108 R->getVPSingleValue()->dump();
109 });
110 llvm_unreachable("Unhandled opcode!");
111}
112
113Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenCallRecipe *R) {
114 auto &CI = *cast<CallInst>(R->getUnderlyingInstr());
115 return CI.getType();
116}
117
118Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenMemoryRecipe *R) {
119 assert((isa<VPWidenLoadRecipe>(R) || isa<VPWidenLoadEVLRecipe>(R)) &&
120 "Store recipes should not define any values");
121 return cast<LoadInst>(&R->getIngredient())->getType();
122}
123
124Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenSelectRecipe *R) {
125 Type *ResTy = inferScalarType(R->getOperand(1));
126 VPValue *OtherV = R->getOperand(2);
127 assert(inferScalarType(OtherV) == ResTy &&
128 "different types inferred for different operands");
129 CachedTypes[OtherV] = ResTy;
130 return ResTy;
131}
132
133Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPReplicateRecipe *R) {
134 switch (R->getUnderlyingInstr()->getOpcode()) {
135 case Instruction::Call: {
136 unsigned CallIdx = R->getNumOperands() - (R->isPredicated() ? 2 : 1);
137 return cast<Function>(R->getOperand(CallIdx)->getLiveInIRValue())
138 ->getReturnType();
139 }
140 case Instruction::UDiv:
141 case Instruction::SDiv:
142 case Instruction::SRem:
143 case Instruction::URem:
144 case Instruction::Add:
145 case Instruction::FAdd:
146 case Instruction::Sub:
147 case Instruction::FSub:
148 case Instruction::Mul:
149 case Instruction::FMul:
150 case Instruction::FDiv:
151 case Instruction::FRem:
152 case Instruction::Shl:
153 case Instruction::LShr:
154 case Instruction::AShr:
155 case Instruction::And:
156 case Instruction::Or:
157 case Instruction::Xor: {
158 Type *ResTy = inferScalarType(R->getOperand(0));
159 assert(ResTy == inferScalarType(R->getOperand(1)) &&
160 "inferred types for operands of binary op don't match");
161 CachedTypes[R->getOperand(1)] = ResTy;
162 return ResTy;
163 }
164 case Instruction::Select: {
165 Type *ResTy = inferScalarType(R->getOperand(1));
166 assert(ResTy == inferScalarType(R->getOperand(2)) &&
167 "inferred types for operands of select op don't match");
168 CachedTypes[R->getOperand(2)] = ResTy;
169 return ResTy;
170 }
171 case Instruction::ICmp:
172 case Instruction::FCmp:
173 return IntegerType::get(Ctx, 1);
174 case Instruction::Alloca:
175 case Instruction::BitCast:
176 case Instruction::Trunc:
177 case Instruction::SExt:
178 case Instruction::ZExt:
179 case Instruction::FPExt:
180 case Instruction::FPTrunc:
181 case Instruction::ExtractValue:
182 case Instruction::SIToFP:
183 case Instruction::UIToFP:
184 case Instruction::FPToSI:
185 case Instruction::FPToUI:
186 case Instruction::PtrToInt:
187 case Instruction::IntToPtr:
188 return R->getUnderlyingInstr()->getType();
189 case Instruction::Freeze:
190 case Instruction::FNeg:
191 case Instruction::GetElementPtr:
192 return inferScalarType(R->getOperand(0));
193 case Instruction::Load:
194 return cast<LoadInst>(R->getUnderlyingInstr())->getType();
195 case Instruction::Store:
196 // FIXME: VPReplicateRecipes with store opcodes still define a result
197 // VPValue, so we need to handle them here. Remove the code here once this
198 // is modeled accurately in VPlan.
199 return Type::getVoidTy(Ctx);
200 default:
201 break;
202 }
203 // Type inference not implemented for opcode.
204 LLVM_DEBUG({
205 dbgs() << "LV: Found unhandled opcode for: ";
206 R->getVPSingleValue()->dump();
207 });
208 llvm_unreachable("Unhandled opcode");
209}
210
212 if (Type *CachedTy = CachedTypes.lookup(V))
213 return CachedTy;
214
215 if (V->isLiveIn()) {
216 if (auto *IRValue = V->getLiveInIRValue())
217 return IRValue->getType();
218 // All VPValues without any underlying IR value (like the vector trip count
219 // or the backedge-taken count) have the same type as the canonical IV.
220 return CanonicalIVTy;
221 }
222
223 Type *ResultTy =
224 TypeSwitch<const VPRecipeBase *, Type *>(V->getDefiningRecipe())
227 VPEVLBasedIVPHIRecipe>([this](const auto *R) {
228 // Handle header phi recipes, except VPWidenIntOrFpInduction
229 // which needs special handling due it being possibly truncated.
230 // TODO: consider inferring/caching type of siblings, e.g.,
231 // backedge value, here and in cases below.
232 return inferScalarType(R->getStartValue());
233 })
234 .Case<VPWidenIntOrFpInductionRecipe, VPDerivedIVRecipe>(
235 [](const auto *R) { return R->getScalarType(); })
237 VPWidenGEPRecipe>([this](const VPRecipeBase *R) {
238 return inferScalarType(R->getOperand(0));
239 })
242 [this](const auto *R) { return inferScalarTypeForRecipe(R); })
243 .Case<VPInterleaveRecipe>([V](const VPInterleaveRecipe *R) {
244 // TODO: Use info from interleave group.
245 return V->getUnderlyingValue()->getType();
246 })
247 .Case<VPWidenCastRecipe>(
248 [](const VPWidenCastRecipe *R) { return R->getResultType(); })
249 .Case<VPScalarCastRecipe>(
250 [](const VPScalarCastRecipe *R) { return R->getResultType(); })
251 .Case<VPExpandSCEVRecipe>([](const VPExpandSCEVRecipe *R) {
252 return R->getSCEV()->getType();
253 });
254
255 assert(ResultTy && "could not infer type for the given VPValue");
256 CachedTypes[V] = ResultTy;
257 return ResultTy;
258}
#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:1933
Canonical scalar induction phi of the vector loop.
Definition: VPlan.h:2548
A recipe for generating the phi node for the current index of elements, adjusted in accordance with E...
Definition: VPlan.h:2637
Recipe to expand a SCEV expression.
Definition: VPlan.h:2516
This is a concrete Recipe that models a single VPlan-level instruction.
Definition: VPlan.h:1159
@ FirstOrderRecurrenceSplice
Definition: VPlan.h:1165
VPInterleaveRecipe is a recipe for transforming an interleave group of load or stores into one wide l...
Definition: VPlan.h:1990
VPPredInstPHIRecipe is a recipe for generating the phi nodes needed when control converges back from ...
Definition: VPlan.h:2251
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition: VPlan.h:709
A recipe for handling reduction phis.
Definition: VPlan.h:1874
VPReplicateRecipe replicates a given instruction producing multiple scalar copies of the original sca...
Definition: VPlan.h:2127
VPScalarCastRecipe is a recipe to create scalar cast instructions.
Definition: VPlan.h:1410
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
Definition: VPlan.h:2765
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:1449
VPWidenCastRecipe is a recipe to create vector cast instructions.
Definition: VPlan.h:1360
A recipe for handling GEP instructions.
Definition: VPlan.h:1522
A common base class for widening memory operations.
Definition: VPlan.h:2284
A recipe for handling phis that are widened in the vector loop.
Definition: VPlan.h:1802
VPWidenRecipe is a recipe for producing a copy of vector type its ingredient.
Definition: VPlan.h:1328
#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:1847
A recipe for widening select instructions.
Definition: VPlan.h:1488