Index: lib/Target/ARM/ARMLoadStoreOptimizer.cpp =================================================================== --- lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -32,6 +32,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterClassInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/IR/DataLayout.h" @@ -1961,6 +1962,7 @@ static char ID; ARMPreAllocLoadStoreOpt() : MachineFunctionPass(ID) {} + AliasAnalysis *AA; const DataLayout *TD; const TargetInstrInfo *TII; const TargetRegisterInfo *TRI; @@ -1974,6 +1976,11 @@ return ARM_PREALLOC_LOAD_STORE_OPT_NAME; } + virtual void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); + } + private: bool CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, DebugLoc &dl, unsigned &NewOpc, unsigned &EvenReg, @@ -2003,6 +2010,7 @@ TRI = STI->getRegisterInfo(); MRI = &Fn.getRegInfo(); MF = &Fn; + AA = &getAnalysis().getAAResults(); bool Modified = false; for (MachineBasicBlock &MFI : Fn) @@ -2016,7 +2024,8 @@ MachineBasicBlock::iterator E, SmallPtrSetImpl &MemOps, SmallSet &MemRegs, - const TargetRegisterInfo *TRI) { + const TargetRegisterInfo *TRI, + AliasAnalysis *AA) { // Are there stores / loads / calls between them? // FIXME: This is overly conservative. We should make use of alias information // some day. @@ -2026,18 +2035,10 @@ continue; if (I->isCall() || I->isTerminator() || I->hasUnmodeledSideEffects()) return false; - if (isLd && I->mayStore()) - return false; - if (!isLd) { - if (I->mayLoad()) - return false; - // It's not safe to move the first 'str' down. - // str r1, [r0] - // strh r5, [r0] - // str r4, [r0, #+4] - if (I->mayStore()) - return false; - } + if (I->mayStore() || (!isLd && I->mayLoad())) + for (MachineInstr *MemOp : MemOps) + if (I->mayAlias(AA, *MemOp, /*UseTBAA*/ false)) + return false; for (unsigned j = 0, NumOps = I->getNumOperands(); j != NumOps; ++j) { MachineOperand &MO = I->getOperand(j); if (!MO.isReg()) @@ -2212,7 +2213,7 @@ bool DoMove = (LastLoc - FirstLoc) <= NumMove*4; // FIXME: Tune this. if (DoMove) DoMove = IsSafeAndProfitableToMove(isLd, Base, FirstOp, LastOp, - MemOps, MemRegs, TRI); + MemOps, MemRegs, TRI, AA); if (!DoMove) { for (unsigned i = 0; i != NumMove; ++i) Ops.pop_back(); Index: test/CodeGen/ARM/ldrd.ll =================================================================== --- test/CodeGen/ARM/ldrd.ll +++ test/CodeGen/ARM/ldrd.ll @@ -189,5 +189,23 @@ ret i32* %p1 } +; CHECK-LABEL: ldrd_strd_aa: +; NORMAL: ldrd [[TMP1:r[0-9]]], [[TMP2:r[0-9]]], +; NORMAL: strd [[TMP1]], [[TMP2]], +; CONSERVATIVE-NOT: ldrd +; CONSERVATIVE-NOT: strd +; CHECK: bx lr + +define void @ldrd_strd_aa(i32* noalias nocapture %x, i32* noalias nocapture readonly %y) { +entry: + %0 = load i32, i32* %y, align 4 + store i32 %0, i32* %x, align 4 + %arrayidx2 = getelementptr inbounds i32, i32* %y, i32 1 + %1 = load i32, i32* %arrayidx2, align 4 + %arrayidx3 = getelementptr inbounds i32, i32* %x, i32 1 + store i32 %1, i32* %arrayidx3, align 4 + ret void +} + declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind