Index: include/llvm/Transforms/Utils/LoopUtils.h =================================================================== --- include/llvm/Transforms/Utils/LoopUtils.h +++ include/llvm/Transforms/Utils/LoopUtils.h @@ -376,6 +376,10 @@ DominatorTree *, Loop *, AliasSetTracker *, LICMSafetyInfo *); +/// \brief Check whether a constant expression is used by any instruction +/// in a given loop. +bool isConstantExprUsedInLoop(ConstantExpr* CE, Loop *CurLoop); + /// \brief Computes safety information for a loop /// checks loop body & header for the possibility of may throw /// exception, it takes LICMSafetyInfo and loop as argument. Index: lib/Transforms/Scalar/LICM.cpp =================================================================== --- lib/Transforms/Scalar/LICM.cpp +++ lib/Transforms/Scalar/LICM.cpp @@ -837,6 +837,28 @@ }; } // end anon namespace +/// Check whether a constant expression is used by any instruction +/// in a given loop. This, unforunately, requires a recursive lookup. +bool llvm::isConstantExprUsedInLoop(ConstantExpr *CE, Loop *CurLoop) { + SmallVector WorkList; + WorkList.push_back(CE); + + while (!WorkList.empty()) { + auto Curr = WorkList.pop_back_val(); + // We only care if the user is an instruction or a constant expression. + // Check if instructions are in the loop, and recurse down ConstantExpr. + for (auto U : Curr->users()) { + if (auto UI = dyn_cast(U)) { + if (CurLoop->contains(UI)) + return true; + } else if (auto UCE = dyn_cast(U)) + WorkList.push_back(UCE); + } + } + + return false; +} + /// Try to promote memory values to scalars by sinking stores out of the /// loop and moving loads to before the loop. We do this by looping over /// the stores in the loop, looking for stores to Must pointers which are @@ -907,6 +929,14 @@ return Changed; for (User *U : ASIV->users()) { + // If we encounter a constant expression which is used by an instruction + // inside the loop, bail. + // FIXME: This is somewhat too conservative, but for now, err on the side + // of correctness. + if (auto UCE = dyn_cast(U)) + if (isConstantExprUsedInLoop(UCE, CurLoop)) + return Changed; + // Ignore instructions that are outside the loop. Instruction *UI = dyn_cast(U); if (!UI || !CurLoop->contains(UI)) Index: test/Transforms/LICM/pr26843.ll =================================================================== --- test/Transforms/LICM/pr26843.ll +++ test/Transforms/LICM/pr26843.ll @@ -0,0 +1,32 @@ +; RUN: opt -S -basicaa -licm < %s | FileCheck %s + +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i686-pc-windows-msvc18.0.0" + +@v = common global [4 x i32] zeroinitializer, align 4 + +; Make sure the store to v[1] is not sunk past the memset to v[1]-v[3]. +; CHECK-LABEL: @main +; CHECK: for.body: +; CHECK-NEXT: store i32 1, i32* getelementptr inbounds ([4 x i32], [4 x i32]* @v, i32 0, i32 1) +; CHECK-NEXT: tail call void @llvm.memset +; CHECK: end: +; CHECK-NEXT: ret i32 0 + +define i32 @main(i1 %k) { +entry: + br label %for.body + +for.body: + store i32 1, i32* getelementptr inbounds ([4 x i32], [4 x i32]* @v, i32 0, i32 1), align 4 + tail call void @llvm.memset.p0i8.i32(i8* bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @v, i32 0, i32 1) to i8*), i8 0, i32 12, i32 4, i1 false) + br label %for.latch + +for.latch: + br i1 %k, label %for.body, label %end + +end: + ret i32 0 +} + +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1)