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::AddrSpaceCast:
175 case Instruction::Alloca:
176 case Instruction::BitCast:
177 case Instruction::Trunc:
178 case Instruction::SExt:
179 case Instruction::ZExt:
180 case Instruction::FPExt:
181 case Instruction::FPTrunc:
182 case Instruction::ExtractValue:
183 case Instruction::SIToFP:
184 case Instruction::UIToFP:
185 case Instruction::FPToSI:
186 case Instruction::FPToUI:
187 case Instruction::PtrToInt:
188 case Instruction::IntToPtr:
189 return R->getUnderlyingInstr()->getType();
190 case Instruction::Freeze:
191 case Instruction::FNeg:
192 case Instruction::GetElementPtr:
193 return inferScalarType(R->getOperand(0));
194 case Instruction::Load:
195 return cast<LoadInst>(R->getUnderlyingInstr())->getType();
196 case Instruction::Store:
197 // FIXME: VPReplicateRecipes with store opcodes still define a result
198 // VPValue, so we need to handle them here. Remove the code here once this
199 // is modeled accurately in VPlan.
200 return Type::getVoidTy(Ctx);
201 default:
202 break;
203 }
204 // Type inference not implemented for opcode.
205 LLVM_DEBUG({
206 dbgs() << "LV: Found unhandled opcode for: ";
207 R->getVPSingleValue()->dump();
208 });
209 llvm_unreachable("Unhandled opcode");
210}
211
213 if (Type *CachedTy = CachedTypes.lookup(V))
214 return CachedTy;
215
216 if (V->isLiveIn()) {
217 if (auto *IRValue = V->getLiveInIRValue())
218 return IRValue->getType();
219 // All VPValues without any underlying IR value (like the vector trip count
220 // or the backedge-taken count) have the same type as the canonical IV.
221 return CanonicalIVTy;
222 }
223
224 Type *ResultTy =
225 TypeSwitch<const VPRecipeBase *, Type *>(V->getDefiningRecipe())
228 VPEVLBasedIVPHIRecipe>([this](const auto *R) {
229 // Handle header phi recipes, except VPWidenIntOrFpInduction
230 // which needs special handling due it being possibly truncated.
231 // TODO: consider inferring/caching type of siblings, e.g.,
232 // backedge value, here and in cases below.
233 return inferScalarType(R->getStartValue());
234 })
235 .Case<VPWidenIntOrFpInductionRecipe, VPDerivedIVRecipe>(
236 [](const auto *R) { return R->getScalarType(); })
238 VPWidenGEPRecipe>([this](const VPRecipeBase *R) {
239 return inferScalarType(R->getOperand(0));
240 })
243 [this](const auto *R) { return inferScalarTypeForRecipe(R); })
244 .Case<VPInterleaveRecipe>([V](const VPInterleaveRecipe *R) {
245 // TODO: Use info from interleave group.
246 return V->getUnderlyingValue()->getType();
247 })
248 .Case<VPWidenCastRecipe>(
249 [](const VPWidenCastRecipe *R) { return R->getResultType(); })
250 .Case<VPScalarCastRecipe>(
251 [](const VPScalarCastRecipe *R) { return R->getResultType(); })
252 .Case<VPExpandSCEVRecipe>([](const VPExpandSCEVRecipe *R) {
253 return R->getSCEV()->getType();
254 });
255
256 assert(ResultTy && "could not infer type for the given VPValue");
257 CachedTypes[V] = ResultTy;
258 return ResultTy;
259}
#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: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:1950
Canonical scalar induction phi of the vector loop.
Definition: VPlan.h:2566
A recipe for generating the phi node for the current index of elements, adjusted in accordance with E...
Definition: VPlan.h:2655
Recipe to expand a SCEV expression.
Definition: VPlan.h:2534
This is a concrete Recipe that models a single VPlan-level instruction.
Definition: VPlan.h:1160
@ FirstOrderRecurrenceSplice
Definition: VPlan.h:1166
VPInterleaveRecipe is a recipe for transforming an interleave group of load or stores into one wide l...
Definition: VPlan.h:2007
VPPredInstPHIRecipe is a recipe for generating the phi nodes needed when control converges back from ...
Definition: VPlan.h:2268
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:1891
VPReplicateRecipe replicates a given instruction producing multiple scalar copies of the original sca...
Definition: VPlan.h:2144
VPScalarCastRecipe is a recipe to create scalar cast instructions.
Definition: VPlan.h:1412
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
Definition: VPlan.h:2777
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:1451
VPWidenCastRecipe is a recipe to create vector cast instructions.
Definition: VPlan.h:1362
A recipe for handling GEP instructions.
Definition: VPlan.h:1538
A common base class for widening memory operations.
Definition: VPlan.h:2301
A recipe for handling phis that are widened in the vector loop.
Definition: VPlan.h:1819
VPWidenRecipe is a recipe for producing a copy of vector type its ingredient.
Definition: VPlan.h:1330
#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:1864
A recipe for widening select instructions.
Definition: VPlan.h:1504