1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 //
10 // Implementation of methods for Region class
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "GenXAlignmentInfo.h"
15 #include "GenXBaling.h"
16 #include "GenXSubtarget.h"
17 #include "GenXUtil.h"
18 #include "vc/GenXOpts/GenXAnalysis.h"
19 
20 #include "llvm/ADT/SmallBitVector.h"
21 #include "llvm/Analysis/ConstantFolding.h"
22 #include "llvm/Analysis/TargetLibraryInfo.h"
23 #include "llvm/Analysis/ValueTracking.h"
24 #include "llvm/IR/Constants.h"
25 #include "llvm/IR/DerivedTypes.h"
26 #include "llvm/IR/Function.h"
27 #include "llvm/IR/Instructions.h"
28 #include "llvm/Support/Debug.h"
29 #include <unordered_map>
30 #include "Probe/Assertion.h"
31 
32 #include "llvmWrapper/IR/DerivedTypes.h"
33 #include "llvmWrapper/Support/TypeSize.h"
34 
35 using namespace llvm;
36 using namespace genx;
37 
38 namespace {
39 
40 /***********************************************************************
41  * Local function for testing one assertion statement.
42  * It returns true if all is ok.
43  * If region index is a vector it should has given number of elements.
44  */
testRegionIndexForSizeMismatch(const llvm::Value * const V,const unsigned & Width,const unsigned & NumElements)45 bool testRegionIndexForSizeMismatch(const llvm::Value *const V,
46   const unsigned& Width, const unsigned& NumElements) {
47 
48   bool Result = true;
49 
50   auto *const VT = dyn_cast<IGCLLVM::FixedVectorType>(V->getType());
51 
52   if (VT) {
53     const unsigned VectorElements = (VT->getNumElements() * Width);
54     Result = (VectorElements == NumElements);
55     IGC_ASSERT_MESSAGE(Result, "vector region index size mismatch");
56   }
57 
58   return Result;
59 }
60 
61 /***********************************************************************
62  * Local function for testing one assertion statement.
63  * It returns true if all is ok.
64  * Instruction 'or' should be changed to 'add' without any errors.
65  */
testOperator(const llvm::Instruction * const Operator)66 bool testOperator(const llvm::Instruction *const Operator) {
67 
68   IGC_ASSERT(Operator);
69   IGC_ASSERT(Operator->getModule());
70 
71   const unsigned Opcode = Operator->getOpcode();
72   const bool IsAdd = (Instruction::Add == Opcode);
73   const bool IsSub = (Instruction::Sub == Opcode);
74   const bool IsOr = (Instruction::Or == Opcode);
75   const bool IsAddAddr =
76     (GenXIntrinsic::genx_add_addr == GenXIntrinsic::getGenXIntrinsicID(Operator));
77 
78   bool Result = (IsAdd || IsSub || IsOr || IsAddAddr);
79   IGC_ASSERT_MESSAGE(Result,
80     "your offset seems to be calculated not through ADD or OR");
81 
82   // check if instruction 'or' could be changed to 'add'
83   if (Result && IsOr) {
84     const llvm::Value *const Op0 = Operator->getOperand(0);
85     const llvm::Value *const Op1 = Operator->getOperand(1);
86     const DataLayout &DL = Operator->getModule()->getDataLayout();
87 
88     Result = llvm::haveNoCommonBitsSet(Op0, Op1, DL);
89     IGC_ASSERT_MESSAGE(Result, "OR should be changed to ADD with no errors");
90   }
91 
92   return Result;
93 }
94 
95 } // namespace
96 
97 
98 /***********************************************************************
99  * makeRegionWithOffset: get a Region given a rdregion/wrregion, baling in
100  * constant add of offset
101  *
102  * This constructs the Region with a variable index that is a constant add
103  * baled in (i.e. Region::Indirect and Region::Offset both set to the
104  * operands of the add). It is for use when baling information is not
105  * available, but the caller wants the constant offset separated out like
106  * that.
107  */
makeRegionWithOffset(Instruction * Inst,bool WantParentWidth)108 Region genx::makeRegionWithOffset(Instruction *Inst, bool WantParentWidth) {
109   unsigned OperandNum = 0;
110   switch (GenXIntrinsic::getGenXIntrinsicID(Inst)) {
111   case GenXIntrinsic::genx_rdregioni:
112   case GenXIntrinsic::genx_rdregionf:
113     OperandNum = GenXIntrinsic::GenXRegion::RdIndexOperandNum;
114     break;
115   case GenXIntrinsic::genx_wrregioni:
116   case GenXIntrinsic::genx_wrregionf:
117   case GenXIntrinsic::genx_wrconstregion:
118     OperandNum = GenXIntrinsic::GenXRegion::WrIndexOperandNum;
119     break;
120   default:
121     IGC_ASSERT_EXIT_MESSAGE(0, "not rdregion or wrregion");
122     break;
123   }
124   BaleInfo BI;
125   if (GenXBaling::isBalableIndexAdd(Inst->getOperand(OperandNum)))
126     BI.setOperandBaled(OperandNum);
127   return makeRegionFromBaleInfo(Inst, BI, WantParentWidth);
128 }
129 
130 /***********************************************************************
131  * Region constructor from a rd/wr region and its BaleInfo
132  * This also works with rdpredregion and wrpredregion, with Offset in
133  * bits rather than bytes, and with ElementBytes set to 1.
134  */
makeRegionFromBaleInfo(Instruction * Inst,const BaleInfo & BI,bool WantParentWidth)135 Region genx::makeRegionFromBaleInfo(Instruction *Inst, const BaleInfo &BI,
136                                     bool WantParentWidth) {
137   Region Result;
138   // Determine where to get the subregion value from and which arg index
139   // the region parameters start at.
140   unsigned ArgIdx = 0;
141   Value *Subregion = 0;
142   IGC_ASSERT(isa<CallInst>(Inst));
143   auto CallI = cast<CallInst>(Inst);
144   IGC_ASSERT(CallI->getCalledFunction());
145   switch (GenXIntrinsic::getGenXIntrinsicID(CallI->getCalledFunction())) {
146     case GenXIntrinsic::genx_rdpredregion:
147       Result.NumElements =
148           cast<IGCLLVM::FixedVectorType>(Inst->getType())->getNumElements();
149       Result.Width = Result.NumElements;
150       Result.Offset = cast<ConstantInt>(Inst->getOperand(1))->getZExtValue();
151       Result.ElementBytes = 1;
152       return Result;
153     case GenXIntrinsic::genx_wrpredregion:
154       Result.NumElements =
155           cast<IGCLLVM::FixedVectorType>(Inst->getOperand(1)->getType())
156               ->getNumElements();
157       Result.Width = Result.NumElements;
158       Result.Offset = cast<ConstantInt>(Inst->getOperand(2))->getZExtValue();
159       Result.ElementBytes = 1;
160       return Result;
161     case GenXIntrinsic::genx_rdregioni:
162     case GenXIntrinsic::genx_rdregionf:
163       ArgIdx = 1;
164       // The size/type of the region is given by the return value:
165       Subregion = Inst;
166       break;
167     case GenXIntrinsic::genx_wrregioni:
168     case GenXIntrinsic::genx_wrregionf:
169     case GenXIntrinsic::genx_wrconstregion:
170       ArgIdx = 2;
171       // The size/type of the region is given by the "subregion value to
172       // write" operand:
173       Subregion = Inst->getOperand(1);
174       // For wrregion, while we're here, also get the mask. We set mask to NULL
175       // if the mask operand is constant 1 (i.e. not predicated).
176       Result.Mask =
177           Inst->getOperand(GenXIntrinsic::GenXRegion::PredicateOperandNum);
178       if (auto C = dyn_cast<Constant>(Result.Mask))
179         if (C->isAllOnesValue())
180           Result.Mask = 0;
181       break;
182     default:
183       IGC_ASSERT(0);
184   }
185   // Get the region parameters.
186   IGC_ASSERT(Subregion);
187   Result.ElementTy = Subregion->getType();
188   if (auto *VT = dyn_cast<IGCLLVM::FixedVectorType>(Result.ElementTy)) {
189     Result.ElementTy = VT->getElementType();
190     Result.NumElements = VT->getNumElements();
191   }
192   const DataLayout &DL = Inst->getModule()->getDataLayout();
193   static_assert(genx::ByteBits);
194   IGC_ASSERT(DL.getTypeSizeInBits(Result.ElementTy) % genx::ByteBits == 0);
195   Result.ElementBytes = DL.getTypeSizeInBits(Result.ElementTy) / genx::ByteBits;
196   Result.VStride = cast<ConstantInt>(Inst->getOperand(ArgIdx))->getSExtValue();
197   Result.Width =
198       cast<ConstantInt>(Inst->getOperand(ArgIdx + 1))->getSExtValue();
199   Result.Stride =
200       cast<ConstantInt>(Inst->getOperand(ArgIdx + 2))->getSExtValue();
201   ArgIdx += 3;
202   // Get the start index.
203   Value *V = Inst->getOperand(ArgIdx);
204   IGC_ASSERT_MESSAGE(V->getType()->getScalarType()->isIntegerTy(16),
205     "region index must be i16 or vXi16 type");
206   IGC_ASSERT(
207       testRegionIndexForSizeMismatch(V, Result.Width, Result.NumElements));
208 
209   if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
210     Result.Offset = CI->getSExtValue(); // Constant index.
211   else {
212     Result.Indirect = V; // Index is variable; assume no baled in add.
213     if (BI.isOperandBaled(ArgIdx)) {
214       Instruction *Operator = cast<Instruction>(V);
215       // The index is variable and has something baled in. We want to process
216       // a baled in add or add_addr, and ignore a baled in rdregion.
217       if(!GenXIntrinsic::isRdRegion(Operator)) {
218         // The index is variable and has a baled in or/add/sub/add_addr.
219         // offset is calculated through 'add' or 'or'
220         IGC_ASSERT(testOperator(Operator));
221 
222         Constant *C = cast<Constant>(Operator->getOperand(1));
223         ConstantInt *CI = dyn_cast<ConstantInt>(C);
224         if (!CI)
225           CI = cast<ConstantInt>(C->getSplatValue());
226 
227         Result.Offset = CI->getSExtValue();
228 
229         if (Operator->getOpcode() == Instruction::Sub)
230           Result.Offset = -Result.Offset;
231 
232         Result.Indirect = Operator->getOperand(0);
233       }
234     }
235     // For a variable index, get the parent width arg.
236     ConstantInt *PW = dyn_cast<ConstantInt>(Inst->getOperand(ArgIdx + 1));
237     if (PW)
238       Result.ParentWidth = PW->getZExtValue();
239   }
240   // We do some trivial legalization here. The legalization pass does not
241   // make these changes; instead we do them here so they are not permanently
242   // written back into the IR but are made on the fly each time some other
243   // pass uses this code to get the region info.
244   if (Result.NumElements == 1) {
245     Result.Width = Result.Stride = 1;
246     Result.VStride = 0;
247   } else {
248     if (Result.NumElements <= Result.Width) {
249       Result.Width = Result.NumElements;
250       Result.VStride = 0;
251     } else if ((unsigned)Result.VStride == Result.Width * Result.Stride) {
252       // VStride == Width * Stride, so we can canonicalize to a 1D region,
253       // but only if not indirect or not asked to preserve parentwidth,
254       // and never if multi-indirect.
255       if (!Result.Indirect ||
256           (!isa<VectorType>(Result.Indirect->getType()) && !WantParentWidth)) {
257         Result.Width = Result.NumElements;
258         Result.VStride = 0;
259         Result.ParentWidth = 0;
260       }
261     } else if (Result.Width == 1) {
262       // We can turn a 2D width 1 region into a 1D region, but if it is
263       // indirect it invalidates ParentWidth. So only do it if not asked
264       // to keep ParentWidth. Also we cannot do it if it is multi-indirect.
265       if (!Result.Indirect ||
266           (!isa<VectorType>(Result.Indirect->getType()) && !WantParentWidth)) {
267         Result.Width = Result.NumElements;
268         Result.Stride = Result.VStride;
269         Result.VStride = 0;
270         Result.ParentWidth = 0;
271       }
272     }
273     if (Result.Stride == 0 && Result.Width == Result.NumElements) {
274       // Canonical scalar region.
275       Result.Width = 1;
276       Result.VStride = 0;
277     }
278   }
279   return Result;
280 }
281 
282 /***********************************************************************
283  * Region::getLegalRegionSizeForTarget: get the max legal size of a region
284  *
285  * Enter:   Idx = start index into the subregion
286  *          Allow2D = whether to allow 2D region
287  *          InputNumElements = number of elements in whole input vector (so
288  *                we can tell if it is small enough that it cannot possibly
289  *                cross a GRF boundary)
290  *          ST = GenXSubtarget (so we can get gen specific crossing rules)
291  *          AI = 0 else AlignmentInfo (to determine alignment of indirect index)
292  */
getLegalRegionSizeForTarget(const GenXSubtarget & ST,const Region & R,unsigned Idx,bool Allow2D,unsigned InputNumElements,AlignmentInfo * AI)293 unsigned genx::getLegalRegionSizeForTarget(const GenXSubtarget &ST,
294                                            const Region &R, unsigned Idx,
295                                            bool Allow2D,
296                                            unsigned InputNumElements,
297                                            AlignmentInfo *AI) {
298   Alignment Align;
299   if (R.Indirect) {
300     Align = Alignment::getUnknown();
301     if (AI)
302       Align = AI->get(R.Indirect);
303   }
304   return getLegalRegionSizeForTarget(ST, R, Idx, Allow2D, InputNumElements,
305                                      Align);
306 }
307 
308 /***********************************************************************
309  * Region::getLegalRegionSizeForTarget : get the max legal size of a region
310  *
311  * Enter:   Idx = start index into the subregion
312  *          Allow2D = whether to allow 2D region
313  *          InputNumElements = number of elements in whole input vector (so
314  *                we can tell if it is small enough that it cannot possibly
315  *                cross a GRF boundary)
316  *          ST = GenXSubtarget (so we can get gen specific crossing rules)
317  *          Align = alignment of indirect index if any
318  *
319  * The setting of Indirect is used as follows:
320  *
321  * 0: not indirect
322  * anything of scalar type: single indirect
323  * anything of vector type: multi indirect
324  */
getLegalRegionSizeForTarget(const GenXSubtarget & ST,const Region & R,unsigned Idx,bool Allow2D,unsigned InputNumElements,Alignment Align)325 unsigned genx::getLegalRegionSizeForTarget(const GenXSubtarget &ST,
326                                            const Region &R, unsigned Idx,
327                                            bool Allow2D,
328                                            unsigned InputNumElements,
329                                            Alignment Align) {
330   // Determine the max valid width.
331   unsigned ValidWidth = 1;
332   unsigned GRFByteSize = ST.getGRFByteSize();
333   int MaxStride = 4;
334   unsigned LogGRFWidth = genx::log2(GRFByteSize);
335   if ((!R.Stride || exactLog2(R.Stride) >= 0) &&
336       (Allow2D || R.Stride <= MaxStride)) {
337     // The stride is legal, so we can potentially do more than one element at a
338     // time.
339     // Disallow 2D if the stride is too large for a real Gen region. For a
340     // source operand (Allow2D is true), we allow a 1D region with stride too
341     // large, because the vISA writer turns it into a 2D region with width 1.
342     bool StrideValid = (R.Stride <= MaxStride);
343 
344     if (R.Indirect && isa<VectorType>(R.Indirect->getType())) {
345       // Multi indirect.
346       if (!Allow2D) {
347         // Multi indirect not allowed in wrregion.
348         if (!R.Stride)
349           ValidWidth = 1 << genx::log2(R.Width);
350       } else if (R.Width == 1 || !R.Stride) {
351         // Multi indirect with width 1 or stride 0.
352         // Return the max power of two number of elements that:
353         // 1. fit in 2 GRFs; and
354         // 2. fit in the whole region; and
355         // 3. fit in a row if the width is not legal
356         // 4. no more than 8 elements in multi indirect (because there
357         //    are only 8 elements in an address register).
358         unsigned LogWidth = genx::log2(Width);
359         if (1U << LogWidth == Width)
360           LogWidth = genx::log2(R.NumElements); // legal width
361         unsigned LogElementBytes = genx::log2(R.ElementBytes);
362         if (LogWidth + LogElementBytes > (LogGRFWidth + 1))
363           LogWidth = LogGRFWidth + 1 - LogElementBytes;
364         ValidWidth = 1 << LogWidth;
365         if (ValidWidth > 8)
366           ValidWidth = 8;
367       }
368       // Other multi indirect can only do one element.
369     } else {
370       // Calculate number of elements up to the boundary imposed by GRF
371       // crossing rules.
372       unsigned ElementsPerGRF = GRFByteSize / R.ElementBytes;
373       unsigned OffsetElements = R.Offset / R.ElementBytes;
374       unsigned ElementsToBoundary = 1;
375       unsigned RealIdx = Idx / R.Width * R.VStride + Idx % R.Width * R.Stride;
376       if (!R.Indirect) {
377         // For a direct operand, just use the constant offset of the
378         // region and the index so far to calculate how far into a GRF this
379         // subregion starts, and set the boundary at the next-but-one GRF
380         // boundary.
381         unsigned NumGRF = 2;
382         ElementsToBoundary = (NumGRF * ElementsPerGRF) -
383                              ((RealIdx + OffsetElements) % ElementsPerGRF);
384       } else if (InputNumElements <= ElementsPerGRF) {
385         // Indirect region but the whole vector is no bigger than a GRF, so
386         // there is no limit imposed by GRF crossing.
387         ElementsToBoundary = ElementsPerGRF;
388       } else {
389         // For an indirect region, calculate the min and max index (including
390         // offset) from the region parameters, and add on the current start
391         // index to both.
392         // For <= BDW:
393         //   1. If the min and max then are in the same GRF, then the distance
394         //      from max to the next GRF boundary is the allowed size.
395         // For >= SKL:
396         //   1. If the min and max then are in the same GRF, then the distance
397         //      from max to the next-but-one GRF boundary is the allowed size.
398         //   2. If the max is in the next GRF after min, then the distance
399         //      from max to the next GRF boundary is the allowed size.
400         // However vISA imposes the restriction that, in a source indirect
401         // region, a row cannot cross a GRF, unless the region is contiguous.
402         // Pending a proper fix, we have a temporary fix here that we disallow
403         // GRF crossing completely unless the original region is a destination
404         // operand or is a 1D source operand (so GenXCisaBuilder can turn it
405         // into Nx1 instead of 1xN).  We use Allow2D as a proxy for "is source
406         // operand".
407         unsigned GRFsPerIndirect =
408             genx::getNumGRFsPerIndirectForRegion(R, &ST, Allow2D);
409         unsigned Last = (R.NumElements / R.Width - 1) * R.VStride +
410                         (R.Width - 1) * R.Stride;
411         unsigned Max = InputNumElements - Last - 1 + RealIdx;
412         unsigned Min = RealIdx;
413         unsigned MinMaxGRFDiff = (Max & -ElementsPerGRF) - (Min & -ElementsPerGRF);
414         if (!MinMaxGRFDiff) // min and max in same GRF
415           ElementsToBoundary = ElementsPerGRF * GRFsPerIndirect
416               - (Max & (ElementsPerGRF - 1));
417         else if (MinMaxGRFDiff == 1 && GRFsPerIndirect > 1)
418           ElementsToBoundary = ElementsPerGRF - (Max & (ElementsPerGRF - 1));
419         // We may be able to refine an indirect region legal width further...
420         if (exactLog2(R.ParentWidth) >= 0 &&
421             R.ParentWidth <= GRFsPerIndirect * ElementsPerGRF) {
422           // ParentWidth tells us that a row of our region cannot cross a
423           // possible number of elements addressed by indirect region. Say that
424           // the boundary is at the next multiple of ParentWidth.
425           ElementsToBoundary = std::max(R.ParentWidth - RealIdx % R.ParentWidth,
426                                         ElementsToBoundary);
427         } else if (!isa<VectorType>(R.Indirect->getType())) {
428           // Use the alignment+offset of the single indirect index, with alignment
429           // limited to one GRF.
430           if (!Align.isUnknown()) {
431             unsigned LogAlign = Align.getLogAlign();
432             unsigned ExtraBits = Align.getExtraBits();
433             ExtraBits += (R.Offset + RealIdx * R.ElementBytes);
434             ExtraBits &= ((1 << LogAlign) - 1);
435             if (LogAlign >= LogGRFWidth && !ExtraBits) {
436               // Start is GRF aligned, so legal width is 1 GRF for <=BDW or
437               // 2 GRFs for >=SKL.
438               ElementsToBoundary = ElementsPerGRF * GRFsPerIndirect;
439             } else if (LogAlign > (unsigned)genx::log2(R.ElementBytes) ||
440                        (LogAlign == (unsigned)genx::log2(R.ElementBytes) &&
441                         ExtraBits == 0)) {
442               LogAlign =
443                   std::min(LogGRFWidth, LogAlign) - genx::log2(R.ElementBytes);
444               ExtraBits =
445                   (ExtraBits & (GRFByteSize - 1)) >> genx::log2(R.ElementBytes);
446               // We have some alignment, so we can say that the next GRF boundary
447               // is (at least) that many elements away, minus the offset from that
448               // alignment.
449               // For SKL+, we can cross one GRF boundary, so add on one GRF's
450               // worth.
451               unsigned ElementsToBoundaryFromAlign = (1U << LogAlign) - ExtraBits;
452               ElementsToBoundaryFromAlign += (GRFsPerIndirect - 1) * ElementsPerGRF;
453               ElementsToBoundary = std::max(ElementsToBoundaryFromAlign,
454                   ElementsToBoundary);
455             }
456           }
457         }
458       }
459 
460       // Now calculate what subregion we can fit in before the boundary
461       // calculated above.
462       if (Allow2D && StrideValid) {
463         if ((!R.VStride || exactLog2(R.VStride) >= 0) &&
464             exactLog2(R.Width) >= 0 && R.Width <= 16 && !(Idx % R.Width) &&
465             ElementsToBoundary >= (R.Width - 1) * R.Stride + 1) {
466           // The vstride and width are legal, and we're at the start of a
467           // row, and ElementsToBoundary is big enough for at least one
468           // whole row, so we can potentially do more than one whole row at a
469           // time. See how many we can fit, without including the "slack"
470           // at the end of the last row.
471           unsigned NumRows = 0;
472           if (R.VStride == 0) // Avoid divide by 0
473             NumRows = (R.NumElements - Idx) / R.Width;
474           else {
475             unsigned LastElementOfRow = (R.Width - 1) * R.Stride;
476             unsigned Slack = R.VStride - (LastElementOfRow + 1);
477             NumRows = (ElementsToBoundary + Slack) / R.VStride;
478             if (NumRows) {
479               if (NumRows * R.Width + Idx > R.NumElements)
480                 NumRows = (R.NumElements - Idx) / R.Width;
481             }
482           }
483           ValidWidth = (1 << genx::log2(NumRows)) * R.Width;
484         }
485         if (ValidWidth == 1 && Idx % R.Width) {
486           // That failed. See if we can legally get to the end of the row then
487           // the same number of elements again at the start of the next row.
488           unsigned ToEndOfRow = R.Width - Idx % R.Width;
489           if (exactLog2(ToEndOfRow) >= 0 && ToEndOfRow <= 16) {
490             unsigned NewVStride = R.VStride + (ToEndOfRow - R.Width) * R.Stride;
491             if (exactLog2(NewVStride) >= 0 &&
492                 NewVStride + (ToEndOfRow - 1) * R.Stride < ElementsToBoundary) {
493               // Yes, we can do the end of one row and the same size start of
494               // the next row.
495               ValidWidth = 2 * ToEndOfRow;
496             }
497           }
498         }
499       }
500       if (ValidWidth == 1) {
501         // That failed. See how many elements we can get, no further than the
502         // next end of row.
503         ValidWidth = R.Width - Idx % R.Width;
504         if (ValidWidth * R.Stride - (R.Stride - 1) > ElementsToBoundary)
505           ValidWidth = (ElementsToBoundary + R.Stride - 1) / R.Stride;
506         ValidWidth = 1 << genx::log2(ValidWidth);
507       }
508       // If the RStride is 0 (which is seen in splat operations) then the
509       // above logic tends to determine that all of the elements can fit,
510       // irrespective of vector size and type. This is usually incorrect
511       // in the wider context, so clamp it here to whatever fits in 2GRF if
512       // necessary
513       if (ValidWidth > (2 * ElementsPerGRF))
514         ValidWidth = 2 * ElementsPerGRF;
515 
516     }
517   }
518   return ValidWidth;
519 }
520 
521 /***********************************************************************
522  * RdWrRegionSequence::buildFromStartWr:  detect a split (legalized)
523  *    sequence rdregion-wrregion from the start, and populate the
524  *    RdWrRegionSequence object with its details
525  *
526  * This fails if there is any predication. It succeeds with a sequence length
527  * of one (i.e. a single rdregion-wrregion pair).
528  *
529  * On success, if the WaitingFor field matches one of the wrregions in the
530  * sequence, then WaitingFor is reset to 0. This is used by buildFromWr to
531  * check that the sequence includes the wrregion originally passed to it.
532  *
533  * On failure, EndWr is left as is, which means that isNull() continues to
534  * be true.
535  */
buildFromStartWr(Instruction * ArgStartWr,GenXBaling * Baling)536 bool RdWrRegionSequence::buildFromStartWr(Instruction *ArgStartWr,
537                                           GenXBaling *Baling) {
538   StartWr = ArgStartWr;
539   auto Wr = StartWr;
540   IGC_ASSERT(GenXIntrinsic::isWrRegion(Wr));
541   IGC_ASSERT(Baling);
542   Region TotalWrR = genx::makeRegionFromBaleInfo(Wr, Baling->getBaleInfo(Wr));
543   WrR = TotalWrR;
544   if (TotalWrR.Mask)
545     return false;
546   OldVal = Wr->getOperand(GenXIntrinsic::GenXRegion::OldValueOperandNum);
547   auto RdVal = Wr->getOperand(GenXIntrinsic::GenXRegion::NewValueOperandNum);
548   if (auto Rd = dyn_cast<Instruction>(RdVal)) {
549     // Handle the case that the start wrregion has a rdregion, so we look for
550     // a sequence of rd-wr pairs.
551     if (!GenXIntrinsic::isRdRegion(Rd))
552       return false;
553     Region TotalRdR = makeRegionFromBaleInfo(Rd, Baling->getBaleInfo(Rd));
554     RdR = TotalRdR;
555     Input = Rd->getOperand(GenXIntrinsic::GenXRegion::OldValueOperandNum);
556     EndWr = Wr;
557     if (Wr == WaitingFor)
558       WaitingFor = nullptr;
559     bool SeenWaitingFor = false;
560     for (;;) {
561       if (!Wr->hasOneUse() || Wr->use_begin()->getOperandNo()
562           != GenXIntrinsic::GenXRegion::OldValueOperandNum)
563         break;
564       Wr = cast<Instruction>(Wr->use_begin()->getUser());
565       if (!GenXIntrinsic::isWrRegion(Wr))
566         break;
567       Value *In = Wr->getOperand(GenXIntrinsic::GenXRegion::NewValueOperandNum);
568       if (!GenXIntrinsic::isRdRegion(In))
569         break;
570       auto Rd = cast<Instruction>(In);
571       if (Rd->getOperand(GenXIntrinsic::GenXRegion::OldValueOperandNum) != Input)
572         break;
573       // Append to the regions. Give up if either fails.
574       if (!TotalRdR.append(
575               makeRegionFromBaleInfo(Rd, Baling->getBaleInfo(Rd))) ||
576           !TotalWrR.append(makeRegionFromBaleInfo(Wr, Baling->getBaleInfo(Wr))))
577         break;
578       SeenWaitingFor |= Wr == WaitingFor;
579       // If both regions are now legal (have a whole number of rows), then
580       // save the current position.
581       if (TotalRdR.isWholeNumRows() && TotalWrR.isWholeNumRows()) {
582         RdR = TotalRdR;
583         WrR = TotalWrR;
584         EndWr = Wr;
585         if (SeenWaitingFor)
586           WaitingFor = nullptr;
587       }
588     }
589     return true;
590   }
591   if (!isa<UndefValue>(Wr->getOperand(GenXIntrinsic::GenXRegion::OldValueOperandNum)))
592     return false;
593   auto TotalC = dyn_cast<Constant>(RdVal);
594   if (!TotalC)
595     return false;
596   // Handle the case that the start wrregion has a constant "new value" operand
597   // and an undef "old value" operand.
598   // We look for a sequence of wrregions where the "new value" operands are all
599   // constant and we derive the overall constant.
600   Region TotalRdR(TotalC);
601   RdR = TotalRdR;
602   Input = TotalC;
603   EndWr = Wr;
604   if (Wr == WaitingFor)
605     WaitingFor = nullptr;
606   bool SeenWaitingFor = false;
607   for (;;) {
608     if (!Wr->hasOneUse() || Wr->use_begin()->getOperandNo()
609         != GenXIntrinsic::GenXRegion::OldValueOperandNum)
610       break;
611     Wr = cast<Instruction>(Wr->use_begin()->getUser());
612     if (!GenXIntrinsic::isWrRegion(Wr))
613       break;
614     auto In = dyn_cast<Constant>(Wr->getOperand(GenXIntrinsic::GenXRegion::NewValueOperandNum));
615     if (!In)
616       break;
617     // Append to the regions. Give up if either fails.
618     Region InR(In);
619     InR.Offset = TotalRdR.NumElements * TotalRdR.ElementBytes;
620     if (!TotalRdR.append(InR) ||
621         !TotalWrR.append(makeRegionFromBaleInfo(Wr, Baling->getBaleInfo(Wr))))
622       break;
623     SeenWaitingFor |= Wr == WaitingFor;
624     // Append the constant.
625     TotalC = concatConstants(TotalC, In);
626     // If both regions are now legal (have a whole number of rows), then save
627     // the current position.
628     if (TotalRdR.isWholeNumRows() && TotalWrR.isWholeNumRows()) {
629       RdR = TotalRdR;
630       WrR = TotalWrR;
631       EndWr = Wr;
632       Input = TotalC;
633       if (SeenWaitingFor)
634         WaitingFor = nullptr;
635     }
636   }
637   return true;
638 }
639 
640 /***********************************************************************
641  * RdWrRegionSequence::buildFromWr:  detect a split (legalized) rdregion-wrregion
642  *    sequence starting from any wrregion within it, and populate the
643  *    RdWrRegionSequence object with its details
644  *
645  * This fails if there is any predication. It succeeds with a sequence length
646  * of one (i.e. a single rdregion-wrregion pair).
647  *
648  * On failure, EndWr is left as is, which means that isNull() continues to
649  * be true.
650  */
buildFromWr(Instruction * Wr,GenXBaling * Baling)651 bool RdWrRegionSequence::buildFromWr(Instruction *Wr, GenXBaling *Baling)
652 {
653   // Remember that our sequence needs to contain Wr.
654   WaitingFor = Wr;
655   // Scan back to what looks like the start of the sequence.
656   IGC_ASSERT(GenXIntrinsic::isWrRegion(Wr));
657   StartWr = Wr;
658   auto RdVal = Wr->getOperand(GenXIntrinsic::GenXRegion::NewValueOperandNum);
659   auto Rd = dyn_cast<Instruction>(RdVal);
660   bool ConstSequence = false;
661   if (!Rd) {
662     if (!isa<Constant>(RdVal))
663       return 0;
664     ConstSequence = true;
665   } else
666     Input = Rd->getOperand(GenXIntrinsic::GenXRegion::OldValueOperandNum);
667   for (;;) {
668     Wr = dyn_cast<Instruction>(
669         Wr->getOperand(GenXIntrinsic::GenXRegion::OldValueOperandNum));
670     if (!GenXIntrinsic::isWrRegion(Wr))
671       break;
672     IGC_ASSERT(Wr);
673     if (!Wr->hasOneUse())
674       break;
675     RdVal = Wr->getOperand(GenXIntrinsic::GenXRegion::NewValueOperandNum);
676     if (ConstSequence) {
677       if (!isa<Constant>(RdVal))
678         break;
679     } else {
680       Rd = dyn_cast<Instruction>(
681           Wr->getOperand(GenXIntrinsic::GenXRegion::NewValueOperandNum));
682       if (!Rd)
683         break;
684       if (Input != Rd->getOperand(GenXIntrinsic::GenXRegion::OldValueOperandNum))
685         break;
686     }
687     StartWr = Wr;
688   }
689   // Try detecting a split rdregion-wrregion starting at StartWr.
690   for (;;) {
691     if (!buildFromStartWr(StartWr, Baling)) {
692       EndWr = nullptr;
693       return false;
694     }
695     if (!WaitingFor)
696       return true; // success
697     // The detected sequence did not include the wrregion this function
698     // started with. Retry with the following sequence.
699     StartWr = cast<Instruction>(EndWr->use_begin()->getUser());
700     if (GenXIntrinsic::isWrRegion(StartWr))
701       return false;
702   }
703 }
704 
705 /***********************************************************************
706  * RdWrRegionSequence::buildFromRd:  detect a split (legalized) rdregion-wrregion
707  *    sequence starting from any rdregion within it, and populate the
708  *    RdWrRegionSequence object with its details
709  *
710  * This fails if there is any predication. It succeeds with a sequence length
711  * of one (i.e. a single rdregion-wrregion pair).
712  */
buildFromRd(Instruction * Rd,GenXBaling * Baling)713 bool RdWrRegionSequence::buildFromRd(Instruction *Rd, GenXBaling *Baling)
714 {
715   IGC_ASSERT(GenXIntrinsic::isRdRegion(Rd));
716   if (!Rd->hasOneUse())
717     return false;
718   if (Rd->use_begin()->getOperandNo() != GenXIntrinsic::GenXRegion::NewValueOperandNum)
719     return false;
720   auto Wr = cast<Instruction>(Rd->use_begin()->getUser());
721   if (!GenXIntrinsic::isWrRegion(Wr))
722     return false;
723   return buildFromWr(Wr, Baling);
724 }
725 
726 /***********************************************************************
727  * RdWrRegionSequence::size : get number of rdregion-wrregion pairs in the
728  *    sequence
729  */
size() const730 unsigned RdWrRegionSequence::size() const
731 {
732   unsigned Size = 1;
733   Instruction *Wr = EndWr;
734   for ( ; Wr != StartWr; ++Size)
735     Wr = cast<Instruction>(
736         Wr->getOperand(GenXIntrinsic::GenXRegion::OldValueOperandNum));
737   return Size;
738 }
739 
740 /***********************************************************************
741  * RdWrRegionSequence::isOnlyUseOfInput : check whether the sequence is the
742  *    only use of its input
743  */
isOnlyUseOfInput() const744 bool RdWrRegionSequence::isOnlyUseOfInput() const
745 {
746   unsigned Count = 0;
747   for (auto ui = Input->use_begin(), ue = Input->use_end();
748       ui != ue; ++ui)
749     ++Count;
750   return Count == size();
751 }
752 
753 /***********************************************************************
754  * RdWrRegionSequence::getRdIndex : get the index of the legalized rdregion
755  */
getRdIndex() const756 Value *RdWrRegionSequence::getRdIndex() const
757 {
758   if (isa<Constant>(Input))
759     return ConstantInt::get(Type::getInt16Ty(StartWr->getContext()), 0);
760   auto Rd = cast<Instruction>(
761       StartWr->getOperand(GenXIntrinsic::GenXRegion::NewValueOperandNum));
762   IGC_ASSERT(GenXIntrinsic::isRdRegion(Rd));
763   return Rd->getOperand(GenXIntrinsic::GenXRegion::RdIndexOperandNum);
764 }
765 
766 /***********************************************************************
767  * RdWrRegionSequence::getWrIndex : get the index of the legalized wrregion
768  */
getWrIndex() const769 Value *RdWrRegionSequence::getWrIndex() const
770 {
771   return StartWr->getOperand(GenXIntrinsic::GenXRegion::WrIndexOperandNum);
772 }
773 
774 /***********************************************************************
775  * RdWrRegionSequence::getInputUse : get some use of Input in the sequence
776  *
777  * This only works if the RdWrRegionSequence is a sequence of rd-wr pairs,
778  * rather than a sequence of wrregions with constant input. In the latter
779  * case, this returns 0.
780  */
getInputUse() const781 Use *RdWrRegionSequence::getInputUse() const
782 {
783   auto Rd = dyn_cast<Instruction>(
784       StartWr->getOperand(GenXIntrinsic::GenXRegion::NewValueOperandNum));
785   if (!GenXIntrinsic::isRdRegion(Rd))
786     return nullptr;
787   const unsigned OpIdx = GenXIntrinsic::GenXRegion::OldValueOperandNum;
788   IGC_ASSERT(Rd);
789   IGC_ASSERT(Rd->getOperand(OpIdx) == Input);
790   return &Rd->getOperandUse(OpIdx);
791 }
792 
793 /***********************************************************************
794  * RdWrRegionSequence::print : debug dump/print
795  */
print(raw_ostream & OS) const796 void RdWrRegionSequence::print(raw_ostream &OS) const
797 {
798   if (isNull())
799     OS << "null";
800   else {
801     OS << "sequence";
802     if (OldVal)
803       dbgs() << " OldVal=" << OldVal->getName();
804     dbgs() << " Input=" << Input->getName()
805       << " StartWr=" << StartWr->getName()
806       << " EndWr=" << EndWr->getName()
807       << " RdR=" << RdR
808       << " WrR=" << WrR;
809   }
810 }
811 
simplifyConstIndirectRegion(Instruction * Inst)812 static Instruction* simplifyConstIndirectRegion(Instruction* Inst) {
813   // if a region has a constant-vector as its indirect offsets,
814   // try to recognize the pattern, and replace it with
815   // a direct region with v-stride, h-stride, h-width
816   Region R = makeRegionFromBaleInfo(Inst, BaleInfo());
817   if (R.Indirect == nullptr)
818     return Inst;
819 
820   auto cv = dyn_cast<ConstantDataVector>(R.Indirect);
821   if (!cv)
822     return Inst;
823   // Flatten the vector out into the elements array
824   llvm::SmallVector<llvm::Constant*, 16> elements;
825   auto vectorLength =
826       cast<IGCLLVM::FixedVectorType>(cv->getType())->getNumElements();
827   for (unsigned i = 0; i < vectorLength; ++i)
828     elements.push_back(cv->getElementAsConstant(i));
829 
830   llvm::ConstantInt* ci = llvm::dyn_cast<llvm::ConstantInt>(elements[0]);
831   if (ci == NULL)
832     return Inst; // Not a vector of integers
833 
834   int VStride = 1;
835   unsigned Width = 1;
836   int Stride = 1;
837   int Offset = (-1);
838 
839   int64_t val0 = ci->getSExtValue();
840   if (vectorLength == 1) {
841     R.Indirect = nullptr;
842     R.Offset = val0 + R.Offset;
843     R.Stride = 0;
844     R.Width = 1;
845     R.VStride = 0;
846     if (GenXIntrinsic::isRdRegion(Inst))
847       return R.createRdRegion(Inst->getOperand(0),
848         Inst->getName(), Inst, Inst->getDebugLoc());
849     else if (GenXIntrinsic::isWrRegion(Inst))
850       return R.createWrRegion(Inst->getOperand(0), Inst->getOperand(1),
851                               Inst->getName(), Inst, Inst->getDebugLoc());
852     return Inst;
853   }
854   ci = llvm::dyn_cast<llvm::ConstantInt>(elements[1]);
855   if (ci == NULL)
856     return Inst; // Not a vector of integers
857 
858   int64_t prevVal = ci->getSExtValue();
859   int64_t diff = prevVal - val0;
860   if (diff < 0)
861     return Inst; // cannot have negative stride
862   int i0 = 0;
863   Offset = val0 + R.Offset;
864   // check if this is a 1d simple-stride region
865   for (int i = 2; i < (int)vectorLength; ++i) {
866     ci = llvm::dyn_cast<llvm::ConstantInt>(elements[i]);
867     if (ci == NULL)
868       return Inst;
869 
870     int64_t nextVal = ci->getSExtValue();
871     if (prevVal + diff != nextVal) {
872       if (Width == 1) {
873         Width = i - i0;
874         VStride = nextVal - val0;
875         val0 = nextVal;
876         i0 = i;
877       }
878       else if (nextVal != val0 + VStride || i != i0 + Width)
879         return Inst;
880       else {
881         val0 = nextVal;
882         i0 = i;
883       }
884       if (VStride < 0)
885         return Inst; // cannot have negative stride
886     }
887     prevVal = nextVal;
888   }
889   Stride = diff*8 / R.ElementTy->getPrimitiveSizeInBits();
890   VStride = VStride*8 / R.ElementTy->getPrimitiveSizeInBits();
891   // rewrite the region inst
892   R.Indirect = nullptr;
893   R.Offset = Offset;
894   R.Stride = Stride;
895   R.Width = (Width == 1) ? R.NumElements : Width;
896   R.VStride = VStride;
897   if (GenXIntrinsic::isRdRegion(Inst))
898     return R.createRdRegion(Inst->getOperand(0),
899       Inst->getName(), Inst, Inst->getDebugLoc());
900   else if (GenXIntrinsic::isWrRegion(Inst))
901     return R.createWrRegion(Inst->getOperand(0), Inst->getOperand(1),
902                             Inst->getName(), Inst, Inst->getDebugLoc());
903   return Inst;
904 }
905 
simplifyRegionWrite(Instruction * Inst)906 static Value *simplifyRegionWrite(Instruction *Inst) {
907   IGC_ASSERT(GenXIntrinsic::isWrRegion(Inst));
908   Value *NewVal = Inst->getOperand(GenXIntrinsic::GenXRegion::NewValueOperandNum);
909 
910   // Replace C with A
911   // C = wrregion(A, undef, R)
912   if (isa<UndefValue>(NewVal))
913     return Inst->getOperand(GenXIntrinsic::GenXRegion::OldValueOperandNum);
914 
915   // When A and undef have the same type, replace C with A
916   // B = rdregion(A, R)
917   // C = wrregion(undef, B, R)
918   //
919   // or replace C by A
920   //
921   // B = rdregion(A, R)
922   // C = wrregion(A, B, R)
923   //
924   if (GenXIntrinsic::isRdRegion(NewVal)) {
925     Instruction *B = cast<Instruction>(NewVal);
926     Region InnerR = makeRegionFromBaleInfo(B, BaleInfo());
927     Region OuterR = makeRegionFromBaleInfo(Inst, BaleInfo());
928     if (OuterR != InnerR)
929       return nullptr;
930 
931     auto OldValB = B->getOperand(GenXIntrinsic::GenXRegion::OldValueOperandNum);
932     if (GenXIntrinsic::isReadPredefReg(OldValB))
933       return nullptr;
934     auto OldValC = Inst->getOperand(GenXIntrinsic::GenXRegion::OldValueOperandNum);
935     if ((isa<UndefValue>(OldValC) &&
936          OldValB->getType() == OldValC->getType()) ||
937         OldValB == OldValC)
938       return OldValB;
939   }
940 
941   return nullptr;
942 }
943 
simplifyRegionRead(Instruction * Inst)944 static Value *simplifyRegionRead(Instruction *Inst) {
945   IGC_ASSERT(GenXIntrinsic::isRdRegion(Inst));
946   Value *Input = Inst->getOperand(GenXIntrinsic::GenXRegion::OldValueOperandNum);
947   if (isa<UndefValue>(Input))
948     return UndefValue::get(Inst->getType());
949   else if (auto C = dyn_cast<Constant>(Input)) {
950     if (auto Splat = C->getSplatValue()) {
951       if (auto *Ty = dyn_cast<IGCLLVM::FixedVectorType>(Inst->getType()))
952         Splat = ConstantVector::getSplat(
953             IGCLLVM::getElementCount(Ty->getNumElements()), Splat);
954       return Splat;
955     }
956   } else if (GenXIntrinsic::isWrRegion(Input) && Input->hasOneUse()) {
957     // W = wrr(A, B, R)
958     // C = rdr(W, R)
959     // =>
960     // replace C by B
961     Instruction *WI = cast<Instruction>(Input);
962     Region R1 = makeRegionFromBaleInfo(WI, BaleInfo());
963     Region R2 = makeRegionFromBaleInfo(Inst, BaleInfo());
964     if (R1 == R2) {
965       Value *B = WI->getOperand(GenXIntrinsic::GenXRegion::NewValueOperandNum);
966       if (B->getType() == Inst->getType())
967         return B;
968     }
969   }
970   return nullptr;
971 }
972 
973 // Simplify a region read or write.
simplifyRegionInst(Instruction * Inst,const DataLayout * DL)974 Value *llvm::genx::simplifyRegionInst(Instruction *Inst, const DataLayout *DL) {
975   if (Inst->use_empty())
976     return nullptr;
977 
978   unsigned ID = GenXIntrinsic::getGenXIntrinsicID(Inst);
979   switch (ID) {
980   case GenXIntrinsic::genx_wrregionf:
981   case GenXIntrinsic::genx_wrregioni:
982   case GenXIntrinsic::genx_rdregionf:
983   case GenXIntrinsic::genx_rdregioni: {
984     auto replace = simplifyConstIndirectRegion(Inst);
985     if (replace != Inst) {
986       Inst->replaceAllUsesWith(replace);
987       Inst = replace;
988     }
989     break;
990   }
991   default:
992     break;
993   }
994   if (Constant *C = ConstantFoldGenX(Inst, *DL))
995     return C;
996 
997   ID = GenXIntrinsic::getGenXIntrinsicID(Inst);
998   switch (ID) {
999   case GenXIntrinsic::genx_wrregionf:
1000   case GenXIntrinsic::genx_wrregioni:
1001     return simplifyRegionWrite(Inst);
1002   case GenXIntrinsic::genx_rdregionf:
1003   case GenXIntrinsic::genx_rdregioni:
1004     return simplifyRegionRead(Inst);
1005   default:
1006     break;
1007   }
1008   return nullptr;
1009 }
1010 
simplifyRegionInsts(Function * F,const DataLayout * DL)1011 bool llvm::genx::simplifyRegionInsts(Function *F, const DataLayout *DL) {
1012   bool Changed = false;
1013   for (auto &BB : F->getBasicBlockList()) {
1014     for (auto I = BB.begin(); I != BB.end();) {
1015       Instruction *Inst = &*I++;
1016       if (auto V = simplifyRegionInst(Inst, DL)) {
1017         Inst->replaceAllUsesWith(V);
1018         Inst->eraseFromParent();
1019         Changed = true;
1020       }
1021     }
1022   }
1023   return Changed;
1024 }
1025 
1026 // Cleanup loads.
1027 // %load1 = load *m
1028 // %load2 = load *m
1029 // no store to m
1030 // use(load1, load2)
1031 //
cleanupLoads(Function * F)1032 bool llvm::genx::cleanupLoads(Function *F) {
1033   bool Changed = false;
1034   for (auto &BB : F->getBasicBlockList()) {
1035     // The dominating loads (may have different types) for each variable.
1036     std::unordered_map<GlobalVariable *, std::vector<LoadInst *>> DomLoads;
1037     for (auto I = BB.begin(); I != BB.end();) {
1038       Instruction *Inst = &*I++;
1039       if (auto SI = dyn_cast<StoreInst>(Inst)) {
1040         auto GV = getUnderlyingGlobalVariable(SI->getPointerOperand());
1041         if (!GV)
1042           continue;
1043         // Kill all live loads on this variable.
1044         DomLoads[GV].clear();
1045       } else if (auto LI = dyn_cast<LoadInst>(Inst)) {
1046         auto GV = getUnderlyingGlobalVariable(LI->getPointerOperand());
1047         if (!GV)
1048           continue;
1049         auto &Loads = DomLoads[GV];
1050         LoadInst *DomLI = nullptr;
1051         for (auto LI1 : Loads) {
1052           if (LI1->getType() == LI->getType()) {
1053             DomLI = LI1;
1054             break;
1055           }
1056         }
1057         if (DomLI == nullptr)
1058           Loads.push_back(LI);
1059         else {
1060           LI->replaceAllUsesWith(DomLI);
1061           LI->eraseFromParent();
1062           Changed = true;
1063         }
1064       }
1065     }
1066   }
1067   return Changed;
1068 }
1069 
1070 bool
IsLinearVectorConstantInts(Value * v,int64_t & start,int64_t & stride)1071 llvm::genx::IsLinearVectorConstantInts(Value* v, int64_t& start, int64_t& stride) {
1072     auto cv = dyn_cast<ConstantDataVector>(v);
1073     if (!cv)
1074         return false;
1075     // Flatten the vector out into the elements array
1076     llvm::SmallVector<llvm::Constant*, 16> elements;
1077     auto vectorLength =
1078         cast<IGCLLVM::FixedVectorType>(cv->getType())->getNumElements();
1079     for (unsigned i = 0; i < vectorLength; ++i)
1080         elements.push_back(cv->getElementAsConstant(i));
1081 
1082     llvm::ConstantInt* ci = llvm::dyn_cast<llvm::ConstantInt>(elements[0]);
1083     if (ci == NULL)
1084         return false; // Not a vector of integers
1085 
1086     int64_t val0 = ci->getSExtValue();
1087     if (vectorLength == 1) {
1088         start = val0;
1089         stride = 0;
1090         return true;
1091     }
1092     ci = llvm::dyn_cast<llvm::ConstantInt>(elements[1]);
1093     if (ci == NULL)
1094         return false; // Not a vector of integers
1095     int64_t prevVal = ci->getSExtValue();
1096     int64_t diff = prevVal - val0;
1097 
1098     // For each element in the array, see if it is both a ConstantInt and
1099     // if the difference between it and the value of the previous element
1100     // is stride.  If not, fail.
1101     for (int i = 2; i < (int)vectorLength; ++i) {
1102         ci = llvm::dyn_cast<llvm::ConstantInt>(elements[i]);
1103         if (ci == NULL)
1104             return false;
1105 
1106         int64_t nextVal = ci->getSExtValue();
1107         if (prevVal + diff != nextVal)
1108             return false;
1109 
1110         prevVal = nextVal;
1111     }
1112     start = val0;
1113     stride = diff;
1114     return true;
1115 }
1116