xref: /src/contrib/llvm-project/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1b1c73532SDimitry Andric //===- VPlanAnalysis.cpp - Various Analyses working on VPlan ----*- C++ -*-===//
2b1c73532SDimitry Andric //
3b1c73532SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b1c73532SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5b1c73532SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b1c73532SDimitry Andric //
7b1c73532SDimitry Andric //===----------------------------------------------------------------------===//
8b1c73532SDimitry Andric 
9b1c73532SDimitry Andric #include "VPlanAnalysis.h"
10b1c73532SDimitry Andric #include "VPlan.h"
11ac9a064cSDimitry Andric #include "VPlanCFG.h"
12b1c73532SDimitry Andric #include "llvm/ADT/TypeSwitch.h"
13ac9a064cSDimitry Andric #include "llvm/IR/Instruction.h"
14ac9a064cSDimitry Andric #include "llvm/IR/PatternMatch.h"
15b1c73532SDimitry Andric 
16b1c73532SDimitry Andric using namespace llvm;
17b1c73532SDimitry Andric 
18b1c73532SDimitry Andric #define DEBUG_TYPE "vplan"
19b1c73532SDimitry Andric 
inferScalarTypeForRecipe(const VPBlendRecipe * R)20b1c73532SDimitry Andric Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPBlendRecipe *R) {
21b1c73532SDimitry Andric   Type *ResTy = inferScalarType(R->getIncomingValue(0));
22b1c73532SDimitry Andric   for (unsigned I = 1, E = R->getNumIncomingValues(); I != E; ++I) {
23b1c73532SDimitry Andric     VPValue *Inc = R->getIncomingValue(I);
24b1c73532SDimitry Andric     assert(inferScalarType(Inc) == ResTy &&
25b1c73532SDimitry Andric            "different types inferred for different incoming values");
26b1c73532SDimitry Andric     CachedTypes[Inc] = ResTy;
27b1c73532SDimitry Andric   }
28b1c73532SDimitry Andric   return ResTy;
29b1c73532SDimitry Andric }
30b1c73532SDimitry Andric 
inferScalarTypeForRecipe(const VPInstruction * R)31b1c73532SDimitry Andric Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPInstruction *R) {
32ac9a064cSDimitry Andric   // Set the result type from the first operand, check if the types for all
33ac9a064cSDimitry Andric   // other operands match and cache them.
34ac9a064cSDimitry Andric   auto SetResultTyFromOp = [this, R]() {
35ac9a064cSDimitry Andric     Type *ResTy = inferScalarType(R->getOperand(0));
36ac9a064cSDimitry Andric     for (unsigned Op = 1; Op != R->getNumOperands(); ++Op) {
37ac9a064cSDimitry Andric       VPValue *OtherV = R->getOperand(Op);
38ac9a064cSDimitry Andric       assert(inferScalarType(OtherV) == ResTy &&
39ac9a064cSDimitry Andric              "different types inferred for different operands");
40ac9a064cSDimitry Andric       CachedTypes[OtherV] = ResTy;
41ac9a064cSDimitry Andric     }
42ac9a064cSDimitry Andric     return ResTy;
43ac9a064cSDimitry Andric   };
44ac9a064cSDimitry Andric 
45ac9a064cSDimitry Andric   unsigned Opcode = R->getOpcode();
46ac9a064cSDimitry Andric   if (Instruction::isBinaryOp(Opcode) || Instruction::isUnaryOp(Opcode))
47ac9a064cSDimitry Andric     return SetResultTyFromOp();
48ac9a064cSDimitry Andric 
49ac9a064cSDimitry Andric   switch (Opcode) {
50b1c73532SDimitry Andric   case Instruction::Select: {
51b1c73532SDimitry Andric     Type *ResTy = inferScalarType(R->getOperand(1));
52b1c73532SDimitry Andric     VPValue *OtherV = R->getOperand(2);
53b1c73532SDimitry Andric     assert(inferScalarType(OtherV) == ResTy &&
54b1c73532SDimitry Andric            "different types inferred for different operands");
55b1c73532SDimitry Andric     CachedTypes[OtherV] = ResTy;
56b1c73532SDimitry Andric     return ResTy;
57b1c73532SDimitry Andric   }
58ac9a064cSDimitry Andric   case Instruction::ICmp:
59ac9a064cSDimitry Andric   case VPInstruction::ActiveLaneMask:
60ac9a064cSDimitry Andric     return inferScalarType(R->getOperand(1));
61ac9a064cSDimitry Andric   case VPInstruction::FirstOrderRecurrenceSplice:
62ac9a064cSDimitry Andric   case VPInstruction::Not:
63ac9a064cSDimitry Andric     return SetResultTyFromOp();
64ac9a064cSDimitry Andric   case VPInstruction::ExtractFromEnd: {
65ac9a064cSDimitry Andric     Type *BaseTy = inferScalarType(R->getOperand(0));
66ac9a064cSDimitry Andric     if (auto *VecTy = dyn_cast<VectorType>(BaseTy))
67ac9a064cSDimitry Andric       return VecTy->getElementType();
68ac9a064cSDimitry Andric     return BaseTy;
69b1c73532SDimitry Andric   }
70ac9a064cSDimitry Andric   case VPInstruction::LogicalAnd:
71ac9a064cSDimitry Andric     return IntegerType::get(Ctx, 1);
72ac9a064cSDimitry Andric   case VPInstruction::PtrAdd:
73ac9a064cSDimitry Andric     // Return the type based on the pointer argument (i.e. first operand).
74ac9a064cSDimitry Andric     return inferScalarType(R->getOperand(0));
75ac9a064cSDimitry Andric   case VPInstruction::BranchOnCond:
76ac9a064cSDimitry Andric   case VPInstruction::BranchOnCount:
77ac9a064cSDimitry Andric     return Type::getVoidTy(Ctx);
78b1c73532SDimitry Andric   default:
79b1c73532SDimitry Andric     break;
80b1c73532SDimitry Andric   }
81b1c73532SDimitry Andric   // Type inference not implemented for opcode.
82b1c73532SDimitry Andric   LLVM_DEBUG({
83b1c73532SDimitry Andric     dbgs() << "LV: Found unhandled opcode for: ";
84b1c73532SDimitry Andric     R->getVPSingleValue()->dump();
85b1c73532SDimitry Andric   });
86b1c73532SDimitry Andric   llvm_unreachable("Unhandled opcode!");
87b1c73532SDimitry Andric }
88b1c73532SDimitry Andric 
inferScalarTypeForRecipe(const VPWidenRecipe * R)89b1c73532SDimitry Andric Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenRecipe *R) {
90b1c73532SDimitry Andric   unsigned Opcode = R->getOpcode();
91b1c73532SDimitry Andric   switch (Opcode) {
92b1c73532SDimitry Andric   case Instruction::ICmp:
93b1c73532SDimitry Andric   case Instruction::FCmp:
94b1c73532SDimitry Andric     return IntegerType::get(Ctx, 1);
95b1c73532SDimitry Andric   case Instruction::UDiv:
96b1c73532SDimitry Andric   case Instruction::SDiv:
97b1c73532SDimitry Andric   case Instruction::SRem:
98b1c73532SDimitry Andric   case Instruction::URem:
99b1c73532SDimitry Andric   case Instruction::Add:
100b1c73532SDimitry Andric   case Instruction::FAdd:
101b1c73532SDimitry Andric   case Instruction::Sub:
102b1c73532SDimitry Andric   case Instruction::FSub:
103b1c73532SDimitry Andric   case Instruction::Mul:
104b1c73532SDimitry Andric   case Instruction::FMul:
105b1c73532SDimitry Andric   case Instruction::FDiv:
106b1c73532SDimitry Andric   case Instruction::FRem:
107b1c73532SDimitry Andric   case Instruction::Shl:
108b1c73532SDimitry Andric   case Instruction::LShr:
109b1c73532SDimitry Andric   case Instruction::AShr:
110b1c73532SDimitry Andric   case Instruction::And:
111b1c73532SDimitry Andric   case Instruction::Or:
112b1c73532SDimitry Andric   case Instruction::Xor: {
113b1c73532SDimitry Andric     Type *ResTy = inferScalarType(R->getOperand(0));
114b1c73532SDimitry Andric     assert(ResTy == inferScalarType(R->getOperand(1)) &&
115b1c73532SDimitry Andric            "types for both operands must match for binary op");
116b1c73532SDimitry Andric     CachedTypes[R->getOperand(1)] = ResTy;
117b1c73532SDimitry Andric     return ResTy;
118b1c73532SDimitry Andric   }
119b1c73532SDimitry Andric   case Instruction::FNeg:
120b1c73532SDimitry Andric   case Instruction::Freeze:
121b1c73532SDimitry Andric     return inferScalarType(R->getOperand(0));
122b1c73532SDimitry Andric   default:
123b1c73532SDimitry Andric     break;
124b1c73532SDimitry Andric   }
125b1c73532SDimitry Andric 
126b1c73532SDimitry Andric   // Type inference not implemented for opcode.
127b1c73532SDimitry Andric   LLVM_DEBUG({
128b1c73532SDimitry Andric     dbgs() << "LV: Found unhandled opcode for: ";
129b1c73532SDimitry Andric     R->getVPSingleValue()->dump();
130b1c73532SDimitry Andric   });
131b1c73532SDimitry Andric   llvm_unreachable("Unhandled opcode!");
132b1c73532SDimitry Andric }
133b1c73532SDimitry Andric 
inferScalarTypeForRecipe(const VPWidenCallRecipe * R)134b1c73532SDimitry Andric Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenCallRecipe *R) {
135b1c73532SDimitry Andric   auto &CI = *cast<CallInst>(R->getUnderlyingInstr());
136b1c73532SDimitry Andric   return CI.getType();
137b1c73532SDimitry Andric }
138b1c73532SDimitry Andric 
inferScalarTypeForRecipe(const VPWidenMemoryRecipe * R)139ac9a064cSDimitry Andric Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenMemoryRecipe *R) {
140ac9a064cSDimitry Andric   assert((isa<VPWidenLoadRecipe>(R) || isa<VPWidenLoadEVLRecipe>(R)) &&
141ac9a064cSDimitry Andric          "Store recipes should not define any values");
142b1c73532SDimitry Andric   return cast<LoadInst>(&R->getIngredient())->getType();
143b1c73532SDimitry Andric }
144b1c73532SDimitry Andric 
inferScalarTypeForRecipe(const VPWidenSelectRecipe * R)145b1c73532SDimitry Andric Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPWidenSelectRecipe *R) {
146b1c73532SDimitry Andric   Type *ResTy = inferScalarType(R->getOperand(1));
147b1c73532SDimitry Andric   VPValue *OtherV = R->getOperand(2);
148b1c73532SDimitry Andric   assert(inferScalarType(OtherV) == ResTy &&
149b1c73532SDimitry Andric          "different types inferred for different operands");
150b1c73532SDimitry Andric   CachedTypes[OtherV] = ResTy;
151b1c73532SDimitry Andric   return ResTy;
152b1c73532SDimitry Andric }
153b1c73532SDimitry Andric 
inferScalarTypeForRecipe(const VPReplicateRecipe * R)154b1c73532SDimitry Andric Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPReplicateRecipe *R) {
155b1c73532SDimitry Andric   switch (R->getUnderlyingInstr()->getOpcode()) {
156b1c73532SDimitry Andric   case Instruction::Call: {
157b1c73532SDimitry Andric     unsigned CallIdx = R->getNumOperands() - (R->isPredicated() ? 2 : 1);
158b1c73532SDimitry Andric     return cast<Function>(R->getOperand(CallIdx)->getLiveInIRValue())
159b1c73532SDimitry Andric         ->getReturnType();
160b1c73532SDimitry Andric   }
161b1c73532SDimitry Andric   case Instruction::UDiv:
162b1c73532SDimitry Andric   case Instruction::SDiv:
163b1c73532SDimitry Andric   case Instruction::SRem:
164b1c73532SDimitry Andric   case Instruction::URem:
165b1c73532SDimitry Andric   case Instruction::Add:
166b1c73532SDimitry Andric   case Instruction::FAdd:
167b1c73532SDimitry Andric   case Instruction::Sub:
168b1c73532SDimitry Andric   case Instruction::FSub:
169b1c73532SDimitry Andric   case Instruction::Mul:
170b1c73532SDimitry Andric   case Instruction::FMul:
171b1c73532SDimitry Andric   case Instruction::FDiv:
172b1c73532SDimitry Andric   case Instruction::FRem:
173b1c73532SDimitry Andric   case Instruction::Shl:
174b1c73532SDimitry Andric   case Instruction::LShr:
175b1c73532SDimitry Andric   case Instruction::AShr:
176b1c73532SDimitry Andric   case Instruction::And:
177b1c73532SDimitry Andric   case Instruction::Or:
178b1c73532SDimitry Andric   case Instruction::Xor: {
179b1c73532SDimitry Andric     Type *ResTy = inferScalarType(R->getOperand(0));
180b1c73532SDimitry Andric     assert(ResTy == inferScalarType(R->getOperand(1)) &&
181b1c73532SDimitry Andric            "inferred types for operands of binary op don't match");
182b1c73532SDimitry Andric     CachedTypes[R->getOperand(1)] = ResTy;
183b1c73532SDimitry Andric     return ResTy;
184b1c73532SDimitry Andric   }
185b1c73532SDimitry Andric   case Instruction::Select: {
186b1c73532SDimitry Andric     Type *ResTy = inferScalarType(R->getOperand(1));
187b1c73532SDimitry Andric     assert(ResTy == inferScalarType(R->getOperand(2)) &&
188b1c73532SDimitry Andric            "inferred types for operands of select op don't match");
189b1c73532SDimitry Andric     CachedTypes[R->getOperand(2)] = ResTy;
190b1c73532SDimitry Andric     return ResTy;
191b1c73532SDimitry Andric   }
192b1c73532SDimitry Andric   case Instruction::ICmp:
193b1c73532SDimitry Andric   case Instruction::FCmp:
194b1c73532SDimitry Andric     return IntegerType::get(Ctx, 1);
195ac9a064cSDimitry Andric   case Instruction::AddrSpaceCast:
196b1c73532SDimitry Andric   case Instruction::Alloca:
197b1c73532SDimitry Andric   case Instruction::BitCast:
198b1c73532SDimitry Andric   case Instruction::Trunc:
199b1c73532SDimitry Andric   case Instruction::SExt:
200b1c73532SDimitry Andric   case Instruction::ZExt:
201b1c73532SDimitry Andric   case Instruction::FPExt:
202b1c73532SDimitry Andric   case Instruction::FPTrunc:
203b1c73532SDimitry Andric   case Instruction::ExtractValue:
204b1c73532SDimitry Andric   case Instruction::SIToFP:
205b1c73532SDimitry Andric   case Instruction::UIToFP:
206b1c73532SDimitry Andric   case Instruction::FPToSI:
207b1c73532SDimitry Andric   case Instruction::FPToUI:
208b1c73532SDimitry Andric   case Instruction::PtrToInt:
209b1c73532SDimitry Andric   case Instruction::IntToPtr:
210b1c73532SDimitry Andric     return R->getUnderlyingInstr()->getType();
211b1c73532SDimitry Andric   case Instruction::Freeze:
212b1c73532SDimitry Andric   case Instruction::FNeg:
213b1c73532SDimitry Andric   case Instruction::GetElementPtr:
214b1c73532SDimitry Andric     return inferScalarType(R->getOperand(0));
215b1c73532SDimitry Andric   case Instruction::Load:
216b1c73532SDimitry Andric     return cast<LoadInst>(R->getUnderlyingInstr())->getType();
217b1c73532SDimitry Andric   case Instruction::Store:
218b1c73532SDimitry Andric     // FIXME: VPReplicateRecipes with store opcodes still define a result
219b1c73532SDimitry Andric     // VPValue, so we need to handle them here. Remove the code here once this
220b1c73532SDimitry Andric     // is modeled accurately in VPlan.
221b1c73532SDimitry Andric     return Type::getVoidTy(Ctx);
222b1c73532SDimitry Andric   default:
223b1c73532SDimitry Andric     break;
224b1c73532SDimitry Andric   }
225b1c73532SDimitry Andric   // Type inference not implemented for opcode.
226b1c73532SDimitry Andric   LLVM_DEBUG({
227b1c73532SDimitry Andric     dbgs() << "LV: Found unhandled opcode for: ";
228b1c73532SDimitry Andric     R->getVPSingleValue()->dump();
229b1c73532SDimitry Andric   });
230b1c73532SDimitry Andric   llvm_unreachable("Unhandled opcode");
231b1c73532SDimitry Andric }
232b1c73532SDimitry Andric 
inferScalarType(const VPValue * V)233b1c73532SDimitry Andric Type *VPTypeAnalysis::inferScalarType(const VPValue *V) {
234b1c73532SDimitry Andric   if (Type *CachedTy = CachedTypes.lookup(V))
235b1c73532SDimitry Andric     return CachedTy;
236b1c73532SDimitry Andric 
237ac9a064cSDimitry Andric   if (V->isLiveIn()) {
238ac9a064cSDimitry Andric     if (auto *IRValue = V->getLiveInIRValue())
239ac9a064cSDimitry Andric       return IRValue->getType();
240ac9a064cSDimitry Andric     // All VPValues without any underlying IR value (like the vector trip count
241ac9a064cSDimitry Andric     // or the backedge-taken count) have the same type as the canonical IV.
242ac9a064cSDimitry Andric     return CanonicalIVTy;
243ac9a064cSDimitry Andric   }
244b1c73532SDimitry Andric 
245b1c73532SDimitry Andric   Type *ResultTy =
246b1c73532SDimitry Andric       TypeSwitch<const VPRecipeBase *, Type *>(V->getDefiningRecipe())
247ac9a064cSDimitry Andric           .Case<VPActiveLaneMaskPHIRecipe, VPCanonicalIVPHIRecipe,
248ac9a064cSDimitry Andric                 VPFirstOrderRecurrencePHIRecipe, VPReductionPHIRecipe,
249ac9a064cSDimitry Andric                 VPWidenPointerInductionRecipe, VPEVLBasedIVPHIRecipe>(
250b1c73532SDimitry Andric               [this](const auto *R) {
251ac9a064cSDimitry Andric                 // Handle header phi recipes, except VPWidenIntOrFpInduction
252b1c73532SDimitry Andric                 // which needs special handling due it being possibly truncated.
253b1c73532SDimitry Andric                 // TODO: consider inferring/caching type of siblings, e.g.,
254b1c73532SDimitry Andric                 // backedge value, here and in cases below.
255b1c73532SDimitry Andric                 return inferScalarType(R->getStartValue());
256b1c73532SDimitry Andric               })
257b1c73532SDimitry Andric           .Case<VPWidenIntOrFpInductionRecipe, VPDerivedIVRecipe>(
258b1c73532SDimitry Andric               [](const auto *R) { return R->getScalarType(); })
259ac9a064cSDimitry Andric           .Case<VPReductionRecipe, VPPredInstPHIRecipe, VPWidenPHIRecipe,
260ac9a064cSDimitry Andric                 VPScalarIVStepsRecipe, VPWidenGEPRecipe, VPVectorPointerRecipe,
261ac9a064cSDimitry Andric                 VPWidenCanonicalIVRecipe>([this](const VPRecipeBase *R) {
262b1c73532SDimitry Andric             return inferScalarType(R->getOperand(0));
263b1c73532SDimitry Andric           })
264b1c73532SDimitry Andric           .Case<VPBlendRecipe, VPInstruction, VPWidenRecipe, VPReplicateRecipe,
265ac9a064cSDimitry Andric                 VPWidenCallRecipe, VPWidenMemoryRecipe, VPWidenSelectRecipe>(
266b1c73532SDimitry Andric               [this](const auto *R) { return inferScalarTypeForRecipe(R); })
267b1c73532SDimitry Andric           .Case<VPInterleaveRecipe>([V](const VPInterleaveRecipe *R) {
268b1c73532SDimitry Andric             // TODO: Use info from interleave group.
269b1c73532SDimitry Andric             return V->getUnderlyingValue()->getType();
270b1c73532SDimitry Andric           })
271b1c73532SDimitry Andric           .Case<VPWidenCastRecipe>(
272ac9a064cSDimitry Andric               [](const VPWidenCastRecipe *R) { return R->getResultType(); })
273ac9a064cSDimitry Andric           .Case<VPScalarCastRecipe>(
274ac9a064cSDimitry Andric               [](const VPScalarCastRecipe *R) { return R->getResultType(); })
275ac9a064cSDimitry Andric           .Case<VPExpandSCEVRecipe>([](const VPExpandSCEVRecipe *R) {
276ac9a064cSDimitry Andric             return R->getSCEV()->getType();
277ac9a064cSDimitry Andric           })
278ac9a064cSDimitry Andric           .Case<VPReductionRecipe>([this](const auto *R) {
279ac9a064cSDimitry Andric             return inferScalarType(R->getChainOp());
280ac9a064cSDimitry Andric           });
281ac9a064cSDimitry Andric 
282b1c73532SDimitry Andric   assert(ResultTy && "could not infer type for the given VPValue");
283b1c73532SDimitry Andric   CachedTypes[V] = ResultTy;
284b1c73532SDimitry Andric   return ResultTy;
285b1c73532SDimitry Andric }
286ac9a064cSDimitry Andric 
collectEphemeralRecipesForVPlan(VPlan & Plan,DenseSet<VPRecipeBase * > & EphRecipes)287ac9a064cSDimitry Andric void llvm::collectEphemeralRecipesForVPlan(
288ac9a064cSDimitry Andric     VPlan &Plan, DenseSet<VPRecipeBase *> &EphRecipes) {
289ac9a064cSDimitry Andric   // First, collect seed recipes which are operands of assumes.
290ac9a064cSDimitry Andric   SmallVector<VPRecipeBase *> Worklist;
291ac9a064cSDimitry Andric   for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
292ac9a064cSDimitry Andric            vp_depth_first_deep(Plan.getVectorLoopRegion()->getEntry()))) {
293ac9a064cSDimitry Andric     for (VPRecipeBase &R : *VPBB) {
294ac9a064cSDimitry Andric       auto *RepR = dyn_cast<VPReplicateRecipe>(&R);
295ac9a064cSDimitry Andric       if (!RepR || !match(RepR->getUnderlyingInstr(),
296ac9a064cSDimitry Andric                           PatternMatch::m_Intrinsic<Intrinsic::assume>()))
297ac9a064cSDimitry Andric         continue;
298ac9a064cSDimitry Andric       Worklist.push_back(RepR);
299ac9a064cSDimitry Andric       EphRecipes.insert(RepR);
300ac9a064cSDimitry Andric     }
301ac9a064cSDimitry Andric   }
302ac9a064cSDimitry Andric 
303ac9a064cSDimitry Andric   // Process operands of candidates in worklist and add them to the set of
304ac9a064cSDimitry Andric   // ephemeral recipes, if they don't have side-effects and are only used by
305ac9a064cSDimitry Andric   // other ephemeral recipes.
306ac9a064cSDimitry Andric   while (!Worklist.empty()) {
307ac9a064cSDimitry Andric     VPRecipeBase *Cur = Worklist.pop_back_val();
308ac9a064cSDimitry Andric     for (VPValue *Op : Cur->operands()) {
309ac9a064cSDimitry Andric       auto *OpR = Op->getDefiningRecipe();
310ac9a064cSDimitry Andric       if (!OpR || OpR->mayHaveSideEffects() || EphRecipes.contains(OpR))
311ac9a064cSDimitry Andric         continue;
312ac9a064cSDimitry Andric       if (any_of(Op->users(), [EphRecipes](VPUser *U) {
313ac9a064cSDimitry Andric             auto *UR = dyn_cast<VPRecipeBase>(U);
314ac9a064cSDimitry Andric             return !UR || !EphRecipes.contains(UR);
315ac9a064cSDimitry Andric           }))
316ac9a064cSDimitry Andric         continue;
317ac9a064cSDimitry Andric       EphRecipes.insert(OpR);
318ac9a064cSDimitry Andric       Worklist.push_back(OpR);
319ac9a064cSDimitry Andric     }
320ac9a064cSDimitry Andric   }
321ac9a064cSDimitry Andric }
322