diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h index 97de0197da9b4..cdbefb36c00c7 100644 --- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -229,10 +229,17 @@ class TargetFrameLowering { /// Returns true if we may need to fix the unwind information for the /// function. - virtual bool enableCFIFixup(MachineFunction &MF) const; + virtual bool enableCFIFixup(const MachineFunction &MF) const; + + /// enableFullCFIFixup - Returns true if we may need to fix the unwind + /// information such that it is accurate for *every* instruction in the + /// function (e.g. if the function has an async unwind table). + virtual bool enableFullCFIFixup(const MachineFunction &MF) const { + return enableCFIFixup(MF); + }; /// Emit CFI instructions that recreate the state of the unwind information - /// upon fucntion entry. + /// upon function entry. virtual void resetCFIToInitialState(MachineBasicBlock &MBB) const {} /// Replace a StackProbe stub (if any) with the actual probe code inline diff --git a/llvm/lib/CodeGen/CFIFixup.cpp b/llvm/lib/CodeGen/CFIFixup.cpp index 7986f7d213454..eaef14574385a 100644 --- a/llvm/lib/CodeGen/CFIFixup.cpp +++ b/llvm/lib/CodeGen/CFIFixup.cpp @@ -80,6 +80,7 @@ #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCDwarf.h" +#include "llvm/Support/CodeGen.h" #include "llvm/Target/TargetMachine.h" #include @@ -252,6 +253,11 @@ fixupBlock(MachineBasicBlock &CurrBB, const BlockFlagsVector &BlockInfo, if (!Info.Reachable) return false; + // If we don't need to perform full CFI fix up, we only need to fix up the + // first basic block in the section. + if (!TFL.enableFullCFIFixup(MF) && !CurrBB.isBeginSection()) + return false; + // If the previous block and the current block are in the same section, // the frame info will propagate from the previous block to the current one. const BlockFlags &PrevInfo = diff --git a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp index 08e86c705786c..5784974cd8ed9 100644 --- a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp +++ b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp @@ -35,7 +35,7 @@ bool TargetFrameLowering::enableCalleeSaveSkip(const MachineFunction &MF) const return false; } -bool TargetFrameLowering::enableCFIFixup(MachineFunction &MF) const { +bool TargetFrameLowering::enableCFIFixup(const MachineFunction &MF) const { return MF.needsFrameMoves() && !MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); } diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index d3abd79b85a75..d118022395762 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -2612,8 +2612,13 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, } } -bool AArch64FrameLowering::enableCFIFixup(MachineFunction &MF) const { +bool AArch64FrameLowering::enableCFIFixup(const MachineFunction &MF) const { return TargetFrameLowering::enableCFIFixup(MF) && + MF.getInfo()->needsDwarfUnwindInfo(MF); +} + +bool AArch64FrameLowering::enableFullCFIFixup(const MachineFunction &MF) const { + return enableCFIFixup(MF) && MF.getInfo()->needsAsyncDwarfUnwindInfo(MF); } diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.h b/llvm/lib/Target/AArch64/AArch64FrameLowering.h index 8f84702f4d2ba..e7d52bb350f13 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.h +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.h @@ -36,7 +36,9 @@ class AArch64FrameLowering : public TargetFrameLowering { void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - bool enableCFIFixup(MachineFunction &MF) const override; + bool enableCFIFixup(const MachineFunction &MF) const override; + + bool enableFullCFIFixup(const MachineFunction &MF) const override; bool canUseAsPrologue(const MachineBasicBlock &MBB) const override; diff --git a/llvm/test/CodeGen/AArch64/cfi-fixup-multi-section.mir b/llvm/test/CodeGen/AArch64/cfi-fixup-multi-section.mir index a24972d138832..a4c88be375c01 100644 --- a/llvm/test/CodeGen/AArch64/cfi-fixup-multi-section.mir +++ b/llvm/test/CodeGen/AArch64/cfi-fixup-multi-section.mir @@ -10,9 +10,19 @@ ret i32 0 } + define i32 @f1(i32 %x) #1 { + entry: br label %return + if.end: br label %return + if.then2: br label %return + if.else: br label %return + return: + ret i32 0 + } + declare i32 @g(i32) attributes #0 = { nounwind shadowcallstack uwtable "sign-return-address"="non-leaf" "target-features"="+reserve-x18" } + attributes #1 = { nounwind shadowcallstack uwtable(sync) "sign-return-address"="non-leaf" "target-features"="+reserve-x18" } ... --- @@ -197,4 +207,181 @@ body: | B %bb.7 +... +--- +name: f1 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +failsVerification: false +registers: [] +liveins: + - { reg: '$w0', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 16 + offsetAdjustment: 0 + maxAlignment: 16 + adjustsStack: true + hasCalls: true + stackProtector: '' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: '', type: spill-slot, offset: -16, size: 8, alignment: 16, + stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +callSites: [] +debugValueSubstitutions: [] +constants: [] +body: | + ; CHECK-LABEL: name: f1 + ; CHECK: bb.0.entry: + ; CHECK-NEXT: successors: %bb.4(0x30000000), %bb.1(0x50000000) + ; CHECK-NEXT: liveins: $w0, $lr, $x18 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: CBZW renamable $w0, %bb.4 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.1.if.end: + ; CHECK-NEXT: successors: %bb.3(0x30000000), %bb.2(0x50000000) + ; CHECK-NEXT: liveins: $w0, $lr, $x18 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: early-clobber $x18 = frame-setup STRXpost $lr, $x18, 8 + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x16, 0x12, 0x02, 0x82, 0x78 + ; CHECK-NEXT: frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state + ; CHECK-NEXT: early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0) + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16 + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w30, -16 + ; CHECK-NEXT: TBNZW renamable $w0, 31, %bb.3 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.2.if.else: + ; CHECK-NEXT: successors: %bb.5(0x80000000) + ; CHECK-NEXT: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $w0 = nuw nsw ADDWri killed renamable $w0, 1, 0 + ; CHECK-NEXT: BL @g, csr_aarch64_aapcs_scs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit-def $sp, implicit-def $w0 + ; CHECK-NEXT: renamable $w8 = MOVZWi 1, 0 + ; CHECK-NEXT: $w0 = SUBWrs killed renamable $w8, killed renamable $w0, 0 + ; CHECK-NEXT: B %bb.5 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.3.if.then2 (bbsections 1): + ; CHECK-NEXT: successors: %bb.5(0x80000000) + ; CHECK-NEXT: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION escape 0x16, 0x12, 0x02, 0x82, 0x78 + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16 + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $w30, -16 + ; CHECK-NEXT: renamable $w0 = nsw SUBWri killed renamable $w0, 1, 0 + ; CHECK-NEXT: BL @g, csr_aarch64_aapcs_scs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit-def $sp, implicit-def $w0 + ; CHECK-NEXT: renamable $w0 = nsw ADDWri killed renamable $w0, 1, 0 + ; CHECK-NEXT: B %bb.5 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.4.return: + ; CHECK-NEXT: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: RET undef $lr, implicit killed $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.5.return: + ; CHECK-NEXT: successors: %bb.7(0x80000000) + ; CHECK-NEXT: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: B %bb.7 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.6.return: + ; CHECK-NEXT: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0) + ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0 + ; CHECK-NEXT: frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp + ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION negate_ra_sign_state + ; CHECK-NEXT: early-clobber $x18, $lr = frame-destroy LDRXpre $x18, -8 + ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w18 + ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $w30 + ; CHECK-NEXT: RET undef $lr, implicit killed $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.7.return: + ; CHECK-NEXT: successors: %bb.6(0x80000000) + ; CHECK-NEXT: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: B %bb.6 + bb.0.entry: + successors: %bb.4(0x30000000), %bb.1(0x50000000) + liveins: $w0, $lr, $x18 + + CBZW renamable $w0, %bb.4 + + bb.1.if.end: + successors: %bb.3(0x30000000), %bb.2(0x50000000) + liveins: $w0, $lr, $x18 + + early-clobber $x18 = frame-setup STRXpost $lr, $x18, 8 + frame-setup CFI_INSTRUCTION escape 0x16, 0x12, 0x02, 0x82, 0x78 + frame-setup PACIASP implicit-def $lr, implicit killed $lr, implicit $sp + frame-setup CFI_INSTRUCTION negate_ra_sign_state + early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.0) + frame-setup CFI_INSTRUCTION def_cfa_offset 16 + frame-setup CFI_INSTRUCTION offset $w30, -16 + TBNZW renamable $w0, 31, %bb.3 + + bb.2.if.else: + successors: %bb.5(0x80000000) + liveins: $w0 + + renamable $w0 = nuw nsw ADDWri killed renamable $w0, 1, 0 + BL @g, csr_aarch64_aapcs_scs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit-def $sp, implicit-def $w0 + renamable $w8 = MOVZWi 1, 0 + $w0 = SUBWrs killed renamable $w8, killed renamable $w0, 0 + B %bb.5 + + bb.3.if.then2 (bbsections 1): + successors: %bb.5(0x80000000) + liveins: $w0 + + renamable $w0 = nsw SUBWri killed renamable $w0, 1, 0 + BL @g, csr_aarch64_aapcs_scs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit-def $sp, implicit-def $w0 + renamable $w0 = nsw ADDWri killed renamable $w0, 1, 0 + B %bb.5 + + bb.4.return: + liveins: $w0 + RET undef $lr, implicit killed $w0 + + bb.5.return: + liveins: $w0 + B %bb.6 + + bb.7.return: + liveins: $w0 + early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.0) + frame-destroy CFI_INSTRUCTION def_cfa_offset 0 + frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp + frame-destroy CFI_INSTRUCTION negate_ra_sign_state + early-clobber $x18, $lr = frame-destroy LDRXpre $x18, -8 + frame-destroy CFI_INSTRUCTION restore $w18 + frame-destroy CFI_INSTRUCTION restore $w30 + RET undef $lr, implicit killed $w0 + + bb.6.return: + liveins: $w0 + B %bb.7 + + ...