Index: include/llvm/CodeGen/MachineFunction.h =================================================================== --- include/llvm/CodeGen/MachineFunction.h +++ include/llvm/CodeGen/MachineFunction.h @@ -661,6 +661,13 @@ MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, int64_t Offset, uint64_t Size); + /// getMachineMemOperand - Allocate a new MachineMemOperand by copying + /// an existing one, replacing only AliasAnalysis information. + /// MachineMemOperands are owned by the MachineFunction and need not be + /// explicitly deallocated. + MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, + const AAMDNodes &AAInfo); + using OperandCapacity = ArrayRecycler::Capacity; /// Allocate an array of MachineOperands. This is only intended for use by Index: include/llvm/CodeGen/MachineInstr.h =================================================================== --- include/llvm/CodeGen/MachineInstr.h +++ include/llvm/CodeGen/MachineInstr.h @@ -379,6 +379,9 @@ return NumMemRefs == 1; } + /// Return the number of memory operands. + unsigned getNumMemOperands() const { return NumMemRefs; } + /// API for querying MachineInstr properties. They are the same as MCInstrDesc /// queries but they are bundle aware. Index: include/llvm/CodeGen/ScheduleDAGInstrs.h =================================================================== --- include/llvm/CodeGen/ScheduleDAGInstrs.h +++ include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -83,6 +83,11 @@ unsigned getSparseSetIndex() const { return Reg; } }; + /// Helper function for tracking a Value to a reference to a known object. + void getUnderlyingObjects(const Value *V, + SmallVectorImpl &Objects, + const DataLayout &DL); + /// Use a SparseMultiSet to track physical registers. Storage is only /// allocated once for the pass. It can be cleared in constant time and reused /// without any frees. Index: lib/CodeGen/MachineFunction.cpp =================================================================== --- lib/CodeGen/MachineFunction.cpp +++ lib/CodeGen/MachineFunction.cpp @@ -330,6 +330,20 @@ MMO->getOrdering(), MMO->getFailureOrdering()); } +MachineMemOperand * +MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO, + const AAMDNodes &AAInfo) { + MachinePointerInfo MPI = MMO->getValue() ? + MachinePointerInfo(MMO->getValue(), MMO->getOffset()) : + MachinePointerInfo(MMO->getPseudoValue(), MMO->getOffset()); + + return new (Allocator) + MachineMemOperand(MPI, MMO->getFlags(), MMO->getSize(), + MMO->getBaseAlignment(), AAInfo, + MMO->getRanges(), MMO->getSyncScopeID(), + MMO->getOrdering(), MMO->getFailureOrdering()); +} + MachineInstr::mmo_iterator MachineFunction::allocateMemRefsArray(unsigned long Num) { return Allocator.Allocate(Num); Index: lib/CodeGen/ScheduleDAGInstrs.cpp =================================================================== --- lib/CodeGen/ScheduleDAGInstrs.cpp +++ lib/CodeGen/ScheduleDAGInstrs.cpp @@ -151,9 +151,9 @@ /// This is a wrapper around GetUnderlyingObjects and adds support for basic /// ptrtoint+arithmetic+inttoptr sequences. -static void getUnderlyingObjects(const Value *V, - SmallVectorImpl &Objects, - const DataLayout &DL) { +void llvm::getUnderlyingObjects(const Value *V, + SmallVectorImpl &Objects, + const DataLayout &DL) { SmallPtrSet Visited; SmallVector Working(1, V); do { Index: lib/CodeGen/StackColoring.cpp =================================================================== --- lib/CodeGen/StackColoring.cpp +++ lib/CodeGen/StackColoring.cpp @@ -37,6 +37,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/ScheduleDAGInstrs.h" // for getUnderlyingObjects #include "llvm/CodeGen/SlotIndexes.h" #include "llvm/CodeGen/StackProtector.h" #include "llvm/CodeGen/WinEHFuncInfo.h" @@ -889,6 +890,10 @@ // Keep a list of *allocas* which need to be remapped. DenseMap Allocas; + + // Keep a list of allocas which has been affected by the remap. + SmallPtrSet MergedAllocas; + for (const std::pair &SI : SlotRemap) { const AllocaInst *From = MFI->getObjectAllocation(SI.first); const AllocaInst *To = MFI->getObjectAllocation(SI.second); @@ -908,6 +913,12 @@ Inst = Cast; } + // We keep both slots to maintain TBAA metadata later. + // FIXME: It is conservative. We can keep TBAA metadata + // if TBAA information of two slots match. + MergedAllocas.insert(From); + MergedAllocas.insert(To); + // Allow the stack protector to adjust its value map to account for the // upcoming replacement. SP->adjustForColoring(From, To); @@ -939,13 +950,6 @@ // Update the MachineMemOperand to use the new alloca. for (MachineMemOperand *MMO : I.memoperands()) { - // FIXME: In order to enable the use of TBAA when using AA in CodeGen, - // we'll also need to update the TBAA nodes in MMOs with values - // derived from the merged allocas. When doing this, we'll need to use - // the same variant of GetUnderlyingObjects that is used by the - // instruction scheduler (that can look through ptrtoint/inttoptr - // pairs). - // We've replaced IR-level uses of the remapped allocas, so we only // need to replace direct uses here. const AllocaInst *AI = dyn_cast_or_null(MMO->getValue()); @@ -997,6 +1001,49 @@ MO.setIndex(ToSlot); FixedInstr++; } + + // We adjust TBAA information for merged stack slots. + MachineSDNode::mmo_iterator MemOps = + MF->allocateMemRefsArray(I.getNumMemOperands()); + unsigned MemOpIdx = 0; + bool ReplaceMemOps = false; + for (MachineMemOperand *MMO : I.memoperands()) { + // If this memory location can be a slot remapped here, + // we remove TBAA information since two objects of different types + // may share the same memory location. + bool MayModified = false; + if (MMO->getAAInfo().TBAA) { + if (const Value *MMOV = MMO->getValue()) { + SmallVector Objs; + getUnderlyingObjects(MMOV, Objs, MF->getDataLayout()); + + if (Objs.empty()) + MayModified = true; + else + for (Value *V : Objs) { + const AllocaInst *AI = dyn_cast_or_null(V); + if (AI && MergedAllocas.count(AI)) { + MayModified = true; + break; + } + } + } + } + if (MayModified) { + // We eliminate information on TBAA from the existing AAInfo. + AAMDNodes NewAAInfo = AAMDNodes(nullptr, MMO->getAAInfo().Scope, + MMO->getAAInfo().NoAlias); + MemOps[MemOpIdx++] = MF->getMachineMemOperand(MMO, NewAAInfo); + ReplaceMemOps = true; + } + else + MemOps[MemOpIdx++] = MMO; + } + + // If any memory operand is updated, set memory references of + // this instruction. + if (ReplaceMemOps) + I.setMemRefs(std::make_pair(MemOps, I.getNumMemOperands())); } // Update the location of C++ catch objects for the MSVC personality routine.