plctlab / llvm-project

PLCT实验室的 RISC-V V Spec 实现,基于llvm/llvm-project,rkruppe/rvv-llvm 和 https://repo.hca.bsc.es/gitlab/rferrer/llvm-epi-0.8
156 stars 42 forks source link

riscv-zce-llvm14 Branch : Zcmp Crash Compiler #40

Closed abukharmeh closed 2 years ago

abukharmeh commented 2 years ago

Hi, I am trying to compile Emench-IOT benchmarks using Zce compiler and it appears that there is something wrong with push/pop Implementation, as the compiler appear to crash In Prologue/Epilogue Insertion & Frame Finalization pass in two of the benchmarks (picojpeg and qrduino), it works if I compile without Zcmp

Backtrace for picojpeg compilation

0.      Program arguments: /data/toolchains/riscv/Zce/llvm-project/build/bin/clang --target=riscv32 --gcc-toolchain=/data/toolchains/riscv/gcc_riscv32/embecosm-ubuntu1804-11.2.0/ -menable-experimental-extensions -march=rv32ima_zca0p70_zcb0p70_zcmb0p70_zcmp0p70 -g -c -Oz -fdata-sections -ffunction-sections -I/data/benchmarks/embench/embench/support -I/data/benchmarks/embench/embench/config/riscv32/boards/generic -I/data/benchmarks/embench/embench/config/riscv32/chips/size-test-llvm-rv32imac-zce -I/data/benchmarks/embench/embench/config/riscv32 -DCPU_MHZ=1 -DWARMUP_HEAT=1 -o libpicojpeg.o /data/benchmarks/embench/embench/src/picojpeg/libpicojpeg.c
1.      <eof> parser at end of file
2.      Code generation
3.      Running pass 'Function Pass Manager' on module '/data/benchmarks/embench/embench/src/picojpeg/libpicojpeg.c'.
4.      Running pass 'Prologue/Epilogue Insertion & Frame Finalization' on function '@pjpeg_decode_init'
 #0 0x00007f13dbb61113 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libLLVMSupport.so.14git+0x1a7113)
 #1 0x00007f13dbb5ee4e llvm::sys::RunSignalHandlers() (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libLLVMSupport.so.14git+0x1a4e4e)
 #2 0x00007f13dbb6047d llvm::sys::CleanupOnSignal(unsigned long) (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libLLVMSupport.so.14git+0x1a647d)
 #3 0x00007f13dba79283 (anonymous namespace)::CrashRecoveryContextImpl::HandleCrash(int, unsigned long) CrashRecoveryContext.cpp:0:0
 #4 0x00007f13dba7942e CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #5 0x00007f13e2657980 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x12980)
 #6 0x00007f13dacc8fb7 raise /build/glibc-S9d2JN/glibc-2.27/signal/../sysdeps/unix/sysv/linux/raise.c:51:0
 #7 0x00007f13dacca921 abort /build/glibc-S9d2JN/glibc-2.27/stdlib/abort.c:81:0
 #8 0x00007f13dba8acc1 (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libLLVMSupport.so.14git+0xd0cc1)
 #9 0x00007f13e2cec68a llvm::RISCVFrameLowering::spillCalleeSavedRegisters(llvm::MachineBasicBlock&, llvm::MachineInstrBundleIterator<llvm::MachineInstr, false>, llvm::ArrayRef<llvm::CalleeSavedInfo>, llvm::TargetRegisterInfo const*) const (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libLLVMRISCVCodeGen.so.14git+0x4568a)
#10 0x00007f13e0f36358 (anonymous namespace)::PEI::runOnMachineFunction(llvm::MachineFunction&) PrologEpilogInserter.cpp:0:0
#11 0x00007f13e0deedee llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libLLVMCodeGen.so.14git+0x2c8dee)
#12 0x00007f13dc9a94f8 llvm::FPPassManager::runOnFunction(llvm::Function&) (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libLLVMCore.so.14git+0x2354f8)
#13 0x00007f13dc9afdb1 llvm::FPPassManager::runOnModule(llvm::Module&) (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libLLVMCore.so.14git+0x23bdb1)
#14 0x00007f13dc9a9bac llvm::legacy::PassManagerImpl::run(llvm::Module&) (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libLLVMCore.so.14git+0x235bac)
#15 0x00007f13e160a0c5 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream> >) (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libclangCodeGen.so.14git+0xc80c5)
#16 0x00007f13e19920b3 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libclangCodeGen.so.14git+0x4500b3)
#17 0x00007f13d56e2134 clang::ParseAST(clang::Sema&, bool, bool) (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/../lib/libclangParse.so.14git+0x35134)
#18 0x00007f13df941a20 clang::FrontendAction::Execute() (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libclangFrontend.so.14git+0x120a20)
#19 0x00007f13df8b945f clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libclangFrontend.so.14git+0x9845f)
#20 0x00007f13e2441ab3 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libclangFrontendTool.so.14git+0x3ab3)
#21 0x0000000000411456 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/data/toolchains/riscv/Zce/llvm-project/build/bin/clang+0x411456)
#22 0x000000000040f30d ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&) driver.cpp:0:0
#23 0x00007f13df426682 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, bool*) const::$_1>(long) Job.cpp:0:0
#24 0x00007f13dba79197 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libLLVMSupport.so.14git+0xbf197)
#25 0x00007f13df4260c7 clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, bool*) const (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libclangDriver.so.14git+0xad0c7)
#26 0x00007f13df3ece38 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&) const (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libclangDriver.so.14git+0x73e38)
#27 0x00007f13df3ed137 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*> >&) const (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libclangDriver.so.14git+0x74137)
#28 0x00007f13df409008 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*> >&) (/data/toolchains/riscv/Zce/llvm-project/build/bin/../lib/libclangDriver.so.14git+0x90008)
#29 0x000000000040eca8 main (/data/toolchains/riscv/Zce/llvm-project/build/bin/clang+0x40eca8)
#30 0x00007f13dacabbf7 __libc_start_main /build/glibc-S9d2JN/glibc-2.27/csu/../csu/libc-start.c:344:0
#31 0x000000000040c1da _start (/data/toolchains/riscv/Zce/llvm-project/build/bin/clang+0x40c1da)
clang-14: error: clang frontend command failed with exit code 134 (use -v to see invocation)
clang version 14.0.0 (https://github.com/plctlab/llvm-project 6955d272ea58a97953156a0d86cf4a623b4915c2)
Xinlong-Wu commented 2 years ago

The problem has been located

linsinan1995 commented 2 years ago

FYI, there are two cases that push/pop does not handle well in the current implementation. I suspect this error is related to case 1.

This piece of code will allow s0-s10 to be a valid reglist, but it will lead to a crash in getPushPopEncoding later. We need a check before it.

    // llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
    for (auto &CS: CSI){
      Register Reg = CS.getReg();
      const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
      if (RISCV::PGPRRegClass.hasSubClassEq(RC))
        MaxReg = std::max(MaxReg.id(), Reg.id()); 
      else
        TII.storeRegToStackSlot(MBB, MI, Reg, true, CS.getFrameIdx(), RC, TRI);
    }

the implementaion of push/pop spimm would be wrong in some cases, e.g. irq.

    // llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
    // RISCVFrameLowering::spillCalleeSavedRegisters
    // fill the base spimm

    MachineInstrBuilder PushBuilder =
        BuildMI(MBB, MI, DL, TII.get(RISCV::CM_PUSH));
    // Use encoded number to represent registers to spill.
    int RegEnc = getPushPopEncoding(MaxReg);
    PushBuilder.addImm(RegEnc);
    // Calculate SpImm Base adjustment, and SpImm field will be updated
    // through adjSPInPushPop.
    bool isRV64 = STI.getFeatureBits()[RISCV::Feature64Bit];
    bool isEABI = false; // Reserved for future implementation
    uint32_t SpImmBase = RISCVZCE::getStackAdjBase(RegEnc, isRV64, isEABI);
    PushBuilder.addImm(SpImmBase);
    // llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
    // adjSPInPushPop
    // fill the real spimm
   int OpNum = MBBI->getNumOperands();
   auto &Operand = MBBI->getOperand(OpNum -1); 
   ...
   Operand.setImm(StackAdj);
   MBBI->setFlag(isPop ? MachineInstr::FrameDestroy : MachineInstr::FrameSetup);

a simple test case to check the wrong output of push.

declare i32 @foo(...)
define void @foo_with_irq() #0 {
  %call = call i32 bitcast (i32 (...)* @foo to i32 ()*)()
  ret void
}

attributes #0 = { nounwind "interrupt"="user" }

btw, the implementation of libcall in riscv backend would be a great example to learn.

Xinlong-Wu commented 2 years ago

fix in commit https://github.com/plctlab/llvm-project/commit/9f567765efb7ce17fbebbbdee43bfad090c06250

and https://github.com/plctlab/llvm-project/commit/fa6972a3ca2cd5f475b16cd33a2230823f161d91

abukharmeh commented 2 years ago

Can confirm that this indeed fixed it, thank you.