LLVM 24.0.0git
InterleavedLoadCombinePass.cpp
Go to the documentation of this file.
1//===- InterleavedLoadCombine.cpp - Combine Interleaved Loads ---*- 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// \file
10//
11// This file defines the interleaved-load-combine pass. The pass searches for
12// ShuffleVectorInstruction that execute interleaving loads. If a matching
13// pattern is found, it adds a combined load and further instructions in a
14// pattern that is detectable by InterleavedAccesPass. The old instructions are
15// left dead to be removed later. The pass is specifically designed to be
16// executed just before InterleavedAccesPass to find any left-over instances
17// that are not detected within former passes.
18//
19//===----------------------------------------------------------------------===//
20
21#include "llvm/ADT/ArrayRef.h"
22#include "llvm/ADT/Hashing.h"
23#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/Statistic.h"
31#include "llvm/CodeGen/Passes.h"
35#include "llvm/IR/DataLayout.h"
36#include "llvm/IR/Dominators.h"
37#include "llvm/IR/Function.h"
38#include "llvm/IR/IRBuilder.h"
41#include "llvm/Pass.h"
42#include "llvm/Support/Debug.h"
46
47#include <algorithm>
48#include <cassert>
49#include <list>
50#include <unordered_map>
51
52using namespace llvm;
53
54#define DEBUG_TYPE "interleaved-load-combine"
55
56namespace {
57
58/// Statistic counter
59STATISTIC(NumInterleavedLoadCombine, "Number of combined loads");
60
61/// Option to disable the pass
62static cl::opt<bool> DisableInterleavedLoadCombine(
63 "disable-" DEBUG_TYPE, cl::init(false), cl::Hidden,
64 cl::desc("Disable combining of interleaved loads"));
65
66struct VectorInfo;
67
68struct InterleavedLoadCombineImpl {
69public:
70 InterleavedLoadCombineImpl(Function &F, DominatorTree &DT, MemorySSA &MSSA,
72 const TargetMachine &TM)
73 : F(F), DT(DT), MSSA(MSSA),
75
76 /// Scan the function for interleaved load candidates and execute the
77 /// replacement if applicable.
78 bool run();
79
80private:
81 /// Function this pass is working on
82 Function &F;
83
84 /// Dominator Tree Analysis
85 DominatorTree &DT;
86
87 /// Memory Alias Analyses
88 MemorySSA &MSSA;
89
90 /// Target Lowering Information
91 const TargetLowering &TLI;
92
93 /// Target Transform Information
95
96 /// Find the instruction in sets LIs that dominates all others, return nullptr
97 /// if there is none.
98 LoadInst *findFirstLoad(const std::set<LoadInst *> &LIs);
99
100 /// Replace interleaved load candidates. It does additional
101 /// analyses if this makes sense. Returns true on success and false
102 /// of nothing has been changed.
103 bool combine(ArrayRef<VectorInfo *> InterleavedLoad,
105}; // InterleavedLoadCombine
106
107/// First Order Polynomial on an n-Bit Integer Value
108///
109/// Polynomial(Value) = Value * B + A + E*2^(n-e)
110///
111/// A and B are the coefficients. E*2^(n-e) is an error within 'e' most
112/// significant bits. It is introduced if an exact computation cannot be proven
113/// (e.q. division by 2).
114///
115/// As part of this optimization multiple loads will be combined. It necessary
116/// to prove that loads are within some relative offset to each other. This
117/// class is used to prove relative offsets of values loaded from memory.
118///
119/// Representing an integer in this form is sound since addition in two's
120/// complement is associative (trivial) and multiplication distributes over the
121/// addition (see Proof(1) in Polynomial::mul). Further, both operations
122/// commute.
123//
124// Example:
125// declare @fn(i64 %IDX, <4 x float>* %PTR) {
126// %Pa1 = add i64 %IDX, 2
127// %Pa2 = lshr i64 %Pa1, 1
128// %Pa3 = getelementptr inbounds <4 x float>, <4 x float>* %PTR, i64 %Pa2
129// %Va = load <4 x float>, <4 x float>* %Pa3
130//
131// %Pb1 = add i64 %IDX, 4
132// %Pb2 = lshr i64 %Pb1, 1
133// %Pb3 = getelementptr inbounds <4 x float>, <4 x float>* %PTR, i64 %Pb2
134// %Vb = load <4 x float>, <4 x float>* %Pb3
135// ... }
136//
137// The goal is to prove that two loads load consecutive addresses.
138//
139// In this case the polynomials are constructed by the following
140// steps.
141//
142// The number tag #e specifies the error bits.
143//
144// Pa_0 = %IDX #0
145// Pa_1 = %IDX + 2 #0 | add 2
146// Pa_2 = %IDX/2 + 1 #1 | lshr 1
147// Pa_3 = %IDX/2 + 1 #1 | GEP, step signext to i64
148// Pa_4 = (%IDX/2)*16 + 16 #0 | GEP, multiply index by sizeof(4) for floats
149// Pa_5 = (%IDX/2)*16 + 16 #0 | GEP, add offset of leading components
150//
151// Pb_0 = %IDX #0
152// Pb_1 = %IDX + 4 #0 | add 2
153// Pb_2 = %IDX/2 + 2 #1 | lshr 1
154// Pb_3 = %IDX/2 + 2 #1 | GEP, step signext to i64
155// Pb_4 = (%IDX/2)*16 + 32 #0 | GEP, multiply index by sizeof(4) for floats
156// Pb_5 = (%IDX/2)*16 + 16 #0 | GEP, add offset of leading components
157//
158// Pb_5 - Pa_5 = 16 #0 | subtract to get the offset
159//
160// Remark: %PTR is not maintained within this class. So in this instance the
161// offset of 16 can only be assumed if the pointers are equal.
162//
163class Polynomial {
164 /// Operations on B
165 enum BOps {
166 LShr,
167 Mul,
168 SExt,
169 Trunc,
170 };
171
172 /// Number of Error Bits e
173 unsigned ErrorMSBs = (unsigned)-1;
174
175 /// Value
176 Value *V = nullptr;
177
178 /// Coefficient B
180
181 /// Coefficient A
182 APInt A;
183
184public:
185 Polynomial(Value *V) : V(V) {
186 IntegerType *Ty = dyn_cast<IntegerType>(V->getType());
187 if (Ty) {
188 ErrorMSBs = 0;
189 this->V = V;
190 A = APInt(Ty->getBitWidth(), 0);
191 }
192 }
193
194 Polynomial(const APInt &A, unsigned ErrorMSBs = 0)
195 : ErrorMSBs(ErrorMSBs), A(A) {}
196
197 Polynomial(unsigned BitWidth, uint64_t A, unsigned ErrorMSBs = 0)
198 : ErrorMSBs(ErrorMSBs), A(BitWidth, A) {}
199
200 Polynomial() = default;
201
202 /// Increment and clamp the number of undefined bits.
203 void incErrorMSBs(unsigned amt) {
204 if (ErrorMSBs == (unsigned)-1)
205 return;
206
207 ErrorMSBs += amt;
208 if (ErrorMSBs > A.getBitWidth())
209 ErrorMSBs = A.getBitWidth();
210 }
211
212 /// Decrement and clamp the number of undefined bits.
213 void decErrorMSBs(unsigned amt) {
214 if (ErrorMSBs == (unsigned)-1)
215 return;
216
217 if (ErrorMSBs > amt)
218 ErrorMSBs -= amt;
219 else
220 ErrorMSBs = 0;
221 }
222
223 /// Apply an add on the polynomial
224 Polynomial &add(const APInt &C) {
225 // Note: Addition is associative in two's complement even when in case of
226 // signed overflow.
227 //
228 // Error bits can only propagate into higher significant bits. As these are
229 // already regarded as undefined, there is no change.
230 //
231 // Theorem: Adding a constant to a polynomial does not change the error
232 // term.
233 //
234 // Proof:
235 //
236 // Since the addition is associative and commutes:
237 //
238 // (B + A + E*2^(n-e)) + C = B + (A + C) + E*2^(n-e)
239 // [qed]
240
241 if (C.getBitWidth() != A.getBitWidth()) {
242 ErrorMSBs = (unsigned)-1;
243 return *this;
244 }
245
246 A += C;
247 return *this;
248 }
249
250 /// Apply a multiplication onto the polynomial.
251 Polynomial &mul(const APInt &C) {
252 // Note: Multiplication distributes over the addition
253 //
254 // Theorem: Multiplication distributes over the addition
255 //
256 // Proof(1):
257 //
258 // (B+A)*C =-
259 // = (B + A) + (B + A) + .. {C Times}
260 // addition is associative and commutes, hence
261 // = B + B + .. {C Times} .. + A + A + .. {C times}
262 // = B*C + A*C
263 // (see (function add) for signed values and overflows)
264 // [qed]
265 //
266 // Theorem: If C has c trailing zeros, errors bits in A or B are shifted out
267 // to the left.
268 //
269 // Proof(2):
270 //
271 // Let B' and A' be the n-Bit inputs with some unknown errors EA,
272 // EB at e leading bits. B' and A' can be written down as:
273 //
274 // B' = B + 2^(n-e)*EB
275 // A' = A + 2^(n-e)*EA
276 //
277 // Let C' be an input with c trailing zero bits. C' can be written as
278 //
279 // C' = C*2^c
280 //
281 // Therefore we can compute the result by using distributivity and
282 // commutativity.
283 //
284 // (B'*C' + A'*C') = [B + 2^(n-e)*EB] * C' + [A + 2^(n-e)*EA] * C' =
285 // = [B + 2^(n-e)*EB + A + 2^(n-e)*EA] * C' =
286 // = (B'+A') * C' =
287 // = [B + 2^(n-e)*EB + A + 2^(n-e)*EA] * C' =
288 // = [B + A + 2^(n-e)*EB + 2^(n-e)*EA] * C' =
289 // = (B + A) * C' + [2^(n-e)*EB + 2^(n-e)*EA)] * C' =
290 // = (B + A) * C' + [2^(n-e)*EB + 2^(n-e)*EA)] * C*2^c =
291 // = (B + A) * C' + C*(EB + EA)*2^(n-e)*2^c =
292 //
293 // Let EC be the final error with EC = C*(EB + EA)
294 //
295 // = (B + A)*C' + EC*2^(n-e)*2^c =
296 // = (B + A)*C' + EC*2^(n-(e-c))
297 //
298 // Since EC is multiplied by 2^(n-(e-c)) the resulting error contains c
299 // less error bits than the input. c bits are shifted out to the left.
300 // [qed]
301
302 if (C.getBitWidth() != A.getBitWidth()) {
303 ErrorMSBs = (unsigned)-1;
304 return *this;
305 }
306
307 // Multiplying by one is a no-op.
308 if (C.isOne()) {
309 return *this;
310 }
311
312 // Multiplying by zero removes the coefficient B and defines all bits.
313 if (C.isZero()) {
314 ErrorMSBs = 0;
315 deleteB();
316 }
317
318 // See Proof(2): Trailing zero bits indicate a left shift. This removes
319 // leading bits from the result even if they are undefined.
320 decErrorMSBs(C.countr_zero());
321
322 A *= C;
323 pushBOperation(Mul, C);
324 return *this;
325 }
326
327 /// Apply a logical shift right on the polynomial
328 Polynomial &lshr(const APInt &C) {
329 // Theorem(1): (B + A + E*2^(n-e)) >> 1 => (B >> 1) + (A >> 1) + E'*2^(n-e')
330 // where
331 // e' = e + 1,
332 // E is a e-bit number,
333 // E' is a e'-bit number,
334 // holds under the following precondition:
335 // pre(1): A % 2 = 0
336 // pre(2): e < n, (see Theorem(2) for the trivial case with e=n)
337 // where >> expresses a logical shift to the right, with adding zeros.
338 //
339 // We need to show that for every, E there is a E'
340 //
341 // B = b_h * 2^(n-1) + b_m * 2 + b_l
342 // A = a_h * 2^(n-1) + a_m * 2 (pre(1))
343 //
344 // where a_h, b_h, b_l are single bits, and a_m, b_m are (n-2) bit numbers
345 //
346 // Let X = (B + A + E*2^(n-e)) >> 1
347 // Let Y = (B >> 1) + (A >> 1) + E*2^(n-e) >> 1
348 //
349 // X = [B + A + E*2^(n-e)] >> 1 =
350 // = [ b_h * 2^(n-1) + b_m * 2 + b_l +
351 // + a_h * 2^(n-1) + a_m * 2 +
352 // + E * 2^(n-e) ] >> 1 =
353 //
354 // The sum is built by putting the overflow of [a_m + b+n] into the term
355 // 2^(n-1). As there are no more bits beyond 2^(n-1) the overflow within
356 // this bit is discarded. This is expressed by % 2.
357 //
358 // The bit in position 0 cannot overflow into the term (b_m + a_m).
359 //
360 // = [ ([b_h + a_h + (b_m + a_m) >> (n-2)] % 2) * 2^(n-1) +
361 // + ((b_m + a_m) % 2^(n-2)) * 2 +
362 // + b_l + E * 2^(n-e) ] >> 1 =
363 //
364 // The shift is computed by dividing the terms by 2 and by cutting off
365 // b_l.
366 //
367 // = ([b_h + a_h + (b_m + a_m) >> (n-2)] % 2) * 2^(n-2) +
368 // + ((b_m + a_m) % 2^(n-2)) +
369 // + E * 2^(n-(e+1)) =
370 //
371 // by the definition in the Theorem e+1 = e'
372 //
373 // = ([b_h + a_h + (b_m + a_m) >> (n-2)] % 2) * 2^(n-2) +
374 // + ((b_m + a_m) % 2^(n-2)) +
375 // + E * 2^(n-e') =
376 //
377 // Compute Y by applying distributivity first
378 //
379 // Y = (B >> 1) + (A >> 1) + E*2^(n-e') =
380 // = (b_h * 2^(n-1) + b_m * 2 + b_l) >> 1 +
381 // + (a_h * 2^(n-1) + a_m * 2) >> 1 +
382 // + E * 2^(n-e) >> 1 =
383 //
384 // Again, the shift is computed by dividing the terms by 2 and by cutting
385 // off b_l.
386 //
387 // = b_h * 2^(n-2) + b_m +
388 // + a_h * 2^(n-2) + a_m +
389 // + E * 2^(n-(e+1)) =
390 //
391 // Again, the sum is built by putting the overflow of [a_m + b+n] into
392 // the term 2^(n-1). But this time there is room for a second bit in the
393 // term 2^(n-2) we add this bit to a new term and denote it o_h in a
394 // second step.
395 //
396 // = ([b_h + a_h + (b_m + a_m) >> (n-2)] >> 1) * 2^(n-1) +
397 // + ([b_h + a_h + (b_m + a_m) >> (n-2)] % 2) * 2^(n-2) +
398 // + ((b_m + a_m) % 2^(n-2)) +
399 // + E * 2^(n-(e+1)) =
400 //
401 // Let o_h = [b_h + a_h + (b_m + a_m) >> (n-2)] >> 1
402 // Further replace e+1 by e'.
403 //
404 // = o_h * 2^(n-1) +
405 // + ([b_h + a_h + (b_m + a_m) >> (n-2)] % 2) * 2^(n-2) +
406 // + ((b_m + a_m) % 2^(n-2)) +
407 // + E * 2^(n-e') =
408 //
409 // Move o_h into the error term and construct E'. To ensure that there is
410 // no 2^x with negative x, this step requires pre(2) (e < n).
411 //
412 // = ([b_h + a_h + (b_m + a_m) >> (n-2)] % 2) * 2^(n-2) +
413 // + ((b_m + a_m) % 2^(n-2)) +
414 // + o_h * 2^(e'-1) * 2^(n-e') + | pre(2), move 2^(e'-1)
415 // | out of the old exponent
416 // + E * 2^(n-e') =
417 // = ([b_h + a_h + (b_m + a_m) >> (n-2)] % 2) * 2^(n-2) +
418 // + ((b_m + a_m) % 2^(n-2)) +
419 // + [o_h * 2^(e'-1) + E] * 2^(n-e') + | move 2^(e'-1) out of
420 // | the old exponent
421 //
422 // Let E' = o_h * 2^(e'-1) + E
423 //
424 // = ([b_h + a_h + (b_m + a_m) >> (n-2)] % 2) * 2^(n-2) +
425 // + ((b_m + a_m) % 2^(n-2)) +
426 // + E' * 2^(n-e')
427 //
428 // Because X and Y are distinct only in there error terms and E' can be
429 // constructed as shown the theorem holds.
430 // [qed]
431 //
432 // For completeness in case of the case e=n it is also required to show that
433 // distributivity can be applied.
434 //
435 // In this case Theorem(1) transforms to (the pre-condition on A can also be
436 // dropped)
437 //
438 // Theorem(2): (B + A + E) >> 1 => (B >> 1) + (A >> 1) + E'
439 // where
440 // A, B, E, E' are two's complement numbers with the same bit
441 // width
442 //
443 // Let A + B + E = X
444 // Let (B >> 1) + (A >> 1) = Y
445 //
446 // Therefore we need to show that for every X and Y there is an E' which
447 // makes the equation
448 //
449 // X = Y + E'
450 //
451 // hold. This is trivially the case for E' = X - Y.
452 //
453 // [qed]
454 //
455 // Remark: Distributing lshr with and arbitrary number n can be expressed as
456 // ((((B + A) lshr 1) lshr 1) ... ) {n times}.
457 // This construction induces n additional error bits at the left.
458
459 if (C.getBitWidth() != A.getBitWidth()) {
460 ErrorMSBs = (unsigned)-1;
461 return *this;
462 }
463
464 if (C.isZero())
465 return *this;
466
467 // Test if the result will be zero
468 unsigned shiftAmt = C.getZExtValue();
469 if (shiftAmt >= C.getBitWidth())
470 return mul(APInt(C.getBitWidth(), 0));
471
472 // The proof that shiftAmt LSBs are zero for at least one summand is only
473 // possible for the constant number.
474 //
475 // If this can be proven add shiftAmt to the error counter
476 // `ErrorMSBs`. Otherwise set all bits as undefined.
477 if (A.countr_zero() < shiftAmt)
478 ErrorMSBs = A.getBitWidth();
479 else
480 incErrorMSBs(shiftAmt);
481
482 // Apply the operation.
483 pushBOperation(LShr, C);
484 A = A.lshr(shiftAmt);
485
486 return *this;
487 }
488
489 /// Apply a sign-extend or truncate operation on the polynomial.
490 Polynomial &sextOrTrunc(unsigned n) {
491 if (n < A.getBitWidth()) {
492 // Truncate: Clearly undefined Bits on the MSB side are removed
493 // if there are any.
494 decErrorMSBs(A.getBitWidth() - n);
495 A = A.trunc(n);
496 pushBOperation(Trunc, APInt(sizeof(n) * 8, n));
497 }
498 if (n > A.getBitWidth()) {
499 // Extend: Clearly extending first and adding later is different
500 // to adding first and extending later in all extended bits.
501 incErrorMSBs(n - A.getBitWidth());
502 A = A.sext(n);
503 pushBOperation(SExt, APInt(sizeof(n) * 8, n));
504 }
505
506 return *this;
507 }
508
509 /// Test if there is a coefficient B.
510 bool isFirstOrder() const { return V != nullptr; }
511
512 /// Test coefficient B of two Polynomials are equal.
513 bool isCompatibleTo(const Polynomial &o) const {
514 // The polynomial use different bit width.
515 if (A.getBitWidth() != o.A.getBitWidth())
516 return false;
517
518 // If neither Polynomial has the Coefficient B.
519 if (!isFirstOrder() && !o.isFirstOrder())
520 return true;
521
522 // The index variable is different.
523 if (V != o.V)
524 return false;
525
526 // Check the operations.
527 if (B.size() != o.B.size())
528 return false;
529
530 auto *ob = o.B.begin();
531 for (const auto &b : B) {
532 if (b != *ob)
533 return false;
534 ob++;
535 }
536
537 return true;
538 }
539
540 /// Subtract two polynomials, return an undefined polynomial if
541 /// subtraction is not possible.
542 Polynomial operator-(const Polynomial &o) const {
543 // Return an undefined polynomial if incompatible.
544 if (!isCompatibleTo(o))
545 return Polynomial();
546
547 // If the polynomials are compatible (meaning they have the same
548 // coefficient on B), B is eliminated. Thus a polynomial solely
549 // containing A is returned
550 return Polynomial(A - o.A, std::max(ErrorMSBs, o.ErrorMSBs));
551 }
552
553 /// Subtract a constant from a polynomial,
554 Polynomial operator-(uint64_t C) const {
555 Polynomial Result(*this);
556 Result.A -= C;
557 return Result;
558 }
559
560 /// Add a constant to a polynomial,
561 Polynomial operator+(uint64_t C) const {
562 Polynomial Result(*this);
563 Result.A += C;
564 return Result;
565 }
566
567 /// Returns true if it can be proven that two Polynomials are equal.
568 bool isProvenEqualTo(const Polynomial &o) const {
569 // Subtract both polynomials and test if it is fully defined and zero.
570 Polynomial r = *this - o;
571 return (r.ErrorMSBs == 0) && (!r.isFirstOrder()) && (r.A.isZero());
572 }
573
574 /// Returns true if every bit of the polynomial is provably exact. An inexact
575 /// polynomial can never be proven equal to another, so it is never a valid
576 /// match candidate.
577 bool isProvenExact() const { return ErrorMSBs == 0; }
578
579 /// Hash the identity checked by isProvenEqualTo. Only meaningful for exact
580 /// polynomials; two exact, proven-equal polynomials hash identically.
581 friend hash_code hash_value(const Polynomial &P) {
582 hash_code H = hash_combine(P.A.getBitWidth(), P.V);
583 for (const auto &BO : P.B)
584 H = hash_combine(H, BO.first, hash_value(BO.second));
585 return hash_combine(H, hash_value(P.A));
586 }
587
588 /// Print the polynomial into a stream.
589 void print(raw_ostream &OS) const {
590 OS << "[{#ErrBits:" << ErrorMSBs << "} ";
591
592 if (V) {
593 for (auto b : B)
594 OS << "(";
595 OS << "(" << *V << ") ";
596
597 for (auto b : B) {
598 switch (b.first) {
599 case LShr:
600 OS << "LShr ";
601 break;
602 case Mul:
603 OS << "Mul ";
604 break;
605 case SExt:
606 OS << "SExt ";
607 break;
608 case Trunc:
609 OS << "Trunc ";
610 break;
611 }
612
613 OS << b.second << ") ";
614 }
615 }
616
617 OS << "+ " << A << "]";
618 }
619
620private:
621 void deleteB() {
622 V = nullptr;
623 B.clear();
624 }
625
626 void pushBOperation(const BOps Op, const APInt &C) {
627 if (isFirstOrder()) {
628 B.push_back(std::make_pair(Op, C));
629 return;
630 }
631 }
632};
633
634#ifndef NDEBUG
635static raw_ostream &operator<<(raw_ostream &OS, const Polynomial &S) {
636 S.print(OS);
637 return OS;
638}
639#endif
640
641/// Address key of a candidate's first vector element: the common base pointer,
642/// the vector type and the offset polynomial. Candidates are matched one basic
643/// block at a time, so the block is implicit in the index. Two candidates
644/// belong to the same interleaved group iff their keys agree on everything but
645/// the constant offset, so consecutive elements are located by building the
646/// neighbouring keys and looking them up.
647struct OffsetKey {
648 Value *PV;
649 FixedVectorType *VTy;
650 Polynomial Ofs;
651
652 bool operator==(const OffsetKey &O) const {
653 return PV == O.PV && VTy == O.VTy && Ofs.isProvenEqualTo(O.Ofs);
654 }
655};
656
657struct OffsetKeyHash {
658 size_t operator()(const OffsetKey &K) const {
659 return hash_combine(K.PV, K.VTy, hash_value(K.Ofs));
660 }
661};
662
663/// VectorInfo stores abstract the following information for each vector
664/// element:
665///
666/// 1) The memory address loaded into the element as Polynomial
667/// 2) a set of load instruction necessary to construct the vector,
668/// 3) a set of all other instructions that are necessary to create the vector and
669/// 4) a pointer value that can be used as relative base for all elements.
670struct VectorInfo {
671private:
672 VectorInfo(const VectorInfo &c) : VTy(c.VTy) {
674 "Copying VectorInfo is neither implemented nor necessary,");
675 }
676
677public:
678 /// Information of a Vector Element
679 struct ElementInfo {
680 /// Offset Polynomial.
681 Polynomial Ofs;
682
683 /// The Load Instruction used to Load the entry. LI is null if the pointer
684 /// of the load instruction does not point on to the entry
685 LoadInst *LI;
686
687 ElementInfo(Polynomial Offset = Polynomial(), LoadInst *LI = nullptr)
688 : Ofs(Offset), LI(LI) {}
689 };
690
691 /// Basic-block the load instructions are within
692 BasicBlock *BB = nullptr;
693
694 /// Pointer value of all participation load instructions
695 Value *PV = nullptr;
696
697 /// Participating load instructions
698 std::set<LoadInst *> LIs;
699
700 /// Participating instructions
701 std::set<Instruction *> Is;
702
703 /// Final shuffle-vector instruction
704 ShuffleVectorInst *SVI = nullptr;
705
706 /// Information of the offset for each vector element
707 ElementInfo *EI;
708
709 /// Vector Type
710 FixedVectorType *const VTy;
711
712 VectorInfo(FixedVectorType *VTy) : VTy(VTy) {
713 EI = new ElementInfo[VTy->getNumElements()];
714 }
715
716 VectorInfo &operator=(const VectorInfo &other) = delete;
717
718 virtual ~VectorInfo() { delete[] EI; }
719
720 unsigned getDimension() const { return VTy->getNumElements(); }
721
722 /// Test if the VectorInfo can be part of an interleaved load with the
723 /// specified factor.
724 ///
725 /// \param Factor of the interleave
726 /// \param DL Targets Datalayout
727 ///
728 /// \returns true if this is possible and false if not
729 bool isInterleaved(unsigned Factor, const DataLayout &DL) const {
730 unsigned Size = DL.getTypeAllocSize(VTy->getElementType());
731 for (unsigned i = 1; i < getDimension(); i++) {
732 if (!EI[i].Ofs.isProvenEqualTo(EI[0].Ofs + i * Factor * Size)) {
733 return false;
734 }
735 }
736 return true;
737 }
738
739 /// Recursively computes the vector information stored in V.
740 ///
741 /// This function delegates the work to specialized implementations
742 ///
743 /// \param V Value to operate on
744 /// \param Result Result of the computation
745 ///
746 /// \returns false if no sensible information can be gathered.
747 static bool compute(Value *V, VectorInfo &Result, const DataLayout &DL) {
749 if (SVI)
750 return computeFromSVI(SVI, Result, DL);
752 if (LI)
753 return computeFromLI(LI, Result, DL);
755 if (BCI)
756 return computeFromBCI(BCI, Result, DL);
757 return false;
758 }
759
760 /// BitCastInst specialization to compute the vector information.
761 ///
762 /// \param BCI BitCastInst to operate on
763 /// \param Result Result of the computation
764 ///
765 /// \returns false if no sensible information can be gathered.
766 static bool computeFromBCI(BitCastInst *BCI, VectorInfo &Result,
767 const DataLayout &DL) {
769
770 if (!Op)
771 return false;
772
774 if (!VTy)
775 return false;
776
777 // We can only cast from large to smaller vectors
778 if (Result.VTy->getNumElements() % VTy->getNumElements())
779 return false;
780
781 unsigned Factor = Result.VTy->getNumElements() / VTy->getNumElements();
782 unsigned NewSize = DL.getTypeAllocSize(Result.VTy->getElementType());
783 unsigned OldSize = DL.getTypeAllocSize(VTy->getElementType());
784
785 if (NewSize * Factor != OldSize)
786 return false;
787
788 VectorInfo Old(VTy);
789 if (!compute(Op, Old, DL))
790 return false;
791
792 for (unsigned i = 0; i < Result.VTy->getNumElements(); i += Factor) {
793 for (unsigned j = 0; j < Factor; j++) {
794 Result.EI[i + j] =
795 ElementInfo(Old.EI[i / Factor].Ofs + j * NewSize,
796 j == 0 ? Old.EI[i / Factor].LI : nullptr);
797 }
798 }
799
800 Result.BB = Old.BB;
801 Result.PV = Old.PV;
802 Result.LIs.insert(Old.LIs.begin(), Old.LIs.end());
803 Result.Is.insert(Old.Is.begin(), Old.Is.end());
804 Result.Is.insert(BCI);
805 Result.SVI = nullptr;
806
807 return true;
808 }
809
810 /// ShuffleVectorInst specialization to compute vector information.
811 ///
812 /// \param SVI ShuffleVectorInst to operate on
813 /// \param Result Result of the computation
814 ///
815 /// Compute the left and the right side vector information and merge them by
816 /// applying the shuffle operation. This function also ensures that the left
817 /// and right side have compatible loads. This means that all loads are with
818 /// in the same basic block and are based on the same pointer.
819 ///
820 /// \returns false if no sensible information can be gathered.
821 static bool computeFromSVI(ShuffleVectorInst *SVI, VectorInfo &Result,
822 const DataLayout &DL) {
823 FixedVectorType *ArgTy =
825
826 // Compute the left hand vector information.
827 VectorInfo LHS(ArgTy);
828 if (!compute(SVI->getOperand(0), LHS, DL))
829 LHS.BB = nullptr;
830
831 // Compute the right hand vector information.
832 VectorInfo RHS(ArgTy);
833 if (!compute(SVI->getOperand(1), RHS, DL))
834 RHS.BB = nullptr;
835
836 // Neither operand produced sensible results?
837 if (!LHS.BB && !RHS.BB)
838 return false;
839 // Only RHS produced sensible results?
840 else if (!LHS.BB) {
841 Result.BB = RHS.BB;
842 Result.PV = RHS.PV;
843 }
844 // Only LHS produced sensible results?
845 else if (!RHS.BB) {
846 Result.BB = LHS.BB;
847 Result.PV = LHS.PV;
848 }
849 // Both operands produced sensible results?
850 else if ((LHS.BB == RHS.BB) && (LHS.PV == RHS.PV)) {
851 Result.BB = LHS.BB;
852 Result.PV = LHS.PV;
853 }
854 // Both operands produced sensible results but they are incompatible.
855 else {
856 return false;
857 }
858
859 // Merge and apply the operation on the offset information.
860 if (LHS.BB) {
861 Result.LIs.insert(LHS.LIs.begin(), LHS.LIs.end());
862 Result.Is.insert(LHS.Is.begin(), LHS.Is.end());
863 }
864 if (RHS.BB) {
865 Result.LIs.insert(RHS.LIs.begin(), RHS.LIs.end());
866 Result.Is.insert(RHS.Is.begin(), RHS.Is.end());
867 }
868 Result.Is.insert(SVI);
869 Result.SVI = SVI;
870
871 int j = 0;
872 for (int i : SVI->getShuffleMask()) {
873 assert((i < 2 * (signed)ArgTy->getNumElements()) &&
874 "Invalid ShuffleVectorInst (index out of bounds)");
875
876 if (i < 0)
877 Result.EI[j] = ElementInfo();
878 else if (i < (signed)ArgTy->getNumElements()) {
879 if (LHS.BB)
880 Result.EI[j] = LHS.EI[i];
881 else
882 Result.EI[j] = ElementInfo();
883 } else {
884 if (RHS.BB)
885 Result.EI[j] = RHS.EI[i - ArgTy->getNumElements()];
886 else
887 Result.EI[j] = ElementInfo();
888 }
889 j++;
890 }
891
892 return true;
893 }
894
895 /// LoadInst specialization to compute vector information.
896 ///
897 /// This function also acts as abort condition to the recursion.
898 ///
899 /// \param LI LoadInst to operate on
900 /// \param Result Result of the computation
901 ///
902 /// \returns false if no sensible information can be gathered.
903 static bool computeFromLI(LoadInst *LI, VectorInfo &Result,
904 const DataLayout &DL) {
905 Value *BasePtr;
906 Polynomial Offset;
907
908 if (LI->isVolatile())
909 return false;
910
911 if (LI->isAtomic())
912 return false;
913
914 if (!DL.typeSizeEqualsStoreSize(Result.VTy->getElementType()))
915 return false;
916
917 // Get the base polynomial
918 computePolynomialFromPointer(*LI->getPointerOperand(), Offset, BasePtr, DL);
919
920 Result.BB = LI->getParent();
921 Result.PV = BasePtr;
922 Result.LIs.insert(LI);
923 Result.Is.insert(LI);
924
925 for (unsigned i = 0; i < Result.getDimension(); i++) {
926 Value *Idx[2] = {
927 ConstantInt::get(Type::getInt32Ty(LI->getContext()), 0),
928 ConstantInt::get(Type::getInt32Ty(LI->getContext()), i),
929 };
930 int64_t Ofs = DL.getIndexedOffsetInType(Result.VTy, Idx);
931 Result.EI[i] = ElementInfo(Offset + Ofs, i == 0 ? LI : nullptr);
932 }
933
934 return true;
935 }
936
937 /// Recursively compute polynomial of a value.
938 ///
939 /// \param BO Input binary operation
940 /// \param Result Result polynomial
941 static void computePolynomialBinOp(BinaryOperator &BO, Polynomial &Result) {
942 Value *LHS = BO.getOperand(0);
943 Value *RHS = BO.getOperand(1);
944
945 // Find the RHS Constant if any
947 if ((!C) && BO.isCommutative()) {
949 if (C)
950 std::swap(LHS, RHS);
951 }
952
953 switch (BO.getOpcode()) {
954 case Instruction::Add:
955 if (!C)
956 break;
957
958 computePolynomial(*LHS, Result);
959 Result.add(C->getValue());
960 return;
961
962 case Instruction::LShr:
963 if (!C)
964 break;
965
966 computePolynomial(*LHS, Result);
967 Result.lshr(C->getValue());
968 return;
969
970 default:
971 break;
972 }
973
974 Result = Polynomial(&BO);
975 }
976
977 /// Recursively compute polynomial of a value
978 ///
979 /// \param V input value
980 /// \param Result result polynomial
981 static void computePolynomial(Value &V, Polynomial &Result) {
982 if (auto *BO = dyn_cast<BinaryOperator>(&V))
983 computePolynomialBinOp(*BO, Result);
984 else
985 Result = Polynomial(&V);
986 }
987
988 /// Compute the Polynomial representation of a Pointer type.
989 ///
990 /// \param Ptr input pointer value
991 /// \param Result result polynomial
992 /// \param BasePtr pointer the polynomial is based on
993 /// \param DL Datalayout of the target machine
994 static void computePolynomialFromPointer(Value &Ptr, Polynomial &Result,
995 Value *&BasePtr,
996 const DataLayout &DL) {
997 // Not a pointer type? Return an undefined polynomial
999 if (!PtrTy) {
1000 Result = Polynomial();
1001 BasePtr = nullptr;
1002 return;
1003 }
1004 unsigned PointerBits =
1005 DL.getIndexSizeInBits(PtrTy->getPointerAddressSpace());
1006
1007 /// Skip pointer casts. Return Zero polynomial otherwise
1008 if (isa<CastInst>(&Ptr)) {
1009 CastInst &CI = *cast<CastInst>(&Ptr);
1010 switch (CI.getOpcode()) {
1011 case Instruction::BitCast:
1012 computePolynomialFromPointer(*CI.getOperand(0), Result, BasePtr, DL);
1013 break;
1014 default:
1015 BasePtr = &Ptr;
1016 Polynomial(PointerBits, 0);
1017 break;
1018 }
1019 }
1020 /// Resolve GetElementPtrInst.
1021 else if (isa<GetElementPtrInst>(&Ptr)) {
1023
1024 APInt BaseOffset(PointerBits, 0);
1025
1026 // Check if we can compute the Offset with accumulateConstantOffset
1027 if (GEP.accumulateConstantOffset(DL, BaseOffset)) {
1028 Result = Polynomial(BaseOffset);
1029 BasePtr = GEP.getPointerOperand();
1030 return;
1031 } else {
1032 // Otherwise we allow that the last index operand of the GEP is
1033 // non-constant.
1034 unsigned idxOperand, e;
1036 for (idxOperand = 1, e = GEP.getNumOperands(); idxOperand < e;
1037 idxOperand++) {
1038 ConstantInt *IDX = dyn_cast<ConstantInt>(GEP.getOperand(idxOperand));
1039 if (!IDX)
1040 break;
1041 Indices.push_back(IDX);
1042 }
1043
1044 // It must also be the last operand.
1045 if (idxOperand + 1 != e) {
1046 Result = Polynomial();
1047 BasePtr = nullptr;
1048 return;
1049 }
1050
1051 // Compute the polynomial of the index operand.
1052 computePolynomial(*GEP.getOperand(idxOperand), Result);
1053
1054 // Compute base offset from zero based index, excluding the last
1055 // variable operand.
1056 BaseOffset =
1057 DL.getIndexedOffsetInType(GEP.getSourceElementType(), Indices);
1058
1059 // Apply the operations of GEP to the polynomial.
1060 unsigned ResultSize = DL.getTypeAllocSize(GEP.getResultElementType());
1061 Result.sextOrTrunc(PointerBits);
1062 Result.mul(APInt(PointerBits, ResultSize));
1063 Result.add(BaseOffset);
1064 BasePtr = GEP.getPointerOperand();
1065 }
1066 }
1067 // All other instructions are handled by using the value as base pointer and
1068 // a zero polynomial.
1069 else {
1070 BasePtr = &Ptr;
1071 Polynomial(DL.getIndexSizeInBits(PtrTy->getPointerAddressSpace()), 0);
1072 }
1073 }
1074
1075#ifndef NDEBUG
1076 void print(raw_ostream &OS) const {
1077 if (PV)
1078 OS << *PV;
1079 else
1080 OS << "(none)";
1081 OS << " + ";
1082 for (unsigned i = 0; i < getDimension(); i++)
1083 OS << ((i == 0) ? "[" : ", ") << EI[i].Ofs;
1084 OS << "]";
1085 }
1086#endif
1087};
1088
1089} // anonymous namespace
1090
1091LoadInst *
1092InterleavedLoadCombineImpl::findFirstLoad(const std::set<LoadInst *> &LIs) {
1093 assert(!LIs.empty() && "No load instructions given.");
1094
1095 // All LIs are within the same BB. Select the first for a reference.
1096 BasicBlock *BB = (*LIs.begin())->getParent();
1098 *BB, [&LIs](Instruction &I) -> bool { return is_contained(LIs, &I); });
1099 assert(FLI != BB->end());
1100
1101 return cast<LoadInst>(FLI);
1102}
1103
1104bool InterleavedLoadCombineImpl::combine(ArrayRef<VectorInfo *> InterleavedLoad,
1105 OptimizationRemarkEmitter &ORE) {
1106 LLVM_DEBUG(dbgs() << "Checking interleaved load\n");
1107
1108 // The insertion point is the LoadInst which loads the first values. The
1109 // following tests are used to proof that the combined load can be inserted
1110 // just before InsertionPoint.
1111 LoadInst *InsertionPoint = InterleavedLoad.front()->EI[0].LI;
1112
1113 // Test if the offset is computed
1114 if (!InsertionPoint)
1115 return false;
1116
1117 std::set<LoadInst *> LIs;
1118 std::set<Instruction *> Is;
1119 std::set<Instruction *> SVIs;
1120
1121 InstructionCost InterleavedCost;
1124
1125 // Get the interleave factor
1126 unsigned Factor = InterleavedLoad.size();
1127
1128 // Merge all input sets used in analysis
1129 for (const VectorInfo *VI : InterleavedLoad) {
1130 // Generate a set of all load instructions to be combined
1131 LIs.insert(VI->LIs.begin(), VI->LIs.end());
1132
1133 // Generate a set of all instructions taking part in load
1134 // interleaved. This list excludes the instructions necessary for the
1135 // polynomial construction.
1136 Is.insert(VI->Is.begin(), VI->Is.end());
1137
1138 // Generate the set of the final ShuffleVectorInst.
1139 SVIs.insert(VI->SVI);
1140 }
1141
1142 // There is nothing to combine.
1143 if (LIs.size() < 2)
1144 return false;
1145
1146 // Test if all participating instruction will be dead after the
1147 // transformation. If intermediate results are used, no performance gain can
1148 // be expected. Also sum the cost of the Instructions beeing left dead.
1149 for (const auto &I : Is) {
1150 // Compute the old cost
1152
1153 // The final SVIs are allowed not to be dead, all uses will be replaced
1154 if (SVIs.find(I) != SVIs.end())
1155 continue;
1156
1157 // If there are users outside the set to be eliminated, we abort the
1158 // transformation. No gain can be expected.
1159 for (auto *U : I->users()) {
1160 if (Is.find(dyn_cast<Instruction>(U)) == Is.end())
1161 return false;
1162 }
1163 }
1164
1165 // We need to have a valid cost in order to proceed.
1166 if (!InstructionCost.isValid())
1167 return false;
1168
1169 // We know that all LoadInst are within the same BB. This guarantees that
1170 // either everything or nothing is loaded.
1171 LoadInst *First = findFirstLoad(LIs);
1172
1173 // To be safe that the loads can be combined, iterate over all loads and test
1174 // that the corresponding defining access dominates first LI. This guarantees
1175 // that there are no aliasing stores in between the loads.
1176 auto FMA = MSSA.getMemoryAccess(First);
1177 for (auto *LI : LIs) {
1178 auto MADef = MSSA.getMemoryAccess(LI)->getDefiningAccess();
1179 if (!MSSA.dominates(MADef, FMA))
1180 return false;
1181 }
1182 assert(!LIs.empty() && "There are no LoadInst to combine");
1183
1184 // It is necessary that insertion point dominates all final ShuffleVectorInst.
1185 for (const VectorInfo *VI : InterleavedLoad) {
1186 if (!DT.dominates(InsertionPoint, VI->SVI))
1187 return false;
1188 }
1189
1190 // All checks are done. Add instructions detectable by InterleavedAccessPass
1191 // The old instruction will are left dead.
1192 IRBuilder<> Builder(InsertionPoint);
1193 Type *ETy = InterleavedLoad.front()->SVI->getType()->getElementType();
1194 unsigned ElementsPerSVI =
1195 cast<FixedVectorType>(InterleavedLoad.front()->SVI->getType())
1196 ->getNumElements();
1197 FixedVectorType *ILTy = FixedVectorType::get(ETy, Factor * ElementsPerSVI);
1198
1199 auto Indices = llvm::to_vector<4>(llvm::seq<unsigned>(0, Factor));
1200 InterleavedCost = TTI.getInterleavedMemoryOpCost(
1201 Instruction::Load, ILTy, Factor, Indices, InsertionPoint->getAlign(),
1202 InsertionPoint->getPointerAddressSpace(), CostKind);
1203
1204 if (InterleavedCost >= InstructionCost) {
1205 return false;
1206 }
1207
1208 // Create the wide load and update the MemorySSA.
1209 auto Ptr = InsertionPoint->getPointerOperand();
1210 auto LI = Builder.CreateAlignedLoad(ILTy, Ptr, InsertionPoint->getAlign(),
1211 "interleaved.wide.load");
1212 auto MSSAU = MemorySSAUpdater(&MSSA);
1213 MemoryUse *MSSALoad = cast<MemoryUse>(MSSAU.createMemoryAccessBefore(
1214 LI, nullptr, MSSA.getMemoryAccess(InsertionPoint)));
1215 MSSAU.insertUse(MSSALoad, /*RenameUses=*/ true);
1216
1217 // Create the final SVIs and replace all uses.
1218 int i = 0;
1219 for (const VectorInfo *VI : InterleavedLoad) {
1220 SmallVector<int, 4> Mask;
1221 for (unsigned j = 0; j < ElementsPerSVI; j++)
1222 Mask.push_back(i + j * Factor);
1223
1224 Builder.SetInsertPoint(VI->SVI);
1225 auto SVI = Builder.CreateShuffleVector(LI, Mask, "interleaved.shuffle");
1226 VI->SVI->replaceAllUsesWith(SVI);
1227 i++;
1228 }
1229
1230 NumInterleavedLoadCombine++;
1231 ORE.emit([&]() {
1232 return OptimizationRemark(DEBUG_TYPE, "Combined Interleaved Load", LI)
1233 << "Load interleaved combined with factor "
1234 << ore::NV("Factor", Factor);
1235 });
1236
1237 return true;
1238}
1239
1240bool InterleavedLoadCombineImpl::run() {
1241 OptimizationRemarkEmitter ORE(&F);
1242 bool changed = false;
1243 unsigned MaxFactor = TLI.getMaxSupportedInterleaveFactor();
1244
1245 auto &DL = F.getDataLayout();
1246
1247 // Start with the highest factor to avoid combining and recombining.
1248 for (unsigned Factor = MaxFactor; Factor >= 2; Factor--) {
1249 // Matching only ever pairs candidates from the same block, so process one
1250 // block at a time and keep the candidate list and offset index small.
1251 for (BasicBlock &BB : F) {
1252 std::list<VectorInfo> Candidates;
1253 for (Instruction &I : BB) {
1254 auto *SVI = dyn_cast<ShuffleVectorInst>(&I);
1255 if (!SVI)
1256 continue;
1257
1258 // We don't support scalable vectors in this pass.
1259 if (isa<ScalableVectorType>(SVI->getType()))
1260 continue;
1261
1262 Candidates.emplace_back(cast<FixedVectorType>(SVI->getType()));
1263
1264 if (!VectorInfo::computeFromSVI(SVI, Candidates.back(), DL)) {
1265 Candidates.pop_back();
1266 continue;
1267 }
1268
1269 if (!Candidates.back().isInterleaved(Factor, DL))
1270 Candidates.pop_back();
1271 }
1272
1273 // Index every candidate whose first element has a provably exact offset
1274 // by its address key. Finding an interleaved group then only needs
1275 // lookups of the neighbouring keys. The key embeds a Polynomial, which
1276 // has no natural empty/tombstone value, so use std::unordered_map rather
1277 // than DenseMap.
1278 std::unordered_map<OffsetKey, SmallVector<VectorInfo *, 1>, OffsetKeyHash>
1279 OffsetMap;
1280 for (VectorInfo &C : Candidates) {
1281 if (!C.EI[0].Ofs.isProvenExact())
1282 continue;
1283 OffsetMap[{C.PV, C.VTy, C.EI[0].Ofs}].push_back(&C);
1284 }
1285
1286 // Candidates already combined (a whole group) or dropped (a failed base).
1287 SmallPtrSet<const VectorInfo *, 16> Consumed;
1288
1289 // Return the last still-available candidate registered under Key.
1290 // Iterating in reverse makes a later duplicate offset win over an earlier
1291 // one.
1292 auto FindNeighbor = [&](const OffsetKey &Key) -> VectorInfo * {
1293 auto It = OffsetMap.find(Key);
1294 if (It == OffsetMap.end())
1295 return nullptr;
1296 for (VectorInfo *Cand : reverse(It->second))
1297 if (!Consumed.contains(Cand))
1298 return Cand;
1299 return nullptr;
1300 };
1301
1302 for (VectorInfo &C0 : Candidates) {
1303 if (Consumed.contains(&C0) || !C0.EI[0].Ofs.isProvenExact())
1304 continue;
1305
1306 unsigned Size = DL.getTypeAllocSize(C0.VTy->getElementType());
1307
1308 // Collect C0 and its Factor - 1 consecutive neighbours.
1310 Group.push_back(&C0);
1311 for (unsigned i = 1; i < Factor; i++) {
1312 VectorInfo *Nb =
1313 FindNeighbor({C0.PV, C0.VTy, C0.EI[0].Ofs + i * Size});
1314 if (!Nb)
1315 break;
1316 Group.push_back(Nb);
1317 }
1318 if (Group.size() != Factor)
1319 continue;
1320
1321 if (combine(Group, ORE)) {
1322 // The whole group is combined and left dead.
1323 Consumed.insert(Group.begin(), Group.end());
1324 changed = true;
1325 } else {
1326 // Drop only the base; keep its neighbours available as future bases.
1327 Consumed.insert(&C0);
1328 }
1329 }
1330 }
1331 }
1332
1333 return changed;
1334}
1335
1336namespace {
1337/// This pass combines interleaved loads into a pattern detectable by
1338/// InterleavedAccessPass.
1339struct InterleavedLoadCombine : public FunctionPass {
1340 static char ID;
1341
1342 InterleavedLoadCombine() : FunctionPass(ID) {}
1343
1344 StringRef getPassName() const override {
1345 return "Interleaved Load Combine Pass";
1346 }
1347
1348 bool runOnFunction(Function &F) override {
1349 if (DisableInterleavedLoadCombine)
1350 return false;
1351
1352 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
1353 if (!TPC)
1354 return false;
1355
1356 LLVM_DEBUG(dbgs() << "*** " << getPassName() << ": " << F.getName()
1357 << "\n");
1358
1359 return InterleavedLoadCombineImpl(
1360 F, getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
1361 getAnalysis<MemorySSAWrapperPass>().getMSSA(),
1362 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F),
1363 TPC->getTM<TargetMachine>())
1364 .run();
1365 }
1366
1367 void getAnalysisUsage(AnalysisUsage &AU) const override {
1368 AU.addRequired<MemorySSAWrapperPass>();
1369 AU.addRequired<DominatorTreeWrapperPass>();
1370 AU.addRequired<TargetTransformInfoWrapperPass>();
1371 FunctionPass::getAnalysisUsage(AU);
1372 }
1373
1374private:
1375};
1376} // anonymous namespace
1377
1378PreservedAnalyses
1380
1381 auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
1382 auto &MemSSA = FAM.getResult<MemorySSAAnalysis>(F).getMSSA();
1383 auto &TTI = FAM.getResult<TargetIRAnalysis>(F);
1384 bool Changed = InterleavedLoadCombineImpl(F, DT, MemSSA, TTI, *TM).run();
1386}
1387
1388char InterleavedLoadCombine::ID = 0;
1389
1391 InterleavedLoadCombine, DEBUG_TYPE,
1392 "Combine interleaved loads into wide loads and shufflevector instructions",
1393 false, false)
1398 InterleavedLoadCombine, DEBUG_TYPE,
1399 "Combine interleaved loads into wide loads and shufflevector instructions",
1401
1404 auto P = new InterleavedLoadCombine();
1405 return P;
1406}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
static bool runOnFunction(Function &F, bool PostInlining)
#define DEBUG_TYPE
Hexagon Common GEP
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define H(x, y, z)
Definition MD5.cpp:56
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
#define P(N)
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
static DominatorTree getDomTree(Function &F)
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallPtrSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
This pass exposes codegen information to IR-level passes.
Value * RHS
Value * LHS
BinaryOperator * Mul
Class for arbitrary precision integers.
Definition APInt.h:78
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:377
AnalysisUsage & addRequired()
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator end()
Definition BasicBlock.h:459
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
BinaryOps getOpcode() const
Definition InstrTypes.h:409
This class represents a no-op cast from one type to another.
This is the base class for all instructions that perform data casts.
Definition InstrTypes.h:512
Instruction::CastOps getOpcode() const
Return the opcode of this CastInst.
Definition InstrTypes.h:674
This is the shared class of boolean and integer constants.
Definition Constants.h:87
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Analysis pass which computes a DominatorTree.
Definition Dominators.h:241
Legacy analysis pass which computes a DominatorTree.
Definition Dominators.h:277
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:867
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
LLVM_ABI bool isCommutative() const LLVM_READONLY
Return true if the instruction is commutative:
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
Class to represent integer types.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Value * getPointerOperand()
bool isVolatile() const
Return true if this is a load from a volatile memory location.
Align getAlign() const
Return the alignment of the access that is being performed.
An analysis that produces MemorySSA for a function.
Definition MemorySSA.h:922
Legacy analysis pass which computes MemorySSA.
Definition MemorySSA.h:975
Encapsulates MemorySSA, including all data associated with memory accesses.
Definition MemorySSA.h:702
LLVM_ABI bool dominates(const MemoryAccess *A, const MemoryAccess *B) const
Given two memory accesses in potentially different blocks, determine whether MemoryAccess A dominates...
MemoryUseOrDef * getMemoryAccess(const Instruction *I) const
Given a memory Mod/Ref'ing instruction, get the MemorySSA access associated with it.
Definition MemorySSA.h:720
MemoryAccess * getDefiningAccess() const
Get the access that produces the memory state used by this Use.
Definition MemorySSA.h:260
The optimization diagnostic interface.
LLVM_ABI void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
This instruction constructs a fixed permutation of two input vectors.
static LLVM_ABI void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Analysis pass providing the TargetTransformInfo.
virtual unsigned getMaxSupportedInterleaveFactor() const
Get the maximum supported factor for interleaved memory accesses.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
virtual const TargetLowering * getTargetLowering() const
Wrapper pass for TargetTransformInfo.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
LLVM_ABI InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const
TargetCostKind
The kind of cost model.
@ TCK_SizeAndLatency
The weighted sum of size and latency.
LLVM_ABI InstructionCost getInstructionCost(const User *U, ArrayRef< const Value * > Operands, TargetCostKind CostKind) const
Estimate the cost of a given IR user when lowered.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:258
Type * getElementType() const
An opaque object representing a hash code.
Definition Hashing.h:77
const ParentTy * getParent() const
Definition ilist_node.h:34
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:520
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
initializer< Ty > init(const Ty &Val)
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
hash_code hash_value(const FixedPointSemantics &Val)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
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:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
TargetTransformInfo TTI
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1772
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
APInt operator-(APInt)
Definition APInt.h:2215
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
APInt operator+(APInt a, const APInt &b)
Definition APInt.h:2220
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition Hashing.h:307
LLVM_ABI FunctionPass * createInterleavedLoadCombinePass()
InterleavedLoadCombines Pass - This pass identifies interleaved loads and combines them into wide loa...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880