Index: lib/Target/Sparc/SparcISelLowering.cpp =================================================================== --- lib/Target/Sparc/SparcISelLowering.cpp +++ lib/Target/Sparc/SparcISelLowering.cpp @@ -2508,7 +2508,10 @@ SDValue SparcTargetLowering::LowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG, const SparcTargetLowering &TLI) const { SDLoc DL(Op); - return DAG.getNode(SPISD::EH_SJLJ_LONGJMP, DL, MVT::Other, Op.getOperand(0), Op.getOperand(1)); + + SDValue Chain = DAG.getNode(SPISD::FLUSHW, DL, MVT::Other, Op.getOperand(0)); + return DAG.getNode(SPISD::EH_SJLJ_LONGJMP, DL, MVT::Other, Chain, + Op.getOperand(1)); } static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG, @@ -3090,13 +3093,10 @@ case SP::SELECT_CC_DFP_FCC: case SP::SELECT_CC_QFP_FCC: return expandSelectCC(MI, BB, SP::FBCOND); - case SP::EH_SJLJ_SETJMP32ri: - case SP::EH_SJLJ_SETJMP32rr: + case SP::EH_SJLJ_SETJMP: return emitEHSjLjSetJmp(MI, BB); - case SP::EH_SJLJ_LONGJMP32rr: - case SP::EH_SJLJ_LONGJMP32ri: + case SP::EH_SJLJ_LONGJMP: return emitEHSjLjLongJmp(MI, BB); - } } @@ -3164,46 +3164,32 @@ MachineFunction *MF = MBB->getParent(); MachineRegisterInfo &MRI = MF->getRegInfo(); - MachineInstrBuilder MIB; MVT PVT = getPointerTy(MF->getDataLayout()); - unsigned RegSize = PVT.getStoreSize(); - assert(PVT == MVT::i32 && "Invalid Pointer Size!"); + assert((PVT == MVT::i64 || PVT == MVT::i32) && "Invalid Pointer Size!"); + const TargetRegisterClass *RC = + (PVT == MVT::i64) ? &SP::I64RegsRegClass : &SP::IntRegsRegClass; + + unsigned LoadOpc = (PVT == MVT::i64) ? SP::LDXri : SP::LDri; + unsigned RegSize = PVT.getStoreSize(); unsigned Buf = MI.getOperand(0).getReg(); - unsigned JmpLoc = MRI.createVirtualRegister(&SP::IntRegsRegClass); - - // TO DO: If we do 64-bit handling, this perhaps should be FLUSHW, not TA 3 - MIB = BuildMI(*MBB, MI, DL, TII->get(SP::TRAPri), SP::G0).addImm(3).addImm(SPCC::ICC_A); - - // Instruction to restore FP - const unsigned FP = SP::I6; - MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri)) - .addReg(FP) - .addReg(Buf) - .addImm(0); - - // Instruction to load jmp location - MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri)) - .addReg(JmpLoc, RegState::Define) - .addReg(Buf) - .addImm(RegSize); - - // Instruction to restore SP - const unsigned SP = SP::O6; - MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri)) - .addReg(SP) - .addReg(Buf) - .addImm(2 * RegSize); - - // Instruction to restore I7 - MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri)) - .addReg(SP::I7) - .addReg(Buf, RegState::Kill) - .addImm(3 * RegSize); + unsigned JmpLoc = MRI.createVirtualRegister(RC); + + unsigned Regs[] = {SP::I6, JmpLoc, SP::O6, SP::I7}; + + // Restore registers + for (unsigned i = 0; i < 4; i++) + BuildMI(*MBB, MI, DL, TII->get(LoadOpc)) + .addReg(Regs[i], RegState::Define) + .addReg(Buf) + .addImm(i * RegSize); // Jump to JmpLoc - BuildMI(*MBB, MI, DL, TII->get(SP::JMPLrr)).addReg(SP::G0).addReg(JmpLoc, RegState::Kill).addReg(SP::G0); + BuildMI(*MBB, MI, DL, TII->get(SP::JMPLrr)) + .addReg(SP::G0, RegState::Define) + .addReg(JmpLoc, RegState::Kill) + .addReg(SP::G0); MI.eraseFromParent(); return MBB; @@ -3214,142 +3200,97 @@ MachineBasicBlock *MBB) const { DebugLoc DL = MI.getDebugLoc(); const TargetInstrInfo *TII = Subtarget->getInstrInfo(); - const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo(); MachineFunction *MF = MBB->getParent(); MachineRegisterInfo &MRI = MF->getRegInfo(); MachineInstrBuilder MIB; MVT PVT = getPointerTy(MF->getDataLayout()); - unsigned RegSize = PVT.getStoreSize(); - assert(PVT == MVT::i32 && "Invalid Pointer Size!"); - - unsigned DstReg = MI.getOperand(0).getReg(); - const TargetRegisterClass *RC = MRI.getRegClass(DstReg); - assert(TRI->isTypeLegalForClass(*RC, MVT::i32) && "Invalid destination!"); - (void)TRI; - unsigned mainDstReg = MRI.createVirtualRegister(RC); - unsigned restoreDstReg = MRI.createVirtualRegister(RC); + assert((PVT == MVT::i64 || PVT == MVT::i32) && "Invalid Pointer Size!"); // For v = setjmp(buf), we generate // - // thisMBB: - // buf[0] = FP - // buf[RegSize] = restoreMBB <-- takes address of restoreMBB - // buf[RegSize * 2] = O6 - // buf[RegSize * 3] = I7 - // Ensure restoreMBB remains in the relocations list (done using a bn instruction) - // b mainMBB + // MBB: + // call mainMBB + // v_restore = 1 + // ba sinkMBB // // mainMBB: + // buf[LabelOffset] = O7 + 8 // v_main = 0 - // b sinkMBB - // - // restoreMBB: - // v_restore = 1 - // --fall through-- + // buf[I7Offset] = I7 // // sinkMBB: // v = phi(main, restore) + // + + unsigned RegSize = PVT.getStoreSize(); + unsigned DstReg = MI.getOperand(0).getReg(); + const TargetRegisterClass *RC = MRI.getRegClass(DstReg); + + unsigned mainDstReg = MRI.createVirtualRegister(RC); + unsigned restoreDstReg = MRI.createVirtualRegister(RC); + unsigned BufReg = MI.getOperand(1).getReg(); const BasicBlock *BB = MBB->getBasicBlock(); MachineFunction::iterator It = ++MBB->getIterator(); - MachineBasicBlock *thisMBB = MBB; - MachineBasicBlock *mainMBB = MF->CreateMachineBasicBlock(BB); - MachineBasicBlock *restoreMBB = MF->CreateMachineBasicBlock(BB); + + unsigned StoreOpc = (PVT == MVT::i64) ? SP::STXri : SP::STri; + MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(BB); + MachineBasicBlock *mainMBB = MF->CreateMachineBasicBlock(BB); MF->insert(It, mainMBB); - MF->insert(It, restoreMBB); MF->insert(It, sinkMBB); - restoreMBB->setHasAddressTaken(); - // Transfer the remainder of BB and its successor edges to sinkMBB. sinkMBB->splice(sinkMBB->begin(), MBB, - std::next(MachineBasicBlock::iterator(MI)), - MBB->end()); + std::next(MachineBasicBlock::iterator(MI)), MBB->end()); sinkMBB->transferSuccessorsAndUpdatePHIs(MBB); - unsigned LabelReg = MRI.createVirtualRegister(&SP::IntRegsRegClass); - unsigned LabelReg2 = MRI.createVirtualRegister(&SP::IntRegsRegClass); - unsigned BufReg = MI.getOperand(1).getReg(); + mainMBB->addLiveIn(SP::O7); + BuildMI(mainMBB, DL, TII->get(SP::ADDri)) + .addReg(SP::O7, RegState::Define) + .addReg(SP::O7) + .addImm(8); - // Instruction to store FP - const unsigned FP = SP::I6; - MIB = BuildMI(thisMBB, DL, TII->get(SP::STri)) - .addReg(BufReg) - .addImm(0) - .addReg(FP); - - // Instructions to store jmp location - MIB = BuildMI(thisMBB, DL, TII->get(SP::SETHIi)) - .addReg(LabelReg, RegState::Define) - .addMBB(restoreMBB, SparcMCExpr::VK_Sparc_HI); - - MIB = BuildMI(thisMBB, DL, TII->get(SP::ORri)) - .addReg(LabelReg2, RegState::Define) - .addReg(LabelReg, RegState::Kill) - .addMBB(restoreMBB, SparcMCExpr::VK_Sparc_LO); - - MIB = BuildMI(thisMBB, DL, TII->get(SP::STri)) + MIB = BuildMI(mainMBB, DL, TII->get(StoreOpc)) .addReg(BufReg) .addImm(RegSize) - .addReg(LabelReg2, RegState::Kill); - - // Instruction to store SP - const unsigned SP = SP::O6; - MIB = BuildMI(thisMBB, DL, TII->get(SP::STri)) - .addReg(BufReg) - .addImm(2 * RegSize) - .addReg(SP); - - // Instruction to store I7 - MIB = BuildMI(thisMBB, DL, TII->get(SP::STri)) - .addReg(BufReg) - .addImm(3 * RegSize) - .addReg(SP::I7); - - - // FIX ME: This next instruction ensures that the restoreMBB block address remains - // valid through optimization passes and serves no other purpose. The ICC_N ensures - // that the branch is never taken. This commented-out code here was an alternative - // attempt to achieve this which brought myriad problems. - //MIB = BuildMI(thisMBB, DL, TII->get(SP::EH_SjLj_Setup)).addMBB(restoreMBB, SparcMCExpr::VK_Sparc_None); - MIB = BuildMI(thisMBB, DL, TII->get(SP::BCOND)) - .addMBB(restoreMBB) - .addImm(SPCC::ICC_N); - - MIB = BuildMI(thisMBB, DL, TII->get(SP::BCOND)) - .addMBB(mainMBB) - .addImm(SPCC::ICC_A); - - thisMBB->addSuccessor(mainMBB); - thisMBB->addSuccessor(restoreMBB); - - - // mainMBB: - MIB = BuildMI(mainMBB, DL, TII->get(SP::ORrr)) - .addReg(mainDstReg, RegState::Define) - .addReg(SP::G0) - .addReg(SP::G0); - MIB = BuildMI(mainMBB, DL, TII->get(SP::BCOND)).addMBB(sinkMBB).addImm(SPCC::ICC_A); - - mainMBB->addSuccessor(sinkMBB); - - - // restoreMBB: - MIB = BuildMI(restoreMBB, DL, TII->get(SP::ORri)) - .addReg(restoreDstReg, RegState::Define) - .addReg(SP::G0) - .addImm(1); - //MIB = BuildMI(restoreMBB, DL, TII->get(SP::BCOND)).addMBB(sinkMBB).addImm(SPCC::ICC_A); - restoreMBB->addSuccessor(sinkMBB); - - // sinkMBB: - MIB = BuildMI(*sinkMBB, sinkMBB->begin(), DL, - TII->get(SP::PHI), DstReg) - .addReg(mainDstReg).addMBB(mainMBB) - .addReg(restoreDstReg).addMBB(restoreMBB); + .addReg(SP::O7); + BuildMI(mainMBB, DL, TII->get(SP::ORri)) + .addReg(mainDstReg, RegState::Define) + .addReg(SP::G0) + .addImm(0); + BuildMI(MBB, DL, TII->get(StoreOpc)) + .addReg(BufReg) + .addImm(3 * RegSize) + .addReg(SP::I7); + + BuildMI(MBB, DL, TII->get(SP::CALL)).addMBB(mainMBB); + + const SparcRegisterInfo *RegInfo = Subtarget->getRegisterInfo(); + MIB.addRegMask(RegInfo->getRTCallPreservedMask(0)); + + BuildMI(MBB, DL, TII->get(SP::ORri)) + .addReg(restoreDstReg, RegState::Define) + .addReg(SP::G0) + .addImm(1); + BuildMI(MBB, DL, TII->get(SP::BA)).addMBB(sinkMBB); + + mainMBB->setIsEHPad(); + mainMBB->setHasAddressTaken(); + sinkMBB->setHasAddressTaken(); + + MBB->addSuccessor(sinkMBB, BranchProbability::getZero()); + MBB->addSuccessor(mainMBB, BranchProbability::getOne()); + mainMBB->addSuccessor(sinkMBB, BranchProbability::getOne()); + + MIB = BuildMI(*sinkMBB, sinkMBB->begin(), DL, TII->get(SP::PHI)) + .addReg(DstReg, RegState::Define) + .addReg(restoreDstReg) + .addMBB(MBB) + .addReg(mainDstReg) + .addMBB(mainMBB); MI.eraseFromParent(); return sinkMBB; Index: lib/Target/Sparc/SparcInstrInfo.td =================================================================== --- lib/Target/Sparc/SparcInstrInfo.td +++ lib/Target/Sparc/SparcInstrInfo.td @@ -474,24 +474,13 @@ } let hasSideEffects = 1, isBarrier = 1, usesCustomInserter = 1 in { - let Defs = [WIM] in - def EH_SJLJ_SETJMP32ri : Pseudo<(outs IntRegs:$dst), (ins MEMri:$buf), - "#EH_SJLJ_SETJMP32", - [(set i32:$dst, (SPsjlj_setjmp ADDRri:$buf))]>, - Requires<[Is32Bit]>; - def EH_SJLJ_SETJMP32rr : Pseudo<(outs IntRegs:$dst), (ins MEMrr:$buf), - "#EH_SJLJ_SETJMP32", - [(set i32:$dst, (SPsjlj_setjmp ADDRrr:$buf))]>, - Requires<[Is32Bit]>; + def EH_SJLJ_SETJMP : Pseudo<(outs IntRegs:$dst), (ins IntRegs:$buf), + "; EH_SJLJ_SETJMP", + [(set i32:$dst, (SPsjlj_setjmp IntRegs:$buf))]>; let isTerminator = 1 in - def EH_SJLJ_LONGJMP32ri : Pseudo<(outs), (ins MEMri:$buf), - "#EH_SJLJ_LONGJMP32", - [(SPsjlj_longjmp ADDRri:$buf)]>, - Requires<[Is32Bit]>; - def EH_SJLJ_LONGJMP32rr : Pseudo<(outs), (ins MEMrr:$buf), - "#EH_SJLJ_LONGJMP32", - [(SPsjlj_longjmp ADDRrr:$buf)]>, - Requires<[Is32Bit]>; + def EH_SJLJ_LONGJMP : Pseudo<(outs), (ins IntRegs:$buf), + "; EH_SJLJ_LONGJMP", + [(SPsjlj_longjmp IntRegs:$buf)]>; } // Section B.1 - Load Integer Instructions, p. 90 Index: test/CodeGen/SPARC/sjlj.ll =================================================================== --- test/CodeGen/SPARC/sjlj.ll +++ test/CodeGen/SPARC/sjlj.ll @@ -1,93 +1,104 @@ -; RUN: llc < %s -march=sparc | FileCheck %s -; RUN: llc < %s -march=sparc -mcpu=leon2 | FileCheck %s -; RUN: llc < %s -march=sparc -mcpu=leon3 | FileCheck %s -; RUN: llc < %s -march=sparc -mcpu=leon4 | FileCheck %s - -%struct.__jmp_buf_tag = type { [64 x i64], i32, %struct.__sigset_t, [8 x i8] } -%struct.__sigset_t = type { [16 x i64] } - -@env_sigill = internal global [1 x %struct.__jmp_buf_tag] zeroinitializer, align 16 - -define void @foo() #0 { +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=sparc -verify-machineinstrs | FileCheck %s -check-prefix=SPARC +; RUN: llc < %s -mtriple=sparcv9 -verify-machineinstrs | FileCheck %s -check-prefix=SPARCV9 + +@buf = common dso_local local_unnamed_addr global i8** null, align 8 + +define i32 @call_setjmp() #0 { +; SPARC-LABEL: call_setjmp: +; SPARC: ! %bb.0: ! %entry +; SPARC-NEXT: save %sp, -96, %sp +; SPARC-NEXT: sethi %hi(buf), %i0 +; SPARC-NEXT: ld [%i0+%lo(buf)], %i0 +; SPARC-NEXT: st %fp, [%i0] +; SPARC-NEXT: st %sp, [%i0+8] +; SPARC-NEXT: call .LBB0_2 +; SPARC-NEXT: st %i7, [%i0+12] +; SPARC-NEXT: ! %bb.1: +; SPARC-NEXT: ret +; SPARC-NEXT: restore %g0, 1, %o0 +; SPARC-NEXT: .LBB0_2: ! Block address taken +; SPARC-NEXT: ! %entry +; SPARC-NEXT: add %o7, 8, %o7 +; SPARC-NEXT: st %o7, [%i0+4] +; SPARC-NEXT: mov 0, %i0 +; SPARC-NEXT: ! %bb.3: ! Block address taken +; SPARC-NEXT: ! %entry +; SPARC-NEXT: ret +; SPARC-NEXT: restore +; +; SPARCV9-LABEL: call_setjmp: +; SPARCV9: ! %bb.0: ! %entry +; SPARCV9-NEXT: save %sp, -128, %sp +; SPARCV9-NEXT: sethi %h44(buf), %i0 +; SPARCV9-NEXT: add %i0, %m44(buf), %i0 +; SPARCV9-NEXT: sllx %i0, 12, %i0 +; SPARCV9-NEXT: ldx [%i0+%l44(buf)], %i0 +; SPARCV9-NEXT: add %fp, 2047, %i1 +; SPARCV9-NEXT: stx %i1, [%i0] +; SPARCV9-NEXT: stx %sp, [%i0+16] +; SPARCV9-NEXT: call .LBB0_2 +; SPARCV9-NEXT: stx %i7, [%i0+24] +; SPARCV9-NEXT: ! %bb.1: +; SPARCV9-NEXT: ret +; SPARCV9-NEXT: restore %g0, 1, %o0 +; SPARCV9-NEXT: .LBB0_2: ! Block address taken +; SPARCV9-NEXT: ! %entry +; SPARCV9-NEXT: add %o7, 8, %o7 +; SPARCV9-NEXT: stx %o7, [%i0+8] +; SPARCV9-NEXT: mov 0, %i0 +; SPARCV9-NEXT: ! %bb.3: ! Block address taken +; SPARCV9-NEXT: ! %entry +; SPARCV9-NEXT: ret +; SPARCV9-NEXT: restore entry: - call void @llvm.eh.sjlj.longjmp(i8* bitcast ([1 x %struct.__jmp_buf_tag]* @env_sigill to i8*)) - unreachable - -; CHECK: @foo -; CHECK: ta 3 -; CHECK: ld [%i0], %fp -; CHECK: ld [%i0+4], %i1 -; CHECK: ld [%i0+8], %sp -; CHECK: jmp %i1 -; CHECK: ld [%i0+12], %i7 - -return: ; No predecessors! - ret void + %0 = load i8**, i8*** @buf, align 8 + %1 = tail call i8* @llvm.frameaddress(i32 0) + store i8* %1, i8** %0, align 8 + %2 = tail call i8* @llvm.stacksave() + %3 = getelementptr inbounds i8*, i8** %0, i32 2 + store i8* %2, i8** %3, align 8 + %4 = bitcast i8** %0 to i8* + %5 = tail call i32 @llvm.eh.sjlj.setjmp(i8* %4) + ret i32 %5 } -declare void @llvm.eh.sjlj.longjmp(i8*) #1 - -define signext i32 @main() #0 { +define void @call_longjmp() #1 { +; SPARC-LABEL: call_longjmp: +; SPARC: ! %bb.0: ! %entry +; SPARC-NEXT: save %sp, -96, %sp +; SPARC-NEXT: sethi %hi(buf), %i0 +; SPARC-NEXT: ld [%i0+%lo(buf)], %i0 +; SPARC-NEXT: ta 3 +; SPARC-NEXT: ld [%i0], %fp +; SPARC-NEXT: ld [%i0+4], %i1 +; SPARC-NEXT: ld [%i0+8], %sp +; SPARC-NEXT: jmp %i1 +; SPARC-NEXT: ld [%i0+12], %i7 +; +; SPARCV9-LABEL: call_longjmp: +; SPARCV9: ! %bb.0: ! %entry +; SPARCV9-NEXT: save %sp, -128, %sp +; SPARCV9-NEXT: sethi %h44(buf), %i0 +; SPARCV9-NEXT: add %i0, %m44(buf), %i0 +; SPARCV9-NEXT: sllx %i0, 12, %i0 +; SPARCV9-NEXT: ldx [%i0+%l44(buf)], %i0 +; SPARCV9-NEXT: flushw +; SPARCV9-NEXT: ldx [%i0], %fp +; SPARCV9-NEXT: ldx [%i0+8], %i1 +; SPARCV9-NEXT: ldx [%i0+16], %sp +; SPARCV9-NEXT: jmp %i1 +; SPARCV9-NEXT: ldx [%i0+24], %i7 entry: - %retval = alloca i32, align 4 - store i32 0, i32* %retval - %0 = call i8* @llvm.frameaddress(i32 0) - store i8* %0, i8** bitcast ([1 x %struct.__jmp_buf_tag]* @env_sigill to i8**) - %1 = call i8* @llvm.stacksave() - store i8* %1, i8** getelementptr (i8*, i8** bitcast ([1 x %struct.__jmp_buf_tag]* @env_sigill to i8**), i32 2) - %2 = call i32 @llvm.eh.sjlj.setjmp(i8* bitcast ([1 x %struct.__jmp_buf_tag]* @env_sigill to i8*)) - %tobool = icmp ne i32 %2, 0 - br i1 %tobool, label %if.then, label %if.else - -if.then: ; preds = %entry - store i32 1, i32* %retval - br label %return - -if.else: ; preds = %entry - call void @foo() - br label %if.end - -if.end: ; preds = %if.else - store i32 0, i32* %retval - br label %return - -return: ; preds = %if.end, %if.then - %3 = load i32, i32* %retval - ret i32 %3 - -; CHECK: @main -; CHECK: st %fp, [%i0] -; CHECK: sethi %hi(.LBB1_2), %i1 -; CHECK: or %i1, %lo(.LBB1_2), %i1 -; CHECK: st %i1, [%i0+4] -; CHECK: st %sp, [%i0+8] -; CHECK: bn .LBB1_2 -; CHECK: st %i7, [%i0+12] -; CHECK: ba .LBB1_1 -; CHECK: nop -; CHECK:.LBB1_1: ! %entry -; CHECK: mov %g0, %i0 -; CHECK: ! %entry -; CHECK: cmp %i0, 0 -; CHECK: be .LBB1_5 -; CHECK: nop -; CHECK:.LBB1_4: -; CHECK: mov 1, %i0 -; CHECK: ba .LBB1_6 -; CHECK:.LBB1_2: ! Block address taken -; CHECK: mov 1, %i0 -; CHECK: cmp %i0, 0 -; CHECK: bne .LBB1_4 -; CHECK: nop + %0 = load i8*, i8** bitcast (i8*** @buf to i8**), align 8 + tail call void @llvm.eh.sjlj.longjmp(i8* %0) + unreachable } -declare i8* @llvm.frameaddress(i32) #2 - -declare i8* @llvm.stacksave() #3 -declare i32 @llvm.eh.sjlj.setjmp(i8*) #3 +declare i8* @llvm.frameaddress(i32) #0 +declare i8* @llvm.stacksave() #0 +declare i32 @llvm.eh.sjlj.setjmp(i8*) #0 +declare void @llvm.eh.sjlj.longjmp(i8*) #1 -attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #0 = { nounwind } attributes #1 = { noreturn nounwind } -attributes #2 = { nounwind readnone } -attributes #3 = { nounwind } -