From fdbf1bd9f1bdec32384eda47f419d895d11a1c50 Mon Sep 17 00:00:00 2001 From: XingYuShuai <1150775134@qq.com> Date: Wed, 15 May 2024 14:42:27 +0800 Subject: [PATCH] [LICM] Solve runtime error caused by the signal function. Using the option enable-signal to control whether to solve the runtime error caused by the signal function when lto is turned on. --- llvm/cmake/modules/HandleLLVMOptions.cmake | 8 ++++ llvm/lib/Transforms/Scalar/LICM.cpp | 47 +++++++++++++++++++ .../Transforms/LICM/signal-before-loop-2.ll | 25 ++++++++++ .../Transforms/LICM/signal-before-loop.ll | 25 ++++++++++ llvm/test/lit.site.cfg.py.in | 1 + 5 files changed, 106 insertions(+) create mode 100644 llvm/test/Transforms/LICM/signal-before-loop-2.ll create mode 100644 llvm/test/Transforms/LICM/signal-before-loop.ll diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake index b8e9dbe29d88..8be5d4ba52c2 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 f8fab03f151d..2feec759f240 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 000000000000..da878c6c691b --- /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 000000000000..cfae4e87db56 --- /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 0e9396e3b014..20c1ecca1d43 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) -- Gitee