[AArch64][SVE] Fix CFA calculation in presence of SVE objects.

The CFA is calculated as (SP/FP + offset), but when there are
SVE objects on the stack the SP offset is partly scalable and
should instead be expressed as the DWARF expression:

     SP + offset + scalable_offset * VG

where VG is the Vector Granule register, containing the
number of 64bits 'granules' in a scalable vector.

Reviewed By: efriedma

Differential Revision: https://reviews.llvm.org/D84043
This commit is contained in:
Sander de Smalen 2020-08-04 10:58:47 +01:00
parent 79b44a4d47
commit fd6584a220
8 changed files with 266 additions and 32 deletions

View File

@ -467,10 +467,12 @@ private:
unsigned Register2;
};
std::vector<char> Values;
std::string Comment;
MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V)
MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V,
StringRef Comment = "")
: Operation(Op), Label(L), Register(R), Offset(O),
Values(V.begin(), V.end()) {
Values(V.begin(), V.end()), Comment(Comment) {
assert(Op != OpRegister);
}
@ -570,8 +572,9 @@ public:
/// .cfi_escape Allows the user to add arbitrary bytes to the unwind
/// info.
static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) {
return MCCFIInstruction(OpEscape, L, 0, 0, Vals);
static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals,
StringRef Comment = "") {
return MCCFIInstruction(OpEscape, L, 0, 0, Vals, Comment);
}
/// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
@ -606,6 +609,10 @@ public:
assert(Operation == OpEscape);
return StringRef(&Values[0], Values.size());
}
StringRef getComment() const {
return Comment;
}
};
struct MCDwarfFrameInfo {

View File

@ -241,6 +241,7 @@ void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
OutStreamer->emitCFIGnuArgsSize(Inst.getOffset());
break;
case MCCFIInstruction::OpEscape:
OutStreamer->AddComment(Inst.getComment());
OutStreamer->emitCFIEscape(Inst.getValues());
break;
case MCCFIInstruction::OpRestore:

View File

@ -148,6 +148,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
@ -399,6 +400,64 @@ static bool ShouldSignReturnAddress(MachineFunction &MF) {
return false;
}
// Convenience function to create a DWARF expression for
// Expr + NumBytes + NumVGScaledBytes * AArch64::VG
static void appendVGScaledOffsetExpr(SmallVectorImpl<char> &Expr,
int NumBytes, int NumVGScaledBytes, unsigned VG,
llvm::raw_string_ostream &Comment) {
uint8_t buffer[16];
if (NumBytes) {
Expr.push_back(dwarf::DW_OP_consts);
Expr.append(buffer, buffer + encodeSLEB128(NumBytes, buffer));
Expr.push_back((uint8_t)dwarf::DW_OP_plus);
Comment << (NumBytes < 0 ? " - " : " + ") << std::abs(NumBytes);
}
if (NumVGScaledBytes) {
Expr.push_back((uint8_t)dwarf::DW_OP_consts);
Expr.append(buffer, buffer + encodeSLEB128(NumVGScaledBytes, buffer));
Expr.push_back((uint8_t)dwarf::DW_OP_bregx);
Expr.append(buffer, buffer + encodeULEB128(VG, buffer));
Expr.push_back(0);
Expr.push_back((uint8_t)dwarf::DW_OP_mul);
Expr.push_back((uint8_t)dwarf::DW_OP_plus);
Comment << (NumVGScaledBytes < 0 ? " - " : " + ")
<< std::abs(NumVGScaledBytes) << " * VG";
}
}
// Creates an MCCFIInstruction:
// { DW_CFA_def_cfa_expression, ULEB128 (sizeof expr), expr }
MCCFIInstruction AArch64FrameLowering::createDefCFAExpressionFromSP(
const TargetRegisterInfo &TRI, const StackOffset &OffsetFromSP) const {
int64_t NumBytes, NumVGScaledBytes;
OffsetFromSP.getForDwarfOffset(NumBytes, NumVGScaledBytes);
std::string CommentBuffer = "sp";
llvm::raw_string_ostream Comment(CommentBuffer);
// Build up the expression (SP + NumBytes + NumVGScaledBytes * AArch64::VG)
SmallString<64> Expr;
Expr.push_back(dwarf::DW_OP_breg0 + /*SP*/ 31);
Expr.push_back(0);
appendVGScaledOffsetExpr(Expr, NumBytes, NumVGScaledBytes,
TRI.getDwarfRegNum(AArch64::VG, true), Comment);
// Wrap this into DW_CFA_def_cfa.
SmallString<64> DefCfaExpr;
DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
uint8_t buffer[16];
DefCfaExpr.append(buffer,
buffer + encodeULEB128(Expr.size(), buffer));
DefCfaExpr.append(Expr.str());
return MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str(),
Comment.str());
}
void AArch64FrameLowering::emitCalleeSavedFrameMoves(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const {
MachineFunction &MF = *MBB.getParent();
@ -1383,9 +1442,18 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
.addCFIIndex(CFIIndex)
.setMIFlags(MachineInstr::FrameSetup);
} else {
// Encode the stack size of the leaf function.
unsigned CFIIndex = MF.addFrameInst(
MCCFIInstruction::cfiDefCfaOffset(nullptr, MFI.getStackSize()));
unsigned CFIIndex;
if (SVEStackSize) {
const TargetSubtargetInfo &STI = MF.getSubtarget();
const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
StackOffset TotalSize =
SVEStackSize + StackOffset((int64_t)MFI.getStackSize(), MVT::i8);
CFIIndex = MF.addFrameInst(createDefCFAExpressionFromSP(TRI, TotalSize));
} else {
// Encode the stack size of the leaf function.
CFIIndex = MF.addFrameInst(
MCCFIInstruction::cfiDefCfaOffset(nullptr, MFI.getStackSize()));
}
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlags(MachineInstr::FrameSetup);

View File

@ -18,6 +18,8 @@
namespace llvm {
class MCCFIInstruction;
class AArch64FrameLowering : public TargetFrameLowering {
public:
explicit AArch64FrameLowering()
@ -119,6 +121,11 @@ private:
int64_t assignSVEStackObjectOffsets(MachineFrameInfo &MF,
int &MinCSFrameIndex,
int &MaxCSFrameIndex) const;
MCCFIInstruction
createDefCFAExpressionFromSP(const TargetRegisterInfo &TRI,
const StackOffset &OffsetFromSP) const;
MCCFIInstruction createCfaOffset(const MCRegisterInfo &MRI, unsigned DwarfReg,
const StackOffset &OffsetFromDefCFA) const;
bool shouldCombineCSRLocalStackBumpInEpilogue(MachineBasicBlock &MBB,
unsigned StackBumpBytes) const;
};

View File

@ -133,6 +133,9 @@ def NZCV : AArch64Reg<0, "nzcv">;
// First fault status register
def FFR : AArch64Reg<0, "ffr">, DwarfRegNum<[47]>;
// Purely virtual Vector Granule (VG) Dwarf register
def VG : AArch64Reg<0, "vg">, DwarfRegNum<[46]>;
// GPR register classes with the intersections of GPR32/GPR32sp and
// GPR64/GPR64sp for use by the coalescer.
def GPR32common : RegisterClass<"AArch64", [i32], 32, (sequence "W%u", 0, 30)> {

View File

@ -123,6 +123,18 @@ public:
}
}
void getForDwarfOffset(int64_t &ByteSized, int64_t &VGSized) const {
assert(isValid() && "Invalid frame offset");
// VGSized offsets are divided by '2', because the VG register is the
// the number of 64bit granules as opposed to 128bit vector chunks,
// which is how the 'n' in e.g. MVT::nxv1i8 is modelled.
// So, for a stack offset of 16 MVT::nxv1i8's, the size is n x 16 bytes.
// VG = n * 2 and the dwarf offset must be VG * 8 bytes.
ByteSized = Bytes;
VGSized = ScalableBytes / 2;
}
/// Returns whether the offset is known zero.
explicit operator bool() const { return Bytes || ScalableBytes; }

View File

@ -1,4 +1,8 @@
# RUN: llc -mattr=+sve -mtriple=aarch64-none-linux-gnu -run-pass=prologepilog %s -o - | FileCheck %s
# RUN: llc -mtriple=aarch64-none-linux-gnu -mattr=+sve -start-before=prologepilog %s -o - | FileCheck %s --check-prefix=ASM
# RUN: llc -mtriple=aarch64-none-linux-gnu -mattr=+sve -start-before=prologepilog %s -filetype=obj -o %t
# RUN: llvm-objdump --dwarf=frames %t | FileCheck %s --check-prefix=UNWINDINFO
# RUN: rm -rf %t
#
# Test allocation and deallocation of SVE objects on the stack,
# as well as using a combination of scalable and non-scalable
@ -23,19 +27,19 @@
#
--- |
define void @test_allocate_sve() nounwind { entry: unreachable }
define void @test_allocate_sve_gpr_callee_saves() nounwind { entry: unreachable }
define void @test_allocate_sve_gpr_realigned() nounwind { entry: unreachable }
define void @test_address_sve() nounwind { entry: unreachable }
define void @test_address_sve_fp() nounwind { entry: unreachable }
define void @test_stack_arg_sve() nounwind { entry: unreachable }
define void @test_address_sve_out_of_range() nounwind { entry: unreachable }
define void @test_address_gpr_vla() nounwind { entry: unreachable }
define aarch64_sve_vector_pcs void @save_restore_pregs_sve() nounwind { entry: unreachable }
define aarch64_sve_vector_pcs void @save_restore_zregs_sve() nounwind { entry: unreachable }
define aarch64_sve_vector_pcs void @save_restore_sve() nounwind { entry: unreachable }
define aarch64_sve_vector_pcs void @save_restore_sve_realign() nounwind { entry: unreachable }
define aarch64_sve_vector_pcs void @frame_layout() nounwind { entry: unreachable }
define void @test_allocate_sve() { entry: unreachable }
define void @test_allocate_sve_gpr_callee_saves() { entry: unreachable }
define void @test_allocate_sve_gpr_realigned() { entry: unreachable }
define void @test_address_sve() { entry: unreachable }
define void @test_address_sve_fp() { entry: unreachable }
define void @test_stack_arg_sve() { entry: unreachable }
define void @test_address_sve_out_of_range() { entry: unreachable }
define void @test_address_gpr_vla() { entry: unreachable }
define aarch64_sve_vector_pcs void @save_restore_pregs_sve() { entry: unreachable }
define aarch64_sve_vector_pcs void @save_restore_zregs_sve() { entry: unreachable }
define aarch64_sve_vector_pcs void @save_restore_sve() { entry: unreachable }
define aarch64_sve_vector_pcs void @save_restore_sve_realign() { entry: unreachable }
define aarch64_sve_vector_pcs void @frame_layout() { entry: unreachable }
...
# +----------+
@ -54,11 +58,19 @@
# CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -16
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -2
# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
# CHECK-COUNT-2: frame-setup CFI_INSTRUCTION
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 2
# CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0
# CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 16
# CHECK-NEXT: RET_ReallyLR
# ASM-LABEL: test_allocate_sve:
# ASM: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 32 + 16 * VG
# ASM-NEXT: .cfi_offset w29, -16
#
# UNWINDINFO: DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +32, DW_OP_plus, DW_OP_consts +16, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
name: test_allocate_sve
stack:
- { id: 0, stack-id: sve-vec, size: 18, alignment: 2 }
@ -85,6 +97,8 @@ body: |
# CHECK-NEXT: frame-setup STPXi killed $x21, killed $x20, $sp, 2
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -2
# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
# CHECK-COUNT-4: frame-setup CFI_INSTRUCTION
#
# CHECK-NEXT: $x20 = IMPLICIT_DEF
# CHECK-NEXT: $x21 = IMPLICIT_DEF
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 2
@ -92,6 +106,17 @@ body: |
# CHECK-NEXT: $x21, $x20 = frame-destroy LDPXi $sp, 2
# CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 32
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: test_allocate_sve_gpr_callee_saves:
# ASM: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x30, 0x22, 0x11, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 48 + 16 * VG
# ASM-NEXT: .cfi_offset w20, -8
# ASM-NEXT: .cfi_offset w21, -16
# ASM-NEXT: .cfi_offset w29, -32
#
# UNWINDINFO: DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +48, DW_OP_plus, DW_OP_consts +16, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_offset: reg20 -8
# UNWINDINFO-NEXT: DW_CFA_offset: reg21 -16
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -32
name: test_allocate_sve_gpr_callee_saves
stack:
- { id: 0, stack-id: sve-vec, size: 18, alignment: 2 }
@ -120,9 +145,20 @@ body: |
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -2
# CHECK-NEXT: $[[TMP:x[0-9]+]] = frame-setup SUBXri $sp, 16, 0
# CHECK-NEXT: $sp = ANDXri killed $[[TMP]]
# CHECK-COUNT-3: frame-setup CFI_INSTRUCTION
# CHECK-NEXT: $sp = frame-destroy ADDXri $fp, 0, 0
# CHECK-NEXT: $sp, $fp, $lr = frame-destroy LDPXpost $sp, 2
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: test_allocate_sve_gpr_realigned:
# ASM: .cfi_def_cfa w29, 16
# ASM-NEXT: .cfi_offset w30, -8
# ASM-NEXT: .cfi_offset w29, -16
#
# UNWINDINFO: DW_CFA_def_cfa: reg29 +16
# UNWINDINFO-NEXT: DW_CFA_offset: reg30 -8
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
name: test_allocate_sve_gpr_realigned
stack:
- { id: 0, stack-id: sve-vec, size: 18, alignment: 2 }
@ -149,6 +185,7 @@ body: |
# CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -16
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3
# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
# CHECK-COUNT-2: frame-setup CFI_INSTRUCTION
# CHECK-NEXT: $[[TMP:x[0-9]+]] = ADDXri $sp, 16
# CHECK-NEXT: STR_ZXI $z0, killed $[[TMP]], 2
@ -161,6 +198,14 @@ body: |
# CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0
# CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 16
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: test_address_sve:
# ASM: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 32 + 24 * VG
# ASM-NEXT: .cfi_offset w29, -16
#
# UNWINDINFO: DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +32, DW_OP_plus, DW_OP_consts +24, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
name: test_address_sve
frameInfo:
maxAlignment: 16
@ -199,6 +244,7 @@ body: |
# CHECK-NEXT: $fp = frame-setup ADDXri $sp, 0, 0
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3
# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
# CHECK-COUNT-3: frame-setup CFI_INSTRUCTION
# CHECK-NEXT: STR_ZXI $z0, $fp, -1
# CHECK-NEXT: STR_ZXI $z1, $fp, -2
@ -208,6 +254,15 @@ body: |
# CHECK: $sp = frame-destroy ADDXri $sp, 16, 0
# CHECK-NEXT: $sp, $fp, $lr = frame-destroy LDPXpost $sp, 2
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: test_address_sve_fp:
# ASM: .cfi_def_cfa w29, 16
# ASM-NEXT: .cfi_offset w30, -8
# ASM-NEXT: .cfi_offset w29, -16
#
# UNWINDINFO: DW_CFA_def_cfa: reg29 +16
# UNWINDINFO-NEXT: DW_CFA_offset: reg30 -8
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
name: test_address_sve_fp
frameInfo:
maxAlignment: 16
@ -244,6 +299,7 @@ body: |
# CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -16
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1
# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
# CHECK-COUNT-2: frame-setup CFI_INSTRUCTION
# CHECK: $[[TMP:x[0-9]+]] = ADDVL_XXI $sp, 1
# CHECK-NEXT: $x0 = LDRXui killed $[[TMP]], 4
@ -252,6 +308,14 @@ body: |
# CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0
# CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 16
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: test_stack_arg_sve:
# ASM: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x20, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 32 + 8 * VG
# ASM-NEXT: .cfi_offset w29, -16
#
# UNWINDINFO: DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +32, DW_OP_plus, DW_OP_consts +8, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
name: test_stack_arg_sve
fixedStack:
- { id: 0, stack-id: default, size: 16, alignment: 16, offset: 0 }
@ -292,6 +356,7 @@ body: |
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1
# CHECK-COUNT-2: frame-setup CFI_INSTRUCTION
# CHECK-NEXT: $[[TMP2:x[0-9]+]] = ADDVL_XXI $sp, 1
# CHECK-NEXT: STR_ZXI $z0, killed $[[TMP2]], 255
@ -310,6 +375,13 @@ body: |
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 9
# CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 16
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: test_address_sve_out_of_range:
# ASM: .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x88, 0x10, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 2056 * VG
# ASM-NEXT: .cfi_offset w29, -16
#
# UNWINDINFO: DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +2056, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
name: test_address_sve_out_of_range
frameInfo:
maxAlignment: 16
@ -344,6 +416,17 @@ body: |
# CHECK: bb.0.entry:
# CHECK: STRXui $xzr, $x19, 0
# CHECK: RET_ReallyLR
#
# ASM-LABEL: test_address_gpr_vla:
# ASM: .cfi_def_cfa w29, 32
# ASM-NEXT: .cfi_offset w19, -16
# ASM-NEXT: .cfi_offset w30, -24
# ASM-NEXT: .cfi_offset w29, -32
#
# UNWINDINFO: DW_CFA_def_cfa: reg29 +32
# UNWINDINFO-NEXT: DW_CFA_offset: reg19 -16
# UNWINDINFO-NEXT: DW_CFA_offset: reg30 -24
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -32
name: test_address_gpr_vla
frameInfo:
maxAlignment: 16
@ -366,6 +449,7 @@ body: |
# CHECK: frame-setup STR_PXI killed $p5, $sp, 6
# CHECK: frame-setup STR_PXI killed $p4, $sp, 7
# CHECK: $sp = frame-setup SUBXri $sp, 32, 0
# CHECK-COUNT-5: frame-setup CFI_INSTRUCTION
# CHECK: $sp = frame-destroy ADDXri $sp, 32, 0
# CHECK: $p6 = frame-destroy LDR_PXI $sp, 5
@ -373,6 +457,15 @@ body: |
# CHECK: $p4 = frame-destroy LDR_PXI $sp, 7
# CHECK: $sp = frame-destroy ADDVL_XXI $sp, 1
# CHECK: RET_ReallyLR
#
# ASM-LABEL: save_restore_pregs_sve:
# ASM: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x30, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 48 + 8 * VG
# ASM-COUNT-3: .cfi_offset
# ASM-NEXT: .cfi_offset w29, -16
#
# UNWINDINFO: DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +48, DW_OP_plus, DW_OP_consts +8, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-COUNT-3: DW_CFA_offset
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
name: save_restore_pregs_sve
stack:
- { id: 0, stack-id: default, size: 32, alignment: 16 }
@ -387,18 +480,29 @@ body: |
---
...
# CHECK-LABEL: name: save_restore_zregs_sve
# CHECK: $sp = frame-setup ADDVL_XXI $sp, -3
# CHECK: frame-setup STR_ZXI killed $z10, $sp, 0
# CHECK: frame-setup STR_ZXI killed $z9, $sp, 1
# CHECK: frame-setup STR_ZXI killed $z8, $sp, 2
# CHECK: $sp = frame-setup SUBXri $sp, 32, 0
# CHECK: $sp = frame-setup STRXpre killed $fp, $sp, -16
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3
# CHECK-NEXT: frame-setup STR_ZXI killed $z10, $sp, 0
# CHECK-NEXT: frame-setup STR_ZXI killed $z9, $sp, 1
# CHECK-NEXT: frame-setup STR_ZXI killed $z8, $sp, 2
# CHECK-NEXT: $sp = frame-setup SUBXri $sp, 32, 0
# CHECK-COUNT-5: frame-setup CFI_INSTRUCTION
# CHECK: $sp = frame-destroy ADDXri $sp, 32, 0
# CHECK: $z10 = frame-destroy LDR_ZXI $sp, 0
# CHECK: $z9 = frame-destroy LDR_ZXI $sp, 1
# CHECK: $z8 = frame-destroy LDR_ZXI $sp, 2
# CHECK: $sp = frame-destroy ADDVL_XXI $sp, 3
# CHECK: RET_ReallyLR
# CHECK: $sp = frame-destroy ADDXri $sp, 32, 0
# CHECK-NEXT: $z10 = frame-destroy LDR_ZXI $sp, 0
# CHECK-NEXT: $z9 = frame-destroy LDR_ZXI $sp, 1
# CHECK-NEXT: $z8 = frame-destroy LDR_ZXI $sp, 2
# CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 3
# CHECK-NEXT: $sp, $fp = frame-destroy LDRXpost $sp, 16
# CHECK-NEXT: RET_ReallyLR
#
# ASM-LABEL: save_restore_zregs_sve:
# ASM: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x30, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 48 + 24 * VG
# ASM-COUNT-3: .cfi_offset
#
# UNWINDINFO: DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +48, DW_OP_plus, DW_OP_consts +24, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-COUNT-3: DW_CFA_offset
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
name: save_restore_zregs_sve
stack:
- { id: 0, stack-id: default, size: 32, alignment: 16 }
@ -432,6 +536,7 @@ body: |
# CHECK: frame-setup STR_ZXI killed $z8, $sp, 17
# CHECK: $sp = frame-setup ADDVL_XXI $sp, -1
# CHECK: $sp = frame-setup SUBXri $sp, 32, 0
# CHECK-COUNT-33: frame-setup CFI_INSTRUCTION
# CHECK: $sp = frame-destroy ADDXri $sp, 32, 0
# CHECK: $sp = frame-destroy ADDVL_XXI $sp, 1
@ -447,6 +552,22 @@ body: |
# CHECK: $x20, $x19 = frame-destroy LDPXi $sp, 2
# CHECK: $sp, ${{[a-z0-9]+}}, $x21 = frame-destroy LDPXpost $sp, 4
# CHECK: RET_ReallyLR
#
# ASM-LABEL: save_restore_sve:
# ASM: .cfi_escape 0x0f, 0x0e, 0x8f, 0x00, 0x11, 0xc0, 0x00, 0x22, 0x11, 0x98, 0x01, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 64 + 152 * VG
# ASM-COUNT-28: .cfi_offset
# ASM-NEXT: .cfi_offset w19, -8
# ASM-NEXT: .cfi_offset w20, -16
# ASM-NEXT: .cfi_offset w21, -24
# ASM-NEXT: .cfi_offset w29, -32
#
# UNWINDINFO: DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +64, DW_OP_plus, DW_OP_consts +152, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-COUNT-28: DW_CFA_offset
# UNWINDINFO-NEXT: DW_CFA_offset: reg19 -8
# UNWINDINFO-NEXT: DW_CFA_offset: reg20 -16
# UNWINDINFO-NEXT: DW_CFA_offset: reg21 -24
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -32
name: save_restore_sve
stack:
- { id: 0, stack-id: sve-vec, size: 16, alignment: 16 }
@ -499,6 +620,7 @@ body: |
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1
# CHECK-NEXT: $[[TMP:x[0-9]+]] = frame-setup SUBXri $sp, 16, 0
# CHECK-NEXT: $sp = ANDXri killed $[[TMP]]
# CHECK-COUNT-31: frame-setup CFI_INSTRUCTION
# CHECK: $sp = frame-destroy ADDVL_XXI $fp, -18
# CHECK-NEXT: $p15 = frame-destroy LDR_PXI $sp, 4
@ -512,6 +634,11 @@ body: |
# CHECK-NEXT: $sp = frame-destroy ADDXri $fp, 0, 0
# CHECK-NEXT: $sp, $fp, $lr = frame-destroy LDPXpost $sp, 2
# CHECK-NEXT: RET_ReallyLR
#
# UNWINDINFO: DW_CFA_def_cfa: reg29 +16
# UNWINDINFO-COUNT-28: DW_CFA_offset
# UNWINDINFO-NEXT: DW_CFA_offset: reg30 -8
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
name: save_restore_sve_realign
stack:
- { id: 0, stack-id: sve-vec, size: 16, alignment: 16 }
@ -586,6 +713,15 @@ body: |
# CHECK-NEXT: STR_ZXI killed $z23, $sp, 1
# CHECK-NEXT: STR_ZXI killed $z8, $sp, 2
# CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -7
# CHECK-COUNT-6: frame-setup CFI_INSTRUCTION
# ASM-LABEL: frame_layout:
# ASM: .cfi_escape 0x0f, 0x0d, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0xd0, 0x00, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 80 * VG
# ASM-COUNT-4: .cfi_offset
# ASM-NEXT: .cfi_offset w29, -16
#
# UNWINDINFO: DW_CFA_def_cfa_expression: DW_OP_breg31 +0, DW_OP_consts +16, DW_OP_plus, DW_OP_consts +80, DW_OP_bregx 0x2e +0, DW_OP_mul, DW_OP_plus
# UNWINDINFO-COUNT-4: DW_CFA_offset
# UNWINDINFO-NEXT: DW_CFA_offset: reg29 -16
name: frame_layout
stack:
- { id: 0, type: default, size: 32, alignment: 16, stack-id: sve-vec }

View File

@ -116,7 +116,7 @@ define <vscale x 16 x i1> @trunc_i64toi1_split3(<vscale x 16 x i64> %in) {
; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill
; CHECK-NEXT: addvl sp, sp, #-1
; CHECK-NEXT: str p4, [sp, #7, mul vl] // 2-byte Folded Spill
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 8 * VG
; CHECK-NEXT: .cfi_offset p4, -2
; CHECK-NEXT: .cfi_offset w29, -16
; CHECK-NEXT: ptrue p0.d