forked from OSchip/llvm-project
[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:
parent
79b44a4d47
commit
fd6584a220
|
@ -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 {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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)> {
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue