Index: llvm/lib/CodeGen/CFIInstrInserter.cpp =================================================================== --- llvm/lib/CodeGen/CFIInstrInserter.cpp +++ llvm/lib/CodeGen/CFIInstrInserter.cpp @@ -18,6 +18,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SetOperations.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" @@ -76,6 +77,10 @@ unsigned IncomingCFARegister = 0; /// Value of cfa register valid at basic block exit. unsigned OutgoingCFARegister = 0; + /// Set of callee saved registers saved at basic block entry. + std::set IncomingCSRSaved; + /// Set of callee saved registers saved at basic block exit. + std::set OutgoingCSRSaved; /// If in/out cfa offset and register values for this block have already /// been set or not. bool Processed = false; @@ -161,6 +166,7 @@ unsigned SetRegister = MBBInfo.IncomingCFARegister; const std::vector &Instrs = MBBInfo.MBB->getParent()->getFrameInstructions(); + SmallVector CSRSaved, CSRRestored; // Determine cfa offset and register set by the block. for (MachineInstr &MI : *MBBInfo.MBB) { @@ -181,6 +187,15 @@ SetRegister = CFI.getRegister(); SetOffset = CFI.getOffset(); break; + case MCCFIInstruction::OpOffset: + case MCCFIInstruction::OpRegister: + case MCCFIInstruction::OpRelOffset: + CSRSaved.push_back(CFI.getRegister()); + break; + case MCCFIInstruction::OpRestore: + case MCCFIInstruction::OpUndefined: + CSRRestored.push_back(CFI.getRegister()); + break; case MCCFIInstruction::OpRememberState: // TODO: Add support for handling cfi_remember_state. #ifndef NDEBUG @@ -199,12 +214,7 @@ break; // Other CFI directives do not affect CFA value. case MCCFIInstruction::OpSameValue: - case MCCFIInstruction::OpOffset: - case MCCFIInstruction::OpRelOffset: case MCCFIInstruction::OpEscape: - case MCCFIInstruction::OpRestore: - case MCCFIInstruction::OpUndefined: - case MCCFIInstruction::OpRegister: case MCCFIInstruction::OpWindowSave: case MCCFIInstruction::OpNegateRAState: case MCCFIInstruction::OpGnuArgsSize: @@ -218,6 +228,13 @@ // Update outgoing CFA info. MBBInfo.OutgoingCFAOffset = SetOffset; MBBInfo.OutgoingCFARegister = SetRegister; + // Update outgoing CSR info. + + MBBInfo.OutgoingCSRSaved = MBBInfo.IncomingCSRSaved; + llvm::for_each(CSRSaved, + [&](auto reg) { MBBInfo.OutgoingCSRSaved.insert(reg); }); + llvm::for_each(CSRRestored, + [&](auto reg) { MBBInfo.OutgoingCSRSaved.erase(reg); }); } void CFIInstrInserter::updateSuccCFAInfo(MBBCFAInfo &MBBInfo) { @@ -236,6 +253,7 @@ if (!SuccInfo.Processed) { SuccInfo.IncomingCFAOffset = CurrentInfo.OutgoingCFAOffset; SuccInfo.IncomingCFARegister = CurrentInfo.OutgoingCFARegister; + SuccInfo.IncomingCSRSaved = CurrentInfo.OutgoingCSRSaved; Stack.push_back(Succ); } } @@ -287,6 +305,15 @@ .addCFIIndex(CFIIndex); InsertedCFIInstr = true; } + auto DiffResult = + set_difference(PrevMBBInfo->OutgoingCSRSaved, MBBInfo.IncomingCSRSaved); + for (unsigned Reg : DiffResult) { + unsigned CFIIndex = + MF.addFrameInst(MCCFIInstruction::createRestore(nullptr, Reg)); + BuildMI(*MBBInfo.MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); + InsertedCFIInstr = true; + } PrevMBBInfo = &MBBInfo; } return InsertedCFIInstr; Index: llvm/test/CodeGen/X86/cfi-inserter-callee-save-register.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/cfi-inserter-callee-save-register.mir @@ -0,0 +1,80 @@ +# RUN: llc -o - %s -mtriple=x86_64-- -verify-cfiinstrs \ +# RUN: -run-pass=cfi-instr-inserter 2>&1 | FileCheck %s +# Test that CFI inserter inserts .cfi_restore properly for +# callee saved registers. +--- | + define void @_Z3foobPl(i64* nocapture readonly %a) { + entry: + %arrayidx2 = getelementptr inbounds i64, i64* %a, i64 1 + %arrayidx3 = getelementptr inbounds i64, i64* %a, i64 2 + br label %if.then + if.then: + br label %return + return: + ret void + } + declare dso_local void @_Z3goov() local_unnamed_addr #1 +... +--- +# CHECK: bb.3.return: +# CHECK: CFI_INSTRUCTION restore $rbx +# CHECK-NEXT: CFI_INSTRUCTION restore $rbp +name: _Z3foobPl +alignment: 16 +tracksRegLiveness: true +liveins: + - { reg: '$edi' } + - { reg: '$rsi' } +frameInfo: + stackSize: 24 + offsetAdjustment: -24 + maxAlignment: 1 + adjustsStack: true + hasCalls: true + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 8 +fixedStack: + - { id: 0, type: spill-slot, offset: -24, size: 8, alignment: 8, callee-saved-register: '$rbx' } + - { id: 1, type: spill-slot, offset: -16, size: 8, alignment: 16 } +machineFunctionInfo: {} +body: | + bb.0.entry: + successors: %bb.2(0x7fef9fcb), %bb.1(0x00106035) + liveins: $edi, $rsi, $rbx + + TEST8rr renamable $dil, renamable $dil, implicit-def $eflags, implicit killed $edi + JCC_1 %bb.2, 5, implicit killed $eflags + + bb.1: + liveins: $rbx + + renamable $eax = MOV32r0 implicit-def dead $eflags, implicit-def $rax + JMP_1 %bb.3 + + bb.2.if.then: + liveins: $rsi:0x0000000D, $rbx + + frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp + CFI_INSTRUCTION def_cfa_offset 16 + CFI_INSTRUCTION offset $rbp, -16 + $rbp = frame-setup MOV64rr $rsp + CFI_INSTRUCTION def_cfa_register $rbp + frame-setup PUSH64r killed $rbx, implicit-def $rsp, implicit $rsp + frame-setup PUSH64r undef $rax, implicit-def $rsp, implicit $rsp + CFI_INSTRUCTION offset $rbx, -24 + renamable $rbx = COPY $rsi + CALL64pcrel32 @_Z3goov, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp + renamable $rax = MOV64rm renamable $rbx, 1, $noreg, 8, $noreg :: (load 8 from %ir.arrayidx2) + renamable $rax = nsw ADD64rm killed renamable $rax, renamable $rbx, 1, $noreg, 0, $noreg, implicit-def dead $eflags :: (load 8 from %ir.a) + renamable $rax = nsw ADD64rm killed renamable $rax, killed renamable $rbx, 1, $noreg, 16, $noreg, implicit-def dead $eflags :: (load 8 from %ir.arrayidx3) + $rsp = frame-destroy ADD64ri8 $rsp, 8, implicit-def dead $eflags + $rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp + $rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp + CFI_INSTRUCTION def_cfa $rsp, 8 + + bb.3.return: + liveins: $rax, $rbx + + RET 0, $rax + +...