LLVM 22.0.0git
VPlanVerifier.cpp
Go to the documentation of this file.
1//===-- VPlanVerifier.cpp -------------------------------------------------===//
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/// \file
10/// This file defines the class VPlanVerifier, which contains utility functions
11/// to check the consistency and invariants of a VPlan.
12///
13//===----------------------------------------------------------------------===//
14
15#include "VPlanVerifier.h"
16#include "VPlan.h"
17#include "VPlanCFG.h"
18#include "VPlanDominatorTree.h"
19#include "VPlanHelpers.h"
20#include "VPlanPatternMatch.h"
22#include "llvm/ADT/TypeSwitch.h"
23
24#define DEBUG_TYPE "loop-vectorize"
25
26using namespace llvm;
27
28namespace {
29class VPlanVerifier {
30 const VPDominatorTree &VPDT;
31 VPTypeAnalysis &TypeInfo;
32 bool VerifyLate;
33
35
36 // Verify that phi-like recipes are at the beginning of \p VPBB, with no
37 // other recipes in between. Also check that only header blocks contain
38 // VPHeaderPHIRecipes.
39 bool verifyPhiRecipes(const VPBasicBlock *VPBB);
40
41 /// Verify that \p EVL is used correctly. The user must be either in
42 /// EVL-based recipes as a last operand or VPInstruction::Add which is
43 /// incoming value into EVL's recipe.
44 bool verifyEVLRecipe(const VPInstruction &EVL) const;
45
46 bool verifyVPBasicBlock(const VPBasicBlock *VPBB);
47
48 bool verifyBlock(const VPBlockBase *VPB);
49
50 /// Helper function that verifies the CFG invariants of the VPBlockBases
51 /// within
52 /// \p Region. Checks in this function are generic for VPBlockBases. They are
53 /// not specific for VPBasicBlocks or VPRegionBlocks.
54 bool verifyBlocksInRegion(const VPRegionBlock *Region);
55
56 /// Verify the CFG invariants of VPRegionBlock \p Region and its nested
57 /// VPBlockBases. Do not recurse inside nested VPRegionBlocks.
58 bool verifyRegion(const VPRegionBlock *Region);
59
60 /// Verify the CFG invariants of VPRegionBlock \p Region and its nested
61 /// VPBlockBases. Recurse inside nested VPRegionBlocks.
62 bool verifyRegionRec(const VPRegionBlock *Region);
63
64public:
65 VPlanVerifier(VPDominatorTree &VPDT, VPTypeAnalysis &TypeInfo,
66 bool VerifyLate)
67 : VPDT(VPDT), TypeInfo(TypeInfo), VerifyLate(VerifyLate) {}
68
69 bool verify(const VPlan &Plan);
70};
71} // namespace
72
73bool VPlanVerifier::verifyPhiRecipes(const VPBasicBlock *VPBB) {
74 auto RecipeI = VPBB->begin();
75 auto End = VPBB->end();
76 unsigned NumActiveLaneMaskPhiRecipes = 0;
77 bool IsHeaderVPBB = VPBlockUtils::isHeader(VPBB, VPDT);
78 while (RecipeI != End && RecipeI->isPhi()) {
80 NumActiveLaneMaskPhiRecipes++;
81
82 if (IsHeaderVPBB &&
84 errs() << "Found non-header PHI recipe in header VPBB";
85#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
86 errs() << ": ";
87 RecipeI->dump();
88#endif
89 return false;
90 }
91
92 if (!IsHeaderVPBB && isa<VPHeaderPHIRecipe>(*RecipeI)) {
93 errs() << "Found header PHI recipe in non-header VPBB";
94#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
95 errs() << ": ";
96 RecipeI->dump();
97#endif
98 return false;
99 }
100
101 // Check if the recipe operands match the number of predecessors.
102 // TODO Extend to other phi-like recipes.
103 if (auto *PhiIRI = dyn_cast<VPIRPhi>(&*RecipeI)) {
104 if (PhiIRI->getNumOperands() != VPBB->getNumPredecessors()) {
105 errs() << "Phi-like recipe with different number of operands and "
106 "predecessors.\n";
107 // TODO: Print broken recipe. At the moment printing an ill-formed
108 // phi-like recipe may crash.
109 return false;
110 }
111 }
112
113 RecipeI++;
114 }
115
116 if (!VerifyLate && NumActiveLaneMaskPhiRecipes > 1) {
117 errs() << "There should be no more than one VPActiveLaneMaskPHIRecipe";
118 return false;
119 }
120
121 while (RecipeI != End) {
122 if (RecipeI->isPhi() && !isa<VPBlendRecipe>(&*RecipeI)) {
123 errs() << "Found phi-like recipe after non-phi recipe";
124
125#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
126 errs() << ": ";
127 RecipeI->dump();
128 errs() << "after\n";
129 std::prev(RecipeI)->dump();
130#endif
131 return false;
132 }
133 RecipeI++;
134 }
135 return true;
136}
137
138bool VPlanVerifier::verifyEVLRecipe(const VPInstruction &EVL) const {
140 errs() << "verifyEVLRecipe should only be called on "
141 "VPInstruction::ExplicitVectorLength\n";
142 return false;
143 }
144 auto VerifyEVLUse = [&](const VPRecipeBase &R,
145 const unsigned ExpectedIdx) -> bool {
147 unsigned UseCount = count(Ops, &EVL);
148 if (UseCount != 1 || Ops[ExpectedIdx] != &EVL) {
149 errs() << "EVL is used as non-last operand in EVL-based recipe\n";
150 return false;
151 }
152 return true;
153 };
154 return all_of(EVL.users(), [this, &VerifyEVLUse](VPUser *U) {
155 return TypeSwitch<const VPUser *, bool>(U)
156 .Case<VPWidenIntrinsicRecipe>([&](const VPWidenIntrinsicRecipe *S) {
157 return VerifyEVLUse(*S, S->getNumOperands() - 1);
158 })
159 .Case<VPWidenStoreEVLRecipe, VPReductionEVLRecipe,
160 VPWidenIntOrFpInductionRecipe, VPWidenPointerInductionRecipe>(
161 [&](const VPRecipeBase *S) { return VerifyEVLUse(*S, 2); })
162 .Case<VPScalarIVStepsRecipe>([&](auto *R) {
163 if (R->getNumOperands() != 3) {
164 errs() << "Unrolling with EVL tail folding not yet supported\n";
165 return false;
166 }
167 return VerifyEVLUse(*R, 2);
168 })
169 .Case<VPWidenLoadEVLRecipe, VPVectorEndPointerRecipe,
170 VPInterleaveEVLRecipe>(
171 [&](const VPRecipeBase *R) { return VerifyEVLUse(*R, 1); })
172 .Case<VPInstructionWithType>(
173 [&](const VPInstructionWithType *S) { return VerifyEVLUse(*S, 0); })
174 .Case<VPInstruction>([&](const VPInstruction *I) {
175 if (I->getOpcode() == Instruction::PHI ||
176 I->getOpcode() == Instruction::ICmp ||
177 I->getOpcode() == Instruction::Sub)
178 return VerifyEVLUse(*I, 1);
179 switch (I->getOpcode()) {
180 case Instruction::Add:
181 break;
182 case Instruction::UIToFP:
183 case Instruction::Trunc:
184 case Instruction::ZExt:
185 case Instruction::Mul:
186 case Instruction::FMul:
188 // Opcodes above can only use EVL after wide inductions have been
189 // expanded.
190 if (!VerifyLate) {
191 errs() << "EVL used by unexpected VPInstruction\n";
192 return false;
193 }
194 break;
195 default:
196 errs() << "EVL used by unexpected VPInstruction\n";
197 return false;
198 }
199 // EVLIVIncrement is only used by EVLIV & BranchOnCount.
200 // Having more than two users is unexpected.
201 using namespace llvm::VPlanPatternMatch;
202 if (I->getOpcode() != VPInstruction::Broadcast &&
203 I->getNumUsers() != 1 &&
204 (I->getNumUsers() != 2 ||
206 m_VPValue()))))) {
207 errs() << "EVL is used in VPInstruction with multiple users\n";
208 return false;
209 }
210 if (!VerifyLate && !isa<VPEVLBasedIVPHIRecipe>(*I->users().begin())) {
211 errs() << "Result of VPInstruction::Add with EVL operand is "
212 "not used by VPEVLBasedIVPHIRecipe\n";
213 return false;
214 }
215 return true;
216 })
217 .Default([&](const VPUser *U) {
218 errs() << "EVL has unexpected user\n";
219 return false;
220 });
221 });
222}
223
224bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) {
225 if (!verifyPhiRecipes(VPBB))
226 return false;
227
228 // Verify that defs in VPBB dominate all their uses.
229 DenseMap<const VPRecipeBase *, unsigned> RecipeNumbering;
230 unsigned Cnt = 0;
231 for (const VPRecipeBase &R : *VPBB)
232 RecipeNumbering[&R] = Cnt++;
233
234 for (const VPRecipeBase &R : *VPBB) {
235 if (isa<VPIRInstruction>(&R) && !isa<VPIRBasicBlock>(VPBB)) {
236 errs() << "VPIRInstructions ";
237#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
238 R.dump();
239 errs() << " ";
240#endif
241 errs() << "not in a VPIRBasicBlock!\n";
242 return false;
243 }
244 for (const VPValue *V : R.definedValues()) {
245 // Verify that we can infer a scalar type for each defined value. With
246 // assertions enabled, inferScalarType will perform some consistency
247 // checks during type inference.
248 if (!TypeInfo.inferScalarType(V)) {
249 errs() << "Failed to infer scalar type!\n";
250 return false;
251 }
252
253 for (const VPUser *U : V->users()) {
254 auto *UI = cast<VPRecipeBase>(U);
255 if (auto *Phi = dyn_cast<VPPhiAccessors>(UI)) {
256 for (const auto &[IncomingVPV, IncomingVPBB] :
257 Phi->incoming_values_and_blocks()) {
258 if (IncomingVPV != V)
259 continue;
260
261 if (VPDT.dominates(VPBB, IncomingVPBB))
262 continue;
263
264 errs() << "Incoming def does not dominate incoming block!\n";
265#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
266 VPSlotTracker Tracker(VPBB->getPlan());
267 IncomingVPV->getDefiningRecipe()->print(errs(), " ", Tracker);
268 errs() << "\n does not dominate " << IncomingVPBB->getName()
269 << " for\n";
270 UI->print(errs(), " ", Tracker);
271#endif
272 return false;
273 }
274 continue;
275 }
276 // TODO: Also verify VPPredInstPHIRecipe.
278 continue;
279
280 // If the user is in the same block, check it comes after R in the
281 // block.
282 if (UI->getParent() == VPBB) {
283 if (RecipeNumbering[UI] >= RecipeNumbering[&R])
284 continue;
285 } else {
286 if (VPDT.dominates(VPBB, UI->getParent()))
287 continue;
288 }
289
290 errs() << "Use before def!\n";
291#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
292 VPSlotTracker Tracker(VPBB->getPlan());
293 UI->print(errs(), " ", Tracker);
294 errs() << "\n before\n";
295 R.print(errs(), " ", Tracker);
296 errs() << "\n";
297#endif
298 return false;
299 }
300 }
301 if (const auto *EVL = dyn_cast<VPInstruction>(&R)) {
303 !verifyEVLRecipe(*EVL)) {
304 errs() << "EVL VPValue is not used correctly\n";
305 return false;
306 }
307 }
308 }
309
310 auto *IRBB = dyn_cast<VPIRBasicBlock>(VPBB);
311 if (!IRBB)
312 return true;
313
314 if (!WrappedIRBBs.insert(IRBB->getIRBasicBlock()).second) {
315 errs() << "Same IR basic block used by multiple wrapper blocks!\n";
316 return false;
317 }
318
319 return true;
320}
321
322/// Utility function that checks whether \p VPBlockVec has duplicate
323/// VPBlockBases.
324static bool hasDuplicates(const SmallVectorImpl<VPBlockBase *> &VPBlockVec) {
326 for (const auto *Block : VPBlockVec) {
327 if (!VPBlockSet.insert(Block).second)
328 return true;
329 }
330 return false;
331}
332
333bool VPlanVerifier::verifyBlock(const VPBlockBase *VPB) {
334 auto *VPBB = dyn_cast<VPBasicBlock>(VPB);
335 // Check block's condition bit.
336 if (!isa<VPIRBasicBlock>(VPB)) {
337 if (VPB->getNumSuccessors() > 1 ||
338 (VPBB && VPBB->getParent() && VPBB->isExiting() &&
339 !VPBB->getParent()->isReplicator())) {
340 if (!VPBB || !VPBB->getTerminator()) {
341 errs() << "Block has multiple successors but doesn't "
342 "have a proper branch recipe!\n";
343 return false;
344 }
345 } else {
346 if (VPBB && VPBB->getTerminator()) {
347 errs() << "Unexpected branch recipe!\n";
348 return false;
349 }
350 }
351 }
352
353 // Check block's successors.
354 const auto &Successors = VPB->getSuccessors();
355 // There must be only one instance of a successor in block's successor list.
356 // TODO: This won't work for switch statements.
357 if (hasDuplicates(Successors)) {
358 errs() << "Multiple instances of the same successor.\n";
359 return false;
360 }
361
362 for (const VPBlockBase *Succ : Successors) {
363 // There must be a bi-directional link between block and successor.
364 const auto &SuccPreds = Succ->getPredecessors();
365 if (!is_contained(SuccPreds, VPB)) {
366 errs() << "Missing predecessor link.\n";
367 return false;
368 }
369 }
370
371 // Check block's predecessors.
372 const auto &Predecessors = VPB->getPredecessors();
373 // There must be only one instance of a predecessor in block's predecessor
374 // list.
375 // TODO: This won't work for switch statements.
376 if (hasDuplicates(Predecessors)) {
377 errs() << "Multiple instances of the same predecessor.\n";
378 return false;
379 }
380
381 for (const VPBlockBase *Pred : Predecessors) {
382 // Block and predecessor must be inside the same region.
383 if (Pred->getParent() != VPB->getParent()) {
384 errs() << "Predecessor is not in the same region.\n";
385 return false;
386 }
387
388 // There must be a bi-directional link between block and predecessor.
389 const auto &PredSuccs = Pred->getSuccessors();
390 if (!is_contained(PredSuccs, VPB)) {
391 errs() << "Missing successor link.\n";
392 return false;
393 }
394 }
395 return !VPBB || verifyVPBasicBlock(VPBB);
396}
397
398bool VPlanVerifier::verifyBlocksInRegion(const VPRegionBlock *Region) {
399 for (const VPBlockBase *VPB : vp_depth_first_shallow(Region->getEntry())) {
400 // Check block's parent.
401 if (VPB->getParent() != Region) {
402 errs() << "VPBlockBase has wrong parent\n";
403 return false;
404 }
405
406 if (!verifyBlock(VPB))
407 return false;
408 }
409 return true;
410}
411
412bool VPlanVerifier::verifyRegion(const VPRegionBlock *Region) {
413 const VPBlockBase *Entry = Region->getEntry();
414 const VPBlockBase *Exiting = Region->getExiting();
415
416 // Entry and Exiting shouldn't have any predecessor/successor, respectively.
417 if (Entry->hasPredecessors()) {
418 errs() << "region entry block has predecessors\n";
419 return false;
420 }
421 if (Exiting->getNumSuccessors() != 0) {
422 errs() << "region exiting block has successors\n";
423 return false;
424 }
425
426 return verifyBlocksInRegion(Region);
427}
428
429bool VPlanVerifier::verifyRegionRec(const VPRegionBlock *Region) {
430 // Recurse inside nested regions and check all blocks inside the region.
431 return verifyRegion(Region) &&
433 [this](const VPBlockBase *VPB) {
434 const auto *SubRegion = dyn_cast<VPRegionBlock>(VPB);
435 return !SubRegion || verifyRegionRec(SubRegion);
436 });
437}
438
439bool VPlanVerifier::verify(const VPlan &Plan) {
441 [this](const VPBlockBase *VPB) { return !verifyBlock(VPB); }))
442 return false;
443
444 const VPRegionBlock *TopRegion = Plan.getVectorLoopRegion();
445 // TODO: Verify all blocks using vp_depth_first_deep iterators.
446 if (!TopRegion)
447 return true;
448
449 if (!verifyRegionRec(TopRegion))
450 return false;
451
452 if (TopRegion->getParent()) {
453 errs() << "VPlan Top Region should have no parent.\n";
454 return false;
455 }
456
457 const VPBasicBlock *Entry = dyn_cast<VPBasicBlock>(TopRegion->getEntry());
458 if (!Entry) {
459 errs() << "VPlan entry block is not a VPBasicBlock\n";
460 return false;
461 }
462
463 if (!isa<VPCanonicalIVPHIRecipe>(&*Entry->begin())) {
464 errs() << "VPlan vector loop header does not start with a "
465 "VPCanonicalIVPHIRecipe\n";
466 return false;
467 }
468
469 const VPBasicBlock *Exiting = dyn_cast<VPBasicBlock>(TopRegion->getExiting());
470 if (!Exiting) {
471 errs() << "VPlan exiting block is not a VPBasicBlock\n";
472 return false;
473 }
474
475 if (Exiting->empty()) {
476 errs() << "VPlan vector loop exiting block must end with BranchOnCount or "
477 "BranchOnCond VPInstruction but is empty\n";
478 return false;
479 }
480
481 auto *LastInst = dyn_cast<VPInstruction>(std::prev(Exiting->end()));
482 if (!LastInst || (LastInst->getOpcode() != VPInstruction::BranchOnCount &&
483 LastInst->getOpcode() != VPInstruction::BranchOnCond)) {
484 errs() << "VPlan vector loop exit must end with BranchOnCount or "
485 "BranchOnCond VPInstruction\n";
486 return false;
487 }
488
489 return true;
490}
491
492bool llvm::verifyVPlanIsValid(const VPlan &Plan, bool VerifyLate) {
493 VPDominatorTree VPDT;
494 VPDT.recalculate(const_cast<VPlan &>(Plan));
495 VPTypeAnalysis TypeInfo(Plan);
496 VPlanVerifier Verifier(VPDT, TypeInfo, VerifyLate);
497 return Verifier.verify(Plan);
498}
@ Default
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define I(x, y, z)
Definition MD5.cpp:58
ppc ctr loops verify
verify safepoint Safepoint IR Verifier
This file defines the SmallPtrSet class.
This file implements the TypeSwitch template, which mimics a switch() statement whose cases are type ...
This file implements dominator tree analysis for a single level of a VPlan's H-CFG.
This file contains the declarations of different VPlan-related auxiliary helpers.
static bool hasDuplicates(const SmallVectorImpl< VPBlockBase * > &VPBlockVec)
Utility function that checks whether VPBlockVec has duplicate VPBlockBases.
This file declares the class VPlanVerifier, which contains utility functions to check the consistency...
This file contains the declarations of the Vectorization Plan base classes:
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition DenseSet.h:291
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
Definition VPlan.h:3786
iterator end()
Definition VPlan.h:3823
iterator begin()
Recipe iterator methods.
Definition VPlan.h:3821
bool empty() const
Definition VPlan.h:3832
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition VPlan.h:82
VPRegionBlock * getParent()
Definition VPlan.h:174
size_t getNumSuccessors() const
Definition VPlan.h:220
size_t getNumPredecessors() const
Definition VPlan.h:221
const VPBlocksTy & getPredecessors() const
Definition VPlan.h:205
const VPBlocksTy & getSuccessors() const
Definition VPlan.h:199
static bool isHeader(const VPBlockBase *VPB, const VPDominatorTree &VPDT)
Returns true if VPB is a loop header, based on regions or VPDT in their absence.
Definition VPlan.cpp:220
Template specialization of the standard LLVM dominator tree utility for VPBlockBases.
This is a concrete Recipe that models a single VPlan-level instruction.
Definition VPlan.h:984
unsigned getOpcode() const
Definition VPlan.h:1120
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition VPlan.h:3974
const VPBlockBase * getEntry() const
Definition VPlan.h:4010
const VPBlockBase * getExiting() const
Definition VPlan.h:4022
An analysis for type-inference for VPValues.
Type * inferScalarType(const VPValue *V)
Infer the type of V. Returns the scalar type of V.
user_range users()
Definition VPlanValue.h:134
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4077
VPBasicBlock * getEntry()
Definition VPlan.h:4176
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
Definition VPlan.cpp:1049
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:202
@ Entry
Definition COFF.h:862
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
MatchFunctor< Val, Pattern > match_fn(const Pattern &P)
A match functor that can be used as a UnaryPredicate in functional algorithms like all_of.
VPInstruction_match< VPInstruction::BranchOnCount, Op0_t, Op1_t > m_BranchOnCount(const Op0_t &Op0, const Op1_t &Op1)
class_match< VPValue > m_VPValue()
Match an arbitrary VPValue and ignore it.
NodeAddr< PhiNode * > Phi
Definition RDFGraph.h:390
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1705
LLVM_ABI_FOR_TEST bool verifyVPlanIsValid(const VPlan &Plan, bool VerifyLate=false)
Verify invariants for general VPlans.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:644
iterator_range< df_iterator< VPBlockShallowTraversalWrapper< VPBlockBase * > > > vp_depth_first_shallow(VPBlockBase *G)
Returns an iterator range to traverse the graph starting at G in depth-first order.
Definition VPlanCFG.h:216
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1712
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1719
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition STLExtras.h:1934
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:560
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1877