diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -1211,6 +1211,89 @@ return true; } +// If the value of base address contained in this memory operand is constant, +// update it to `BaseAddr` and return true. Otherwise, return false. +static bool getConstantBaseAddress(const MachineMemOperand *MMO, + uint64_t &BaseAddr) { + const Value *Val = MMO->getValue(); + + if (!Val) { + return false; + } + + if (auto *CE = dyn_cast(Val)) { + if (CE->getOpcode() == Instruction::IntToPtr && + isa(CE->getOperand(0))) { + auto Op0 = dyn_cast(CE->getOperand(0)); + BaseAddr = Op0->getUniqueInteger().getZExtValue(); + return true; + } + } + + return false; +} + +// Return true if two memory operands access different memory addresses and +// false otherwise. +static bool areMemOperandsTriviallyDisjoint(const MachineMemOperand *MMOa, + const MachineMemOperand *MMOb) { + // If memory accesses come from different address spaces, they are trivially + // disjoint. + if (MMOa->getAddrSpace() != MMOb->getAddrSpace()) { + return true; + } + + // Skip if the base address is not constant. + uint64_t BaseAddrA = 0; + uint64_t BaseAddrB = 0; + if (!getConstantBaseAddress(MMOa, BaseAddrA) || + !getConstantBaseAddress(MMOb, BaseAddrB)) { + return false; + } + + // Skip if the offset from the base address is negative. + const int64_t OffsetA = MMOa->getOffset(); + const int64_t OffsetB = MMOb->getOffset(); + if (OffsetA < 0 || OffsetB < 0) { + return false; + } + + // Skip if the size of the memory reference is unknown. + const uint64_t WidthA = MMOa->getSize(); + const uint64_t WidthB = MMOb->getSize(); + if (WidthA == MemoryLocation::UnknownSize || + WidthB == MemoryLocation::UnknownSize) { + return false; + } + + // Check memory accesses whether overlap. + const auto StartAddrA = BaseAddrA + OffsetA; + const auto EndAddrA = StartAddrA + WidthA; + const auto StartAddrB = BaseAddrB + OffsetB; + const auto EndAddrB = StartAddrB + WidthB; + return std::max(StartAddrA, StartAddrB) >= std::min(EndAddrA, EndAddrB); +} + +// Return true if two instructions access different memory addresses and false +// otherwise. +static bool +areMemOperandsTriviallyDisjoint(ArrayRef MMOpsA, + ArrayRef MMOpsB) { + assert(!MMOpsA.empty() && !MMOpsB.empty()); + + // Check each pair of memory operands from both instructions, which are + // disjoint only if all pairs won't access the same memory addresses. + for (auto MMOa : MMOpsA) { + for (auto MMOb : MMOpsB) { + if (!areMemOperandsTriviallyDisjoint(MMOa, MMOb)) { + return false; + } + } + } + + return true; +} + static bool MemOperandsHaveAlias(const MachineFrameInfo &MFI, AAResults *AA, bool UseTBAA, const MachineMemOperand *MMOa, const MachineMemOperand *MMOb) { @@ -1312,6 +1395,9 @@ if (NumChecks > TII->getMemOperandAACheckLimit()) return true; + if (areMemOperandsTriviallyDisjoint(memoperands(), Other.memoperands())) + return false; + // Check each pair of memory operands from both instructions, which can't // alias only if all pairs won't alias. for (auto *MMOa : memoperands())