Index: lib/Transforms/Scalar/LICM.cpp =================================================================== --- lib/Transforms/Scalar/LICM.cpp +++ lib/Transforms/Scalar/LICM.cpp @@ -1191,30 +1191,39 @@ } else { // MSSAU if (isOnlyMemoryAccess(SI, CurLoop, MSSAU)) return true; + // If there are more accesses than the Promotion cap, give up, we're not + // walking a list that long. + if (NoOfMemAccTooLarge) + return false; + // Check store only if there's still "quota" to check clobber. if (*LicmMssaOptCounter < LicmMssaOptCap) { - auto *Source = MSSA->getSkipSelfWalker()->getClobberingMemoryAccess(SI); - (*LicmMssaOptCounter)++; - // If there are no clobbering Defs in the loop, we still need to check - // for interfering Uses. If there are more accesses than the Promotion - // cap, give up, we're not walking a list that long. Otherwise, walk the - // list, check each Use if it's optimized to an access outside the loop. - // If yes, store is safe to hoist. This is fairly restrictive, but - // conservatively correct. + // If there are interfering Uses (i.e. their defining access is in the + // loop), or ordered loads (stored as Defs!), don't move this store. + // Could do better here, but this is conservatively correct. // TODO: Cache set of Uses on the first walk in runOnLoop, update when // moving accesses. Can also extend to dominating uses. - if ((!MSSA->isLiveOnEntryDef(Source) && - CurLoop->contains(Source->getBlock())) || - NoOfMemAccTooLarge) - return false; for (auto *BB : CurLoop->getBlocks()) if (auto *Accesses = MSSA->getBlockAccesses(BB)) - for (const auto &MA : *Accesses) + for (const auto &MA : *Accesses) { if (const auto *MU = dyn_cast(&MA)) { auto *MD = MU->getDefiningAccess(); if (!MSSA->isLiveOnEntryDef(MD) && CurLoop->contains(MD->getBlock())) return false; + } else { + if (const auto *MD = dyn_cast(&MA)) + if (auto *LI= dyn_cast(MD->getMemoryInst())) + if (!LI->isUnordered()) + return false; } + } + + auto *Source = MSSA->getSkipSelfWalker()->getClobberingMemoryAccess(SI); + (*LicmMssaOptCounter)++; + // If there are no clobbering Defs in the loop, store is safe to hoist. + if (!MSSA->isLiveOnEntryDef(Source) && + CurLoop->contains(Source->getBlock())) + return false; return true; } return false; Index: test/Transforms/LICM/hoist-debuginvariant.ll =================================================================== --- test/Transforms/LICM/hoist-debuginvariant.ll +++ test/Transforms/LICM/hoist-debuginvariant.ll @@ -1,6 +1,6 @@ ; RUN: opt < %s -licm -S | FileCheck %s ; RUN: opt < %s -strip-debug -licm -S | FileCheck %s -; RUN: opt < %s -licm -enable-mssa-loop-dependency=true -verify-memoryssa -S | FileCheck %s --check-prefixes=CHECK,MSSA +; RUN: opt < %s -licm -enable-mssa-loop-dependency=true -verify-memoryssa -S | FileCheck %s --check-prefixes=CHECK target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -17,7 +17,6 @@ ; CHECK-NEXT: [[_TMP2:%.*]] = load i32, i32* @a, align 4 ; CHECK-NEXT: [[_TMP3:%.*]] = load i32, i32* @b, align 4 ; CHECK-NEXT: [[_TMP4:%.*]] = sdiv i32 [[_TMP2]], [[_TMP3]] -; MSSA-NEXT: store i32 [[_TMP4:%.*]], i32* @c, align 4 ; CHECK-NEXT: br label [[BB3:%.*]] br label %bb3