Closed abukharmeh closed 2 years ago
The problem has been located
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.
Can confirm that this indeed fixed it, thank you.
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 ZcmpBacktrace for picojpeg compilation