Index: llvm/include/llvm/CodeGen/TargetInstrInfo.h =================================================================== --- llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -189,7 +189,27 @@ bool isReallyTriviallyReMaterializableGeneric(const MachineInstr &MI, AAResults *AA) const; + /// If the value of base address contained in this memory operand is constant, + /// update it to `BaseAddr` and return true. Otherwise, return false. + bool getConstantBaseAddress(const MachineMemOperand *MMO, + uint64_t &BaseAddr) const; + + /// Return true if two machine memory operands access different memory + /// addresses and false otherwise. + bool areMemOperandsTriviallyDisjoint(const MachineMemOperand *MMOa, + const MachineMemOperand *MMOb) const; + public: + /// Provide a target independent method using machine memory operands + /// to check whether two instructions can alias. This function expects + /// one instruction will write to memory at least. + /// + /// Return true if two instructions access different memory addresses + /// and false otherwise. + bool + areMemOperandsTriviallyDisjoint(ArrayRef MMOpsA, + ArrayRef MMOpsB) const; + /// These methods return the opcode of the frame setup/destroy instructions /// if they exist (-1 otherwise). Some targets use pseudo instructions in /// order to abstract away the difference between operating with a frame @@ -1802,7 +1822,8 @@ "MIa must load from or modify a memory location"); assert(MIb.mayLoadOrStore() && "MIb must load from or modify a memory location"); - return false; + return areMemOperandsTriviallyDisjoint(MIa.memoperands(), + MIb.memoperands()); } /// Return the value to use for the MachineCSE's LookAheadLimit, Index: llvm/lib/CodeGen/TargetInstrInfo.cpp =================================================================== --- llvm/lib/CodeGen/TargetInstrInfo.cpp +++ llvm/lib/CodeGen/TargetInstrInfo.cpp @@ -12,6 +12,7 @@ #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Analysis/MemoryLocation.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -1431,3 +1432,84 @@ return true; } + +bool TargetInstrInfo::getConstantBaseAddress(const MachineMemOperand *MMO, + uint64_t &BaseAddr) const { + 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; +} + +bool TargetInstrInfo::areMemOperandsTriviallyDisjoint( + const MachineMemOperand *MMOa, const MachineMemOperand *MMOb) const { + // 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); +} + +bool TargetInstrInfo::areMemOperandsTriviallyDisjoint( + ArrayRef MMOpsA, + ArrayRef MMOpsB) const { + // If there is an instruction without machine memory operands, + // conservatively assume that they may access the same memory addresses. + if (MMOpsA.empty() || MMOpsB.empty()) { + return false; + } + + // 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; +}