diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake index b8e9dbe29d88db95826ef99a71b4d0aabd2dc7a0..8be5d4ba52c29a12227aee5adb8ab076a0f97c61 100644 --- a/llvm/cmake/modules/HandleLLVMOptions.cmake +++ b/llvm/cmake/modules/HandleLLVMOptions.cmake @@ -120,6 +120,14 @@ else() set(LLVM_ENABLE_AUTOTUNER 0) endif() +option(LLVM_BUILD_FOR_COMMON "" ON) +if(LLVM_BUILD_FOR_COMMON) + set(LLVM_BUILD_FOR_COMMON 1) + add_definitions( -DBUILD_FOR_COMMON ) +else() + set(LLVM_BUILD_FOR_COMMON 0) +endif() + if(LLVM_ENABLE_EXPENSIVE_CHECKS) add_compile_definitions(EXPENSIVE_CHECKS) diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index f8fab03f151d28a7f4a9ccf890e81c2590d103e6..2feec759f2404501f552dd7717402516700d6248 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -44,6 +44,9 @@ #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/CaptureTracking.h" +#ifdef BUILD_FOR_COMMON +#include "llvm/Analysis/CFG.h" +#endif // BUILD_FOR_COMMON #include "llvm/Analysis/GuardUtils.h" #include "llvm/Analysis/LazyBlockFrequencyInfo.h" #include "llvm/Analysis/Loads.h" @@ -122,6 +125,13 @@ static cl::opt SingleThread("licm-force-thread-model-single", cl::Hidden, cl::init(false), cl::desc("Force thread model single in LICM pass")); +#ifdef BUILD_FOR_COMMON +static cl::opt DisableMovStoreInsOutsideOfLoopInSigFun( + "disable-move-store-ins-outside-of-loop", + cl::Hidden, cl::init(true), cl::desc("Disable move store instruction" + "outside of loop in signal function.")); +#endif // BUILD_FOR_COMMON + static cl::opt MaxNumUsesTraversed( "licm-max-num-uses-traversed", cl::Hidden, cl::init(8), cl::desc("Max num uses visited for identifying load " @@ -2075,8 +2085,45 @@ bool llvm::promoteLoopAccessesToScalars( for (Use &U : ASIV->uses()) { // Ignore instructions that are outside the loop. Instruction *UI = dyn_cast(U.getUser()); + #if defined(BUILD_FOR_COMMON) + if (DisableMovStoreInsOutsideOfLoopInSigFun) { + if (!UI) + continue; + + // In the following scenario, there will be a loop index store + // instruction that is moved outside the loop and when the termination + // loop is triggered by the signal function, the store instruction is not + // executed.However, the function registered by the signal will read the + // data sored in the store instruction, so the data read is incorrect. + // Solution: Prevent the store instruction form going outside the loop. + // NOTE: The sys_signal function takes the same arguments and performs + // the same task as signal. They all belong to glic. + if(StoreSafety == StoreSafe && !CurLoop->contains(UI)) { + if(LoadInst *NotCurLoopLoad = dyn_cast(UI)) { + Function *NotCurLoopFun = UI->getParent()->getParent(); + for (Use &UseFun : NotCurLoopFun->uses()) { + CallInst *Call = dyn_cast(UseFun.getUser()); + if (Call && Call->getCalledFunction() && + (Call->getCalledFunction()->getName() == "__sysv_signal" || + Call->getCalledFunction()->getName() == "signal") && + isPotentiallyReachable(Call->getParent(), + CurLoop->getLoopPreheader(),NULL,DT, + LI)) + return false; + } + } + } + + if (!CurLoop->contains(UI)) + continue; + } else { + if (!UI || !CurLoop->contains(UI)) + continue; + } +#else if (!UI || !CurLoop->contains(UI)) continue; +#endif // BUILD_FOR_COMMON // If there is an non-load/store instruction in the loop, we can't promote // it. diff --git a/llvm/test/Transforms/LICM/signal-before-loop-2.ll b/llvm/test/Transforms/LICM/signal-before-loop-2.ll new file mode 100644 index 0000000000000000000000000000000000000000..da878c6c691bd0851d350c130cf3633db440cfe3 --- /dev/null +++ b/llvm/test/Transforms/LICM/signal-before-loop-2.ll @@ -0,0 +1,25 @@ +; REQUIRES: enable_build_for_common +; RUN:opt -disable-move-store-ins-outside-of-loop=true -S < %s | FileCheck %s + +@Run_Index = external global i64 + +declare ptr @signal(ptr) + +define void @report() { +entry: + %0 = load i64, ptr @Run_Index, align 8 + unreachable +} + +define i32 @main() { +if.end: + %call.i4 = call ptr @signal(ptr @report) + br label %for.cond + +; CHECK-LABEL: for.cond +; CHECK: store +for.cond: + %0 = load i64, ptr @Run_Index, align 8 + store i64 %0, ptr @Run_Index, align 8 + br label %for.cond +} diff --git a/llvm/test/Transforms/LICM/signal-before-loop.ll b/llvm/test/Transforms/LICM/signal-before-loop.ll new file mode 100644 index 0000000000000000000000000000000000000000..cfae4e87db5662a9dc7a2092c77022ad6c87f708 --- /dev/null +++ b/llvm/test/Transforms/LICM/signal-before-loop.ll @@ -0,0 +1,25 @@ +; REQUIRES: enable_build_for_common +; RUN:opt -disable-move-store-ins-outside-of-loop=true -S < %s | FileCheck %s + +@Run_Index = external global i64 + +declare ptr @__sysv_signal(ptr) + +define void @report() { +entry: + %0 = load i64, ptr @Run_Index, align 8 + unreachable +} + +define i32 @main() { +if.end: + %call.i4 = call ptr @__sysv_signal(ptr @report) + br label %for.cond + +; CHECK-LABEL: for.cond +; CHECK: store +for.cond: + %0 = load i64, ptr @Run_Index, align 8 + store i64 %0, ptr @Run_Index, align 8 + br label %for.cond +} diff --git a/llvm/test/lit.site.cfg.py.in b/llvm/test/lit.site.cfg.py.in index 0e9396e3b014134d9507d4a345b88f16f5ddccd9..20c1ecca1d43002a436cb5b11929b136b12ba81d 100644 --- a/llvm/test/lit.site.cfg.py.in +++ b/llvm/test/lit.site.cfg.py.in @@ -63,6 +63,7 @@ config.dxil_tests = @LLVM_INCLUDE_DXIL_TESTS@ config.have_llvm_driver = @LLVM_TOOL_LLVM_DRIVER_BUILD@ config.use_classic_flang = @LLVM_ENABLE_CLASSIC_FLANG@ config.enable_enable_autotuner = @LLVM_ENABLE_AUTOTUNER@ +config.enable_build_for_common = @LLVM_BUILD_FOR_COMMON@ import lit.llvm lit.llvm.initialize(lit_config, config)