llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen Author: None (anoopkg6) <details> <summary>Changes</summary> Implementation for __builtin_setjmp and __builtin_longjmp for SystemZ. --- Patch is 665.11 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/116642.diff 76 Files Affected: - (modified) clang/lib/Basic/Targets/SystemZ.h (+2) - (modified) clang/lib/CodeGen/CGBuiltin.cpp (+6) - (modified) llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp (+4) - (modified) llvm/lib/Target/SystemZ/SystemZISelLowering.cpp (+252-1) - (modified) llvm/lib/Target/SystemZ/SystemZISelLowering.h (+7) - (modified) llvm/lib/Target/SystemZ/SystemZInstrInfo.td (+14) - (modified) llvm/lib/Target/SystemZ/SystemZLongBranch.cpp (+4-1) - (modified) llvm/lib/Target/SystemZ/SystemZOperators.td (+12) - (modified) llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp (+5) - (modified) llvm/lib/Target/SystemZ/SystemZRegisterInfo.h (+1) - (added) llvm/test/CodeGen/SystemZ/builtin-longjmp-01.ll (+44) - (added) llvm/test/CodeGen/SystemZ/builtin-longjmp-backchain-01.ll (+46) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-01.ll (+60) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-backchain-01.ll (+65) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-01.ll (+72) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-02.ll (+101) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-03.ll (+87) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-04-o0.ll (+94) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-04-o2.ll (+93) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-00-o0.ll (+284) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-00-o2.ll (+170) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-00.ll (+170) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-01.ll (+343) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-02.ll (+329) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-03.ll (+1037) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-04-o0.ll (+149) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-04-o2.ll (+157) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-04.ll (+157) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-00-o0.ll (+286) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-00-o2.ll (+170) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-01.ll (+343) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-02.ll (+330) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-03.ll (+1038) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-04-o0.ll (+150) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-04-o2.ll (+133) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-backchain-01.ll (+73) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-backchain-02.ll (+82) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-backchain-03.ll (+88) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-backchain-04-o0.ll (+95) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-backchain-04-o2.ll (+95) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-00.ll (+94) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-01.ll (+203) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-02.ll (+276) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-03.ll (+291) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-04.ll (+264) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-backchain-00.ll (+94) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-backchain-01.ll (+175) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-backchain-02.ll (+277) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-backchain-03.ll (+290) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-backchain-04.ll (+264) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-global-02-o2.ll (+133) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-global-0l-o2.ll (+109) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-global-backchain-02-o2.ll (+135) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-global-backchain-0l-o2.ll (+111) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-local-01-o0.ll (+105) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-local-02-o0.ll (+147) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-local-03.ll (+393) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-local-backchain-01-o0.ll (+106) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-local-backchain-02-o0.ll (+147) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-local-backchain-03.ll (+393) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-volatile-01-o2.ll (+104) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-volatile-02-o2.ll (+122) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-volatile-backchain-01-o2.ll (+105) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-volatile-backchain-02-o2.ll (+124) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-double-01.ll (+245) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-double-02.ll (+152) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-double-03.ll (+223) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-double-backchain-01.ll (+246) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-double-backchain-02.ll (+153) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-double-backchain-03.ll (+225) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-int-01.ll (+243) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-int-02.ll (+151) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-int-03.ll (+222) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-int-backchain-01.ll (+241) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-int-backchain-02.ll (+155) - (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-int-backchain-03.ll (+227) ``````````diff diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h index ef9a07033a6e4f..e6405f174f660f 100644 --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -247,6 +247,8 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { return RegNo < 4 ? 6 + RegNo : -1; } + bool hasSjLjLowering() const override { return true; } + std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override { return std::make_pair(256, 256); } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index e2d03eff8ab4a0..1de6aded302ceb 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4619,6 +4619,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Buffer is a void**. Address Buf = EmitPointerWithAlignment(E->getArg(0)); + if (getTarget().getTriple().getArch() == llvm::Triple::systemz) { + // Call LLVM's EH setjmp, which is lightweight. + Function *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp); + return RValue::get(Builder.CreateCall(F, Buf.emitRawPointer(*this))); + } + // Store the frame pointer to the setjmp buffer. Value *FrameAddr = Builder.CreateCall( CGM.getIntrinsic(Intrinsic::frameaddress, AllocaInt8PtrTy), diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp index 050a482c69d528..a75dac5b91ceca 100644 --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -687,6 +687,10 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot)); return; } + // EH_SjLj_Setup is a dummy terminator instruction of size 0, + // It is used to handle the clobber register for builtin setjmp. + case SystemZ::EH_SjLj_Setup: + return; default: Lower.lower(MI, LoweredMI); diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index 3e05f3b0180a78..f498f9eab865f1 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -751,6 +751,13 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM, setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom); setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); + // We're not using SJLJ for exception handling, but they're implemented + // solely to support use of __builtin_setjmp / __builtin_longjmp. + setOperationAction(ISD::EH_SJLJ_SETJMP, MVT::i32, Custom); + setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom); + + + // We want to use MVC in preference to even a single load/store pair. MaxStoresPerMemcpy = Subtarget.hasVector() ? 2 : 0; MaxStoresPerMemcpyOptSize = 0; @@ -940,7 +947,242 @@ bool SystemZTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, return SystemZVectorConstantInfo(Imm).isVectorConstantLegal(Subtarget); } -/// Returns true if stack probing through inline assembly is requested. + +MachineBasicBlock * +SystemZTargetLowering::emitEHSjLjSetJmp(MachineInstr &MI, + MachineBasicBlock *MBB) const { + + DebugLoc DL = MI.getDebugLoc(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); + const SystemZRegisterInfo *TRI = Subtarget.getRegisterInfo(); + + MachineFunction *MF = MBB->getParent(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + + const BasicBlock *BB = MBB->getBasicBlock(); + MachineFunction::iterator I = ++MBB->getIterator(); + + Register DstReg = MI.getOperand(0).getReg(); + const TargetRegisterClass *RC = MRI.getRegClass(DstReg); + assert(TRI->isTypeLegalForClass(*RC, MVT::i32) && "Invalid destination!"); + Register mainDstReg = MRI.createVirtualRegister(RC); + Register restoreDstReg = MRI.createVirtualRegister(RC); + + MVT PVT = getPointerTy(MF->getDataLayout()); + assert((PVT == MVT::i64 || PVT == MVT::i32) && + "Invalid Pointer Size!"); + // For v = setjmp(buf), we generate. + // Algorithm: + // + // --------- + // | thisMBB | + // --------- + // | + // ------------------------ + // | | + // ---------- --------------- + // | mainMBB | | restoreMBB | + // | v = 0 | | v = 1 | + // ---------- --------------- + // | | + // ------------------------- + // | + // ----------------------------- + // | sinkMBB | + // | phi(v_mainMBB,v_restoreMBB) | + // ----------------------------- + // thisMBB: + // buf[0] = Frame Pointer if hasFP. + // buf[LabelOffset] = restoreMBB <-- takes address of restoreMBB. + // buf[BCOffset] = Backchain value if building with -mbackchain. + // buf[SPOffset] = Stack Pointer. + // buf[LPOffset] = We never write this slot with R13, gcc stores R13 always. + // SjLjSetup restoreMBB + // mainMBB: + // v_main = 0 + // sinkMBB: + // v = phi(v_main, v_restore) + // restoreMBB: + // v_restore = 1 + + MachineBasicBlock *thisMBB = MBB; + MachineBasicBlock *mainMBB = MF->CreateMachineBasicBlock(BB); + MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(BB); + MachineBasicBlock *restoreMBB = MF->CreateMachineBasicBlock(BB); + + MF->insert(I, mainMBB); + MF->insert(I, sinkMBB); + MF->push_back(restoreMBB); + restoreMBB->setMachineBlockAddressTaken(); + + MachineInstrBuilder MIB; + + // Transfer the remainder of BB and its successor edges to sinkMBB. + sinkMBB->splice(sinkMBB->begin(), MBB, + std::next(MachineBasicBlock::iterator(MI)), MBB->end()); + sinkMBB->transferSuccessorsAndUpdatePHIs(MBB); + + + // thisMBB: + const int64_t LabelOffset = 1 * PVT.getStoreSize(); // Slot 2. + const int64_t SPOffset = 3 * PVT.getStoreSize(); // Slot 4. + + // Buf address. + Register BufReg = MI.getOperand(1).getReg(); + + unsigned LabelReg = 0; + const TargetRegisterClass *PtrRC = getRegClassFor(PVT); + LabelReg = MRI.createVirtualRegister(PtrRC); + + // prepare IP for longjmp. + BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::LARL), LabelReg) + .addMBB(restoreMBB); + + // store IP for return from jmp, slot 2, offset = 1. + BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::STG)) + .addReg(LabelReg) + .addReg(BufReg) + .addImm(LabelOffset) + .addReg(0); + + bool HasFP = Subtarget.getFrameLowering()->hasFP(*MF); + if (HasFP) { + const int64_t FPOffset = 0; + BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::STG)) + .addReg(SystemZ::R11D) + .addReg(BufReg) + .addImm(FPOffset) + .addReg(0); + } + + // store SP. + BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::STG)) + .addReg(SystemZ::R15D) + .addReg(BufReg) + .addImm(SPOffset) + .addReg(0); + + // Slot 3(Offset = 2) Backchain value (if building with -mbackchain). + bool BackChain = MF->getSubtarget<SystemZSubtarget>().hasBackChain(); + if (BackChain) { + const int64_t BCOffset = 2 * PVT.getStoreSize(); + Register BCReg = MRI.createVirtualRegister(RC); + MIB = BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::LG), BCReg) + .addReg(SystemZ::R15D) + .addImm(0) + .addReg(0); + + BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::STG)) + .addReg(BCReg) + .addReg(BufReg) + .addImm(BCOffset) + .addReg(0); + } + + // Setup. + MIB = BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::EH_SjLj_Setup)) + .addMBB(restoreMBB); + + const SystemZRegisterInfo *RegInfo = Subtarget.getRegisterInfo(); + MIB.addRegMask(RegInfo->getNoPreservedMask()); + + thisMBB->addSuccessor(mainMBB); + thisMBB->addSuccessor(restoreMBB); + + // mainMBB: + BuildMI(mainMBB, DL, TII->get(SystemZ::LHI), mainDstReg).addImm(0); + mainMBB->addSuccessor(sinkMBB); + + // sinkMBB: + BuildMI(*sinkMBB, sinkMBB->begin(), DL, TII->get(SystemZ::PHI), DstReg) + .addReg(mainDstReg) + .addMBB(mainMBB) + .addReg(restoreDstReg) + .addMBB(restoreMBB); + + // restoreMBB. + BuildMI(restoreMBB, DL, TII->get(SystemZ::LHI), restoreDstReg).addImm(1); + BuildMI(restoreMBB, DL, TII->get(SystemZ::J)).addMBB(sinkMBB); + restoreMBB->addSuccessor(sinkMBB); + + MI.eraseFromParent(); + + return sinkMBB; +} + +MachineBasicBlock * +SystemZTargetLowering::emitEHSjLjLongJmp(MachineInstr &MI, + MachineBasicBlock *MBB) const { + + DebugLoc DL = MI.getDebugLoc(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); + + MachineFunction *MF = MBB->getParent(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + + MVT PVT = getPointerTy(MF->getDataLayout()); + assert((PVT == MVT::i64 || PVT == MVT::i32) && + "Invalid Pointer Size!"); + Register BufReg = MI.getOperand(0).getReg(); + const TargetRegisterClass *RC = MRI.getRegClass(BufReg); + + Register Tmp = MRI.createVirtualRegister(RC); + Register BCReg = MRI.createVirtualRegister(RC); + + MachineInstrBuilder MIB; + + const int64_t FPOffset = 0; + const int64_t LabelOffset = 1 * PVT.getStoreSize(); + const int64_t SPOffset = 3 * PVT.getStoreSize(); + const int64_t LPOffset = 4 * PVT.getStoreSize(); + + MIB = BuildMI(*MBB, MI, DL, TII->get(SystemZ::LG), Tmp) + .addReg(BufReg) + .addImm(LabelOffset) + .addReg(0); + + MIB = BuildMI(*MBB, MI, DL, TII->get(SystemZ::LG), SystemZ::R11D) + .addReg(BufReg) + .addImm(FPOffset) + .addReg(0); + + // We are restoring R13 even though we never stored in setjmp from llvm, + // as gcc always stores R13 in builtin_setjmp. We could have mixed code + // gcc setjmp and llvm longjmp. + MIB = BuildMI(*MBB, MI, DL, TII->get(SystemZ::LG), SystemZ::R13D) + .addReg(BufReg) + .addImm(LPOffset) + .addReg(0); + + bool BackChain = MF->getSubtarget<SystemZSubtarget>().hasBackChain(); + if (BackChain) { + const int64_t BCOffset = 2 * PVT.getStoreSize(); + MIB = BuildMI(*MBB, MI, DL, TII->get(SystemZ::LG), BCReg) + .addReg(BufReg) + .addImm(BCOffset) + .addReg(0); + } + + MIB = BuildMI(*MBB, MI, DL, TII->get(SystemZ::LG), SystemZ::R15D) + .addReg(BufReg) + .addImm(SPOffset) + .addReg(0); + + if (BackChain) { + BuildMI(*MBB, MI, DL, TII->get(SystemZ::STG)) + .addReg(BCReg) + .addReg(SystemZ::R15D) + .addImm(0) + .addReg(0); + } + + MIB = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BR)).addReg(Tmp); + + MI.eraseFromParent(); + return MBB; +} + +// Returns true if stack probing through inline assembly is requested. bool SystemZTargetLowering::hasInlineStackProbe(const MachineFunction &MF) const { // If the function specifically requests inline stack probes, emit them. if (MF.getFunction().hasFnAttribute("probe-stack")) @@ -6292,6 +6534,10 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op, return lowerGET_ROUNDING(Op, DAG); case ISD::READCYCLECOUNTER: return lowerREADCYCLECOUNTER(Op, DAG); + case ISD::EH_SJLJ_SETJMP: + case ISD::EH_SJLJ_LONGJMP: + return Op; + default: llvm_unreachable("Unexpected node to lower"); } @@ -9724,6 +9970,11 @@ MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter( case SystemZ::PROBED_ALLOCA: return emitProbedAlloca(MI, MBB); + + case SystemZ::EH_SjLj_SetJmp: + return emitEHSjLjSetJmp(MI, MBB); + case SystemZ::EH_SjLj_LongJmp: + return emitEHSjLjLongJmp(MI, MBB); case TargetOpcode::STACKMAP: case TargetOpcode::PATCHPOINT: diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h index 3c06c1fdf2b1bc..92ac938c903b68 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h @@ -476,6 +476,12 @@ class SystemZTargetLowering : public TargetLowering { // LD, and having the full constant in memory enables reg/mem opcodes. return VT != MVT::f64; } + MachineBasicBlock *emitEHSjLjSetJmp(MachineInstr &MI, + MachineBasicBlock *MBB) const; + + MachineBasicBlock *emitEHSjLjLongJmp(MachineInstr &MI, + MachineBasicBlock *MBB) const; + bool hasInlineStackProbe(const MachineFunction &MF) const override; AtomicExpansionKind shouldCastAtomicLoadInIR(LoadInst *LI) const override; AtomicExpansionKind shouldCastAtomicStoreInIR(StoreInst *SI) const override; @@ -723,6 +729,7 @@ class SystemZTargetLowering : public TargetLowering { SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const; SDValue lowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const; + bool canTreatAsByteVector(EVT VT) const; SDValue combineExtract(const SDLoc &DL, EVT ElemVT, EVT VecVT, SDValue OrigOp, unsigned Index, DAGCombinerInfo &DCI, diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td index f3baf896658de5..ad7ee522a8c6f7 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td @@ -1871,6 +1871,20 @@ let mayLoad = 1, mayStore = 1, Defs = [CC] in { } } +//-------------------------------------------------------------------------- +// Setjmp/Longjmp. +//-------------------------------------------------------------------------- +let isTerminator = 1, isBarrier = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1, Size = 0 in { + def EH_SjLj_Setup : Pseudo<(outs), (ins brtarget32:$dst), []>; +} + +let hasSideEffects = 1, isBarrier = 1, usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { + def EH_SjLj_SetJmp : Pseudo<(outs GR32:$dst), (ins ADDR64:$R2), [(set GR32:$dst, (z_eh_sjlj_setjmp ADDR64:$R2))]>; +} + +let hasSideEffects = 1, isTerminator = 1, isBarrier = 1, usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { + def EH_SjLj_LongJmp : Pseudo<(outs), (ins ADDR64:$R2), [(z_eh_sjlj_longjmp ADDR64:$R2)]>; +} //===----------------------------------------------------------------------===// // Message-security assist //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp b/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp index 632218cc61eefe..8267d398c50ed6 100644 --- a/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp +++ b/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp @@ -220,7 +220,10 @@ static unsigned getInstSizeInBytes(const MachineInstr &MI, MI.isImplicitDef() || MI.getOpcode() == TargetOpcode::MEMBARRIER || // These have a size that may be zero: MI.isInlineAsm() || MI.getOpcode() == SystemZ::STACKMAP || - MI.getOpcode() == SystemZ::PATCHPOINT) && + MI.getOpcode() == SystemZ::PATCHPOINT || + // EH_SjLj_Setup is a dummy terminator instruction of size 0, + // It is used to handle the clobber register for builtin setjmp. + MI.getOpcode() == SystemZ::EH_SjLj_Setup) && "Missing size value for instruction."); return Size; } diff --git a/llvm/lib/Target/SystemZ/SystemZOperators.td b/llvm/lib/Target/SystemZ/SystemZOperators.td index 6cb89ccff85e68..90fb4e5f370dab 100644 --- a/llvm/lib/Target/SystemZ/SystemZOperators.td +++ b/llvm/lib/Target/SystemZ/SystemZOperators.td @@ -238,6 +238,12 @@ def SDT_ZTest : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisVT<2, i64>]>; +def SDT_ZSetJmp : SDTypeProfile<1, 1, + [SDTCisInt<0>, + SDTCisPtrTy<1>]>; +def SDT_ZLongJmp : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; + + //===----------------------------------------------------------------------===// // Node definitions //===----------------------------------------------------------------------===// @@ -314,6 +320,12 @@ def z_stckf : SDNode<"SystemZISD::STCKF", SDT_ZStoreInherent, def z_tdc : SDNode<"SystemZISD::TDC", SDT_ZTest>; +def z_eh_sjlj_setjmp : SDNode<"ISD::EH_SJLJ_SETJMP", SDT_ZSetJmp, + [SDNPHasChain, SDNPSideEffect]>; +def z_eh_sjlj_longjmp : SDNode<"ISD::EH_SJLJ_LONGJMP", SDT_ZLongJmp, + [SDNPHasChain, SDNPSideEffect]>; + + // Defined because the index is an i32 rather than a pointer. def z_vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT", SDT_ZInsertVectorElt>; diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp index d246d3f3c5bd11..6d3e542c1b4e81 100644 --- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -254,6 +254,11 @@ SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF, return Regs->getCallPreservedMask(MF, CC); } +const uint32_t* +SystemZRegisterInfo::getNoPreservedMask() const { + return CSR_SystemZ_NoRegs_RegMask; +} + BitVector SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const { BitVector Reserved(getNumRegs()); diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h index cbc02c73f1ac70..4f497f8d23d29a 100644 --- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h +++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h @@ -161,6 +161,7 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo { const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; const uint32_t *getCallPreservedMask(const MachineFunction &MF, CallingConv::ID CC) const override; + const uint32_t *getNoPreservedMask() const override; BitVector getReservedRegs(const MachineFunction &MF) const override; bool eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, unsigned FIOperandNum, diff --git a/llvm/test/CodeGen/SystemZ/builtin-longjmp-01.ll b/llvm/test/CodeGen/SystemZ/builtin-longjmp-01.ll new file mode 100644 index 00000000000000..413b651acb64a7 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/builtin-longjmp-01.ll @@ -0,0 +1,44 @@ +;Test longjmp load from jmp_buf. +; Frame pointer from Slot 1. +; Jump address from Slot 2. +; Stack Pointer from Slot 4. +; Literal Pool Pointer from Slot 5. + +; RUN: llc -O2 < %s | FileCheck %s + + +; ModuleID = 'longjmp.c' +source_filename = "longjmp.c" +target datalayout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64" +target triple = "s390x-unknown-linux-gnu" + +@buf = dso_local global [20 x ptr] zeroinitializer, align 8 + +; Function Attrs: noreturn nounwind +define dso_local void @foo() local_unnamed_addr #0 { +entry: +; CHECK: stmg %r11, %r15, 88(%r15) +; CHECK: larl %r1, buf +; CHECK: lg %r2, 8(%r1) +; CHECK: lg %r11, 0(%r1) +; CHECK: lg %r13, 32(%r1) +; CHECK: lg %r15, 24(%r1) +; CHECK: br %r2 + + tail call void @llvm.eh.sjlj.longjmp(ptr nonnull @buf) + unreachable +} + +; Function Attrs: noreturn nounwind +declare void @llvm.eh.sjlj.longjmp(ptr) #1 + +attributes #0 = { noreturn nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="z10" } +attributes #1 = { noreturn nounwind } + +!llvm.module.flags = !{!0, !1, !2} +!llvm.ident = !{!3} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 8, !"PIC Level", i32 2} +!2 = !{i32 7, !"PIE Level", i32 2} +!3 = !{!"clang version 20.0.0git (https://github.com/llvm/llvm-project.git 79880371396d6e486bf6bacd6c4087ebdac591f8)"} diff --git a/llvm/test/CodeGen/SystemZ/builtin-longjmp-backchain-01.ll b/llvm/test/CodeGen/SystemZ/builtin-longjmp-backchain-01.ll new file mode 100644 index 00000000000000..39ee483c27cbd5 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/builtin-longjmp-backchain-01.ll @@ -0,0 +1,46 @@ +;Test -mba... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/116642 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits