|
22 | 22 | #include "llvm/ADT/STLExtras.h" |
23 | 23 | #include "llvm/ADT/SmallSet.h" |
24 | 24 | #include "llvm/ADT/SmallVector.h" |
| 25 | +#include "llvm/Analysis/AliasAnalysis.h" |
25 | 26 | #include "llvm/CodeGen/CFIInstBuilder.h" |
26 | 27 | #include "llvm/CodeGen/LivePhysRegs.h" |
27 | 28 | #include "llvm/CodeGen/MachineBasicBlock.h" |
@@ -7413,35 +7414,51 @@ static bool getMiscPatterns(MachineInstr &Root, |
7413 | 7414 | return false; |
7414 | 7415 | } |
7415 | 7416 |
|
7416 | | -/// Check if there are any stores or calls between two instructions in the same |
7417 | | -/// basic block. |
7418 | | -static bool hasInterveningStoreOrCall(const MachineInstr *First, |
7419 | | - const MachineInstr *Last) { |
| 7417 | +/// Collect all loads, stores and calls between `First` and `Last`. |
| 7418 | +/// `First` and `Last` must be within the same MBB. |
| 7419 | +static void getMemOps(const MachineInstr *First, const MachineInstr *Last, |
| 7420 | + SmallVectorImpl<const MachineInstr *> &MemOps) { |
7420 | 7421 | if (!First || !Last || First == Last) |
7421 | | - return false; |
| 7422 | + return; |
7422 | 7423 |
|
7423 | 7424 | // Both instructions must be in the same basic block. |
7424 | 7425 | if (First->getParent() != Last->getParent()) |
7425 | | - return false; |
| 7426 | + return; |
7426 | 7427 |
|
7427 | | - // Sanity check that First comes before Last. |
7428 | 7428 | const MachineBasicBlock *MBB = First->getParent(); |
7429 | 7429 | auto InstrIt = First->getIterator(); |
7430 | 7430 | auto LastIt = Last->getIterator(); |
| 7431 | + MemOps.push_back(First); |
7431 | 7432 |
|
7432 | 7433 | for (; InstrIt != MBB->end(); ++InstrIt) { |
7433 | 7434 | if (InstrIt == LastIt) |
7434 | 7435 | break; |
7435 | 7436 |
|
7436 | 7437 | // Check for stores or calls that could interfere |
7437 | | - if (InstrIt->mayStore() || InstrIt->isCall()) |
7438 | | - return true; |
| 7438 | + if (InstrIt->mayLoadOrStore() || InstrIt->isCall()) |
| 7439 | + MemOps.push_back(&*InstrIt); |
7439 | 7440 | } |
7440 | 7441 |
|
7441 | | - // If we reached the end of the basic block, our instructions must have not |
7442 | | - // been ordered correctly and the analysis is invalid. |
7443 | | - assert(InstrIt != MBB->end() && |
| 7442 | + // If we have not iterated to `Last` the instructions must have not been |
| 7443 | + // ordered correctly. |
| 7444 | + assert(&*InstrIt == Last && |
7444 | 7445 | "Got bad machine instructions, First should come before Last!"); |
| 7446 | + |
| 7447 | + MemOps.push_back(Last); |
| 7448 | +} |
| 7449 | + |
| 7450 | +/// Check if a given MachineInstr `MIa` may alias with any of the instructions |
| 7451 | +/// in `MemInstrs`. |
| 7452 | +static bool mayAlias(const MachineInstr &MIa, |
| 7453 | + SmallVectorImpl<const MachineInstr *> &MemInstrs, |
| 7454 | + AliasAnalysis *AA) { |
| 7455 | + for (const MachineInstr *MIb : MemInstrs) { |
| 7456 | + if (MIa.mayAlias(AA, *MIb, /*UseTBAA*/ false)) { |
| 7457 | + MIb->dump(); |
| 7458 | + return true; |
| 7459 | + } |
| 7460 | + } |
| 7461 | + |
7445 | 7462 | return false; |
7446 | 7463 | } |
7447 | 7464 |
|
@@ -7539,9 +7556,14 @@ static bool getGatherPattern(MachineInstr &Root, |
7539 | 7556 |
|
7540 | 7557 | const MachineInstr *FirstLoad = SortedLoads.front(); |
7541 | 7558 | const MachineInstr *LastLoad = SortedLoads.back(); |
| 7559 | + SmallVector<const MachineInstr *, 16> MemOps = {}; |
| 7560 | + getMemOps(FirstLoad, LastLoad, MemOps); |
7542 | 7561 |
|
7543 | | - if (hasInterveningStoreOrCall(FirstLoad, LastLoad)) |
7544 | | - return false; |
| 7562 | + // If there is any chance of aliasing, do not apply the pattern. |
| 7563 | + for (const MachineInstr *MemInstr : MemOps) { |
| 7564 | + if (mayAlias(*MemInstr, MemOps, nullptr)) |
| 7565 | + return false; |
| 7566 | + } |
7545 | 7567 |
|
7546 | 7568 | switch (NumLanes) { |
7547 | 7569 | case 4: |
|
0 commit comments