Index: lib/Transforms/Scalar/EarlyCSE.cpp =================================================================== --- lib/Transforms/Scalar/EarlyCSE.cpp +++ lib/Transforms/Scalar/EarlyCSE.cpp @@ -562,13 +562,20 @@ if (!MSSA) return false; + // If MemorySSA has determined that one of EarlierInst or LaterInst does not + // read/write memory, then we can safely return true here. + MemoryAccess *EarlierMA = MSSA->getMemoryAccess(EarlierInst); + MemoryAccess *LaterMA = MSSA->getMemoryAccess(LaterInst); + if (!EarlierMA || !LaterMA) + return true; + // Since we know LaterDef dominates LaterInst and EarlierInst dominates // LaterInst, if LaterDef dominates EarlierInst then it can't occur between // EarlierInst and LaterInst and neither can any other write that potentially // clobbers LaterInst. MemoryAccess *LaterDef = MSSA->getWalker()->getClobberingMemoryAccess(LaterInst); - return MSSA->dominates(LaterDef, MSSA->getMemoryAccess(EarlierInst)); + return MSSA->dominates(LaterDef, EarlierMA); } bool EarlyCSE::processNode(DomTreeNode *Node) { Index: test/Transforms/EarlyCSE/globalsaa-memoryssa.ll =================================================================== --- /dev/null +++ test/Transforms/EarlyCSE/globalsaa-memoryssa.ll @@ -0,0 +1,23 @@ +; RUN: opt < %s -S -globals-aa -early-cse-memssa | FileCheck %s + +define i16 @f1() readonly { + ret i16 0 +} + +declare void @f2() + +; Check that EarlyCSE correctly handles function calls that don't have +; a MemoryAccess. In this case the calls to @f1 have no +; MemoryAccesses since globals-aa determines that @f1 doesn't +; read/write memory at all. + +; CHECK-LABEL: @f3( +; CHECK-NEXT: %call1 = call i16 @f1() +; CHECK-NEXT: call void @f2() +; CHECK-NEXT ret void +define void @f3() { + %call1 = call i16 @f1() + call void @f2() + %call2 = call i16 @f1() + ret void +}