[SystemZ] Add support for anyregcc calling convention
This adds back-end support for the anyregcc calling convention for use with patchpoints. Since all registers are considered call-saved with anyregcc (except for 0 and 1 which may still be clobbered by PLT stubs and the like), this required adding support for saving and restoring vector registers in prologue/epilogue code for the first time. This is not used by any other calling convention. llvm-svn: 326612
This commit is contained in:
parent
5eb64110d2
commit
8b19be46c7
|
@ -120,3 +120,12 @@ def CSR_SystemZ : CalleeSavedRegs<(add (sequence "R%dD", 6, 15),
|
|||
|
||||
// R9 is used to return SwiftError; remove it from CSR.
|
||||
def CSR_SystemZ_SwiftError : CalleeSavedRegs<(sub CSR_SystemZ, R9D)>;
|
||||
|
||||
// "All registers" as used by the AnyReg calling convention.
|
||||
// Note that registers 0 and 1 are still defined as intra-call scratch
|
||||
// registers that may be clobbered e.g. by PLT stubs.
|
||||
def CSR_SystemZ_AllRegs : CalleeSavedRegs<(add (sequence "R%dD", 2, 15),
|
||||
(sequence "F%dD", 0, 15))>;
|
||||
def CSR_SystemZ_AllRegs_Vector : CalleeSavedRegs<(add (sequence "R%dD", 2, 15),
|
||||
(sequence "V%d", 0, 31))>;
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
|||
addSavedGPR(MBB, MIB, SystemZ::ArgGPRs[I], true);
|
||||
}
|
||||
|
||||
// Save FPRs in the normal TargetInstrInfo way.
|
||||
// Save FPRs/VRs in the normal TargetInstrInfo way.
|
||||
for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
|
||||
unsigned Reg = CSI[I].getReg();
|
||||
if (SystemZ::FP64BitRegClass.contains(Reg)) {
|
||||
|
@ -212,6 +212,11 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
|||
TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(),
|
||||
&SystemZ::FP64BitRegClass, TRI);
|
||||
}
|
||||
if (SystemZ::VR128BitRegClass.contains(Reg)) {
|
||||
MBB.addLiveIn(Reg);
|
||||
TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(),
|
||||
&SystemZ::VR128BitRegClass, TRI);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -231,12 +236,15 @@ restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
|||
bool HasFP = hasFP(MF);
|
||||
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||
|
||||
// Restore FPRs in the normal TargetInstrInfo way.
|
||||
// Restore FPRs/VRs in the normal TargetInstrInfo way.
|
||||
for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
|
||||
unsigned Reg = CSI[I].getReg();
|
||||
if (SystemZ::FP64BitRegClass.contains(Reg))
|
||||
TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(),
|
||||
&SystemZ::FP64BitRegClass, TRI);
|
||||
if (SystemZ::VR128BitRegClass.contains(Reg))
|
||||
TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(),
|
||||
&SystemZ::VR128BitRegClass, TRI);
|
||||
}
|
||||
|
||||
// Restore call-saved GPRs (but not call-clobbered varargs, which at
|
||||
|
@ -425,7 +433,7 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF,
|
|||
I->addLiveIn(SystemZ::R11D);
|
||||
}
|
||||
|
||||
// Skip over the FPR saves.
|
||||
// Skip over the FPR/VR saves.
|
||||
SmallVector<unsigned, 8> CFIIndexes;
|
||||
for (auto &Save : CSI) {
|
||||
unsigned Reg = Save.getReg();
|
||||
|
@ -436,6 +444,14 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF,
|
|||
++MBBI;
|
||||
else
|
||||
llvm_unreachable("Couldn't skip over FPR save");
|
||||
} else if (SystemZ::VR128BitRegClass.contains(Reg)) {
|
||||
if (MBBI != MBB.end() &&
|
||||
MBBI->getOpcode() == SystemZ::VST)
|
||||
++MBBI;
|
||||
else
|
||||
llvm_unreachable("Couldn't skip over VR save");
|
||||
} else
|
||||
continue;
|
||||
|
||||
// Add CFI for the this save.
|
||||
unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
|
||||
|
@ -447,8 +463,7 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF,
|
|||
nullptr, DwarfReg, SPOffsetFromCFA + Offset));
|
||||
CFIIndexes.push_back(CFIIndex);
|
||||
}
|
||||
}
|
||||
// Complete the CFI for the FPR saves, modelling them as taking effect
|
||||
// Complete the CFI for the FPR/VR saves, modelling them as taking effect
|
||||
// after the last save.
|
||||
for (auto CFIIndex : CFIIndexes) {
|
||||
BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
|
||||
|
|
|
@ -108,6 +108,10 @@ SystemZRegisterInfo::getRegAllocationHints(unsigned VirtReg,
|
|||
|
||||
const MCPhysReg *
|
||||
SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
||||
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
|
||||
if (MF->getFunction().getCallingConv() == CallingConv::AnyReg)
|
||||
return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_SaveList
|
||||
: CSR_SystemZ_AllRegs_SaveList;
|
||||
if (MF->getSubtarget().getTargetLowering()->supportSwiftError() &&
|
||||
MF->getFunction().getAttributes().hasAttrSomewhere(
|
||||
Attribute::SwiftError))
|
||||
|
@ -118,6 +122,10 @@ SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
|||
const uint32_t *
|
||||
SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
|
||||
CallingConv::ID CC) const {
|
||||
const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
|
||||
if (CC == CallingConv::AnyReg)
|
||||
return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_RegMask
|
||||
: CSR_SystemZ_AllRegs_RegMask;
|
||||
if (MF.getSubtarget().getTargetLowering()->supportSwiftError() &&
|
||||
MF.getFunction().getAttributes().hasAttrSomewhere(
|
||||
Attribute::SwiftError))
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Make sure all regs are spilled
|
||||
define anyregcc void @anyregcc1() {
|
||||
entry:
|
||||
;CHECK-LABEL: anyregcc1
|
||||
;CHECK: stmg %r2, %r15, 16(%r15)
|
||||
;CHECK: std %f0,
|
||||
;CHECK: std %f1,
|
||||
;CHECK: std %f2,
|
||||
;CHECK: std %f3,
|
||||
;CHECK: std %f4,
|
||||
;CHECK: std %f5,
|
||||
;CHECK: std %f6,
|
||||
;CHECK: std %f7,
|
||||
;CHECK: std %f8,
|
||||
;CHECK: std %f9,
|
||||
;CHECK: std %f10,
|
||||
;CHECK: std %f11,
|
||||
;CHECK: std %f12,
|
||||
;CHECK: std %f13,
|
||||
;CHECK: std %f14,
|
||||
;CHECK: std %f15,
|
||||
call void asm sideeffect "", "~{r0},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f8},~{f9},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15}"() nounwind
|
||||
ret void
|
||||
}
|
||||
|
||||
; Make sure we don't spill any FPs
|
||||
declare anyregcc void @foo()
|
||||
define void @anyregcc2() {
|
||||
entry:
|
||||
;CHECK-LABEL: anyregcc2
|
||||
;CHECK-NOT: std
|
||||
;CHECK: std %f8,
|
||||
;CHECK-NEXT: std %f9,
|
||||
;CHECK-NEXT: std %f10,
|
||||
;CHECK-NEXT: std %f11,
|
||||
;CHECK-NEXT: std %f12,
|
||||
;CHECK-NEXT: std %f13,
|
||||
;CHECK-NEXT: std %f14,
|
||||
;CHECK-NEXT: std %f15,
|
||||
;CHECK-NOT: std
|
||||
%a0 = call double asm sideeffect "", "={f0}"() nounwind
|
||||
%a1 = call double asm sideeffect "", "={f1}"() nounwind
|
||||
%a2 = call double asm sideeffect "", "={f2}"() nounwind
|
||||
%a3 = call double asm sideeffect "", "={f3}"() nounwind
|
||||
%a4 = call double asm sideeffect "", "={f4}"() nounwind
|
||||
%a5 = call double asm sideeffect "", "={f5}"() nounwind
|
||||
%a6 = call double asm sideeffect "", "={f6}"() nounwind
|
||||
%a7 = call double asm sideeffect "", "={f7}"() nounwind
|
||||
%a8 = call double asm sideeffect "", "={f8}"() nounwind
|
||||
%a9 = call double asm sideeffect "", "={f9}"() nounwind
|
||||
%a10 = call double asm sideeffect "", "={f10}"() nounwind
|
||||
%a11 = call double asm sideeffect "", "={f11}"() nounwind
|
||||
%a12 = call double asm sideeffect "", "={f12}"() nounwind
|
||||
%a13 = call double asm sideeffect "", "={f13}"() nounwind
|
||||
%a14 = call double asm sideeffect "", "={f14}"() nounwind
|
||||
%a15 = call double asm sideeffect "", "={f15}"() nounwind
|
||||
call anyregcc void @foo()
|
||||
call void asm sideeffect "", "{f0},{f1},{f2},{f3},{f4},{f5},{f6},{f7},{f8},{f9},{f10},{f11},{f12},{f13},{f14},{f15}"(double %a0, double %a1, double %a2, double %a3, double %a4, double %a5, double %a6, double %a7, double %a8, double %a9, double %a10, double %a11, double %a12, double %a13, double %a14, double %a15)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
|
||||
declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
|
|
@ -0,0 +1,99 @@
|
|||
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s
|
||||
|
||||
; Make sure all regs are spilled
|
||||
define anyregcc void @anyregcc1() {
|
||||
entry:
|
||||
;CHECK-LABEL: anyregcc1
|
||||
;CHECK: stmg %r2, %r15, 16(%r15)
|
||||
;CHECK: vst %v0,
|
||||
;CHECK: vst %v1,
|
||||
;CHECK: vst %v2,
|
||||
;CHECK: vst %v3,
|
||||
;CHECK: vst %v4,
|
||||
;CHECK: vst %v5,
|
||||
;CHECK: vst %v6,
|
||||
;CHECK: vst %v7,
|
||||
;CHECK: vst %v8,
|
||||
;CHECK: vst %v9,
|
||||
;CHECK: vst %v10,
|
||||
;CHECK: vst %v11,
|
||||
;CHECK: vst %v12,
|
||||
;CHECK: vst %v13,
|
||||
;CHECK: vst %v14,
|
||||
;CHECK: vst %v15,
|
||||
;CHECK: vst %v16,
|
||||
;CHECK: vst %v17,
|
||||
;CHECK: vst %v18,
|
||||
;CHECK: vst %v19,
|
||||
;CHECK: vst %v20,
|
||||
;CHECK: vst %v21,
|
||||
;CHECK: vst %v22,
|
||||
;CHECK: vst %v23,
|
||||
;CHECK: vst %v24,
|
||||
;CHECK: vst %v25,
|
||||
;CHECK: vst %v26,
|
||||
;CHECK: vst %v27,
|
||||
;CHECK: vst %v28,
|
||||
;CHECK: vst %v29,
|
||||
;CHECK: vst %v30,
|
||||
;CHECK: vst %v31,
|
||||
call void asm sideeffect "", "~{r0},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"() nounwind
|
||||
ret void
|
||||
}
|
||||
|
||||
; Make sure we don't spill any FPs
|
||||
declare anyregcc void @foo()
|
||||
define void @anyregcc2() {
|
||||
entry:
|
||||
;CHECK-LABEL: anyregcc2
|
||||
;CHECK-NOT: std
|
||||
;CHECK-NOT: vst
|
||||
;CHECK: std %f8,
|
||||
;CHECK-NEXT: std %f9,
|
||||
;CHECK-NEXT: std %f10,
|
||||
;CHECK-NEXT: std %f11,
|
||||
;CHECK-NEXT: std %f12,
|
||||
;CHECK-NEXT: std %f13,
|
||||
;CHECK-NEXT: std %f14,
|
||||
;CHECK-NEXT: std %f15,
|
||||
;CHECK-NOT: std
|
||||
;CHECK-NOT: vst
|
||||
%a0 = call <2 x i64> asm sideeffect "", "={v0}"() nounwind
|
||||
%a1 = call <2 x i64> asm sideeffect "", "={v1}"() nounwind
|
||||
%a2 = call <2 x i64> asm sideeffect "", "={v2}"() nounwind
|
||||
%a3 = call <2 x i64> asm sideeffect "", "={v3}"() nounwind
|
||||
%a4 = call <2 x i64> asm sideeffect "", "={v4}"() nounwind
|
||||
%a5 = call <2 x i64> asm sideeffect "", "={v5}"() nounwind
|
||||
%a6 = call <2 x i64> asm sideeffect "", "={v6}"() nounwind
|
||||
%a7 = call <2 x i64> asm sideeffect "", "={v7}"() nounwind
|
||||
%a8 = call <2 x i64> asm sideeffect "", "={v8}"() nounwind
|
||||
%a9 = call <2 x i64> asm sideeffect "", "={v9}"() nounwind
|
||||
%a10 = call <2 x i64> asm sideeffect "", "={v10}"() nounwind
|
||||
%a11 = call <2 x i64> asm sideeffect "", "={v11}"() nounwind
|
||||
%a12 = call <2 x i64> asm sideeffect "", "={v12}"() nounwind
|
||||
%a13 = call <2 x i64> asm sideeffect "", "={v13}"() nounwind
|
||||
%a14 = call <2 x i64> asm sideeffect "", "={v14}"() nounwind
|
||||
%a15 = call <2 x i64> asm sideeffect "", "={v15}"() nounwind
|
||||
%a16 = call <2 x i64> asm sideeffect "", "={v16}"() nounwind
|
||||
%a17 = call <2 x i64> asm sideeffect "", "={v17}"() nounwind
|
||||
%a18 = call <2 x i64> asm sideeffect "", "={v18}"() nounwind
|
||||
%a19 = call <2 x i64> asm sideeffect "", "={v19}"() nounwind
|
||||
%a20 = call <2 x i64> asm sideeffect "", "={v20}"() nounwind
|
||||
%a21 = call <2 x i64> asm sideeffect "", "={v21}"() nounwind
|
||||
%a22 = call <2 x i64> asm sideeffect "", "={v22}"() nounwind
|
||||
%a23 = call <2 x i64> asm sideeffect "", "={v23}"() nounwind
|
||||
%a24 = call <2 x i64> asm sideeffect "", "={v24}"() nounwind
|
||||
%a25 = call <2 x i64> asm sideeffect "", "={v25}"() nounwind
|
||||
%a26 = call <2 x i64> asm sideeffect "", "={v26}"() nounwind
|
||||
%a27 = call <2 x i64> asm sideeffect "", "={v27}"() nounwind
|
||||
%a28 = call <2 x i64> asm sideeffect "", "={v28}"() nounwind
|
||||
%a29 = call <2 x i64> asm sideeffect "", "={v29}"() nounwind
|
||||
%a30 = call <2 x i64> asm sideeffect "", "={v30}"() nounwind
|
||||
%a31 = call <2 x i64> asm sideeffect "", "={v31}"() nounwind
|
||||
call anyregcc void @foo()
|
||||
call void asm sideeffect "", "{v0},{v1},{v2},{v3},{v4},{v5},{v6},{v7},{v8},{v9},{v10},{v11},{v12},{v13},{v14},{v15},{v16},{v17},{v18},{v19},{v20},{v21},{v22},{v23},{v24},{v25},{v26},{v27},{v28},{v29},{v30},{v31}"(<2 x i64> %a0, <2 x i64> %a1, <2 x i64> %a2, <2 x i64> %a3, <2 x i64> %a4, <2 x i64> %a5, <2 x i64> %a6, <2 x i64> %a7, <2 x i64> %a8, <2 x i64> %a9, <2 x i64> %a10, <2 x i64> %a11, <2 x i64> %a12, <2 x i64> %a13, <2 x i64> %a14, <2 x i64> %a15, <2 x i64> %a16, <2 x i64> %a17, <2 x i64> %a18, <2 x i64> %a19, <2 x i64> %a20, <2 x i64> %a21, <2 x i64> %a22, <2 x i64> %a23, <2 x i64> %a24, <2 x i64> %a25, <2 x i64> %a26, <2 x i64> %a27, <2 x i64> %a28, <2 x i64> %a29, <2 x i64> %a30, <2 x i64> %a31)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
|
||||
declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
|
|
@ -0,0 +1,449 @@
|
|||
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
||||
|
||||
; Stackmap Header: no constants - 6 callsites
|
||||
; CHECK: .section .llvm_stackmaps
|
||||
; CHECK-NEXT: __LLVM_StackMaps:
|
||||
; Header
|
||||
; CHECK-NEXT: .byte 3
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 0
|
||||
; Num Functions
|
||||
; CHECK-NEXT: .long 8
|
||||
; Num Constants
|
||||
; CHECK-NEXT: .long 0
|
||||
; Num Callsites
|
||||
; CHECK-NEXT: .long 8
|
||||
|
||||
; Functions and stack size
|
||||
; CHECK-NEXT: .quad test
|
||||
; CHECK-NEXT: .quad 160
|
||||
; CHECK-NEXT: .quad 1
|
||||
; CHECK-NEXT: .quad property_access1
|
||||
; CHECK-NEXT: .quad 160
|
||||
; CHECK-NEXT: .quad 1
|
||||
; CHECK-NEXT: .quad property_access2
|
||||
; CHECK-NEXT: .quad 168
|
||||
; CHECK-NEXT: .quad 1
|
||||
; CHECK-NEXT: .quad property_access3
|
||||
; CHECK-NEXT: .quad 168
|
||||
; CHECK-NEXT: .quad 1
|
||||
; CHECK-NEXT: .quad anyreg_test1
|
||||
; CHECK-NEXT: .quad 160
|
||||
; CHECK-NEXT: .quad 1
|
||||
; CHECK-NEXT: .quad anyreg_test2
|
||||
; CHECK-NEXT: .quad 160
|
||||
; CHECK-NEXT: .quad 1
|
||||
; CHECK-NEXT: .quad patchpoint_spilldef
|
||||
; CHECK-NEXT: .quad 168
|
||||
; CHECK-NEXT: .quad 1
|
||||
; CHECK-NEXT: .quad patchpoint_spillargs
|
||||
; CHECK-NEXT: .quad 192
|
||||
; CHECK-NEXT: .quad 1
|
||||
|
||||
; No constants
|
||||
|
||||
; Callsites
|
||||
; test
|
||||
; CHECK: .long .L{{.*}}-test
|
||||
; CHECK-NEXT: .short 0
|
||||
; 3 locations
|
||||
; CHECK-NEXT: .short 3
|
||||
; Loc 0: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 4
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 1: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 4
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 2: Constant 3
|
||||
; CHECK-NEXT: .byte 4
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 3
|
||||
define i64 @test() nounwind ssp uwtable {
|
||||
entry:
|
||||
call anyregcc void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 0, i32 14, i8* null, i32 2, i32 1, i32 2, i64 3)
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
; property access 1 - %obj is an anyreg call argument and should therefore be in a register
|
||||
; CHECK: .long .L{{.*}}-property_access1
|
||||
; CHECK-NEXT: .short 0
|
||||
; 2 locations
|
||||
; CHECK-NEXT: .short 2
|
||||
; Loc 0: Register <-- this is the return register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 1: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
define i64 @property_access1(i8* %obj) nounwind ssp uwtable {
|
||||
entry:
|
||||
%f = inttoptr i64 12297829382473034410 to i8*
|
||||
%ret = call anyregcc i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 1, i32 14, i8* %f, i32 1, i8* %obj)
|
||||
ret i64 %ret
|
||||
}
|
||||
|
||||
; property access 2 - %obj is an anyreg call argument and should therefore be in a register
|
||||
; CHECK: .long .L{{.*}}-property_access2
|
||||
; CHECK-NEXT: .short 0
|
||||
; 2 locations
|
||||
; CHECK-NEXT: .short 2
|
||||
; Loc 0: Register <-- this is the return register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 1: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
define i64 @property_access2() nounwind ssp uwtable {
|
||||
entry:
|
||||
%obj = alloca i64, align 8
|
||||
%f = inttoptr i64 12297829382473034410 to i8*
|
||||
%ret = call anyregcc i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 2, i32 14, i8* %f, i32 1, i64* %obj)
|
||||
ret i64 %ret
|
||||
}
|
||||
|
||||
; property access 3 - %obj is a frame index
|
||||
; CHECK: .long .L{{.*}}-property_access3
|
||||
; CHECK-NEXT: .short 0
|
||||
; 2 locations
|
||||
; CHECK-NEXT: .short 2
|
||||
; Loc 0: Register <-- this is the return register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 1: Direct %r15 + 160
|
||||
; CHECK-NEXT: .byte 2
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short 15
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 160
|
||||
define i64 @property_access3() nounwind ssp uwtable {
|
||||
entry:
|
||||
%obj = alloca i64, align 8
|
||||
%f = inttoptr i64 12297829382473034410 to i8*
|
||||
%ret = call anyregcc i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 3, i32 14, i8* %f, i32 0, i64* %obj)
|
||||
ret i64 %ret
|
||||
}
|
||||
|
||||
; anyreg_test1
|
||||
; CHECK: .long .L{{.*}}-anyreg_test1
|
||||
; CHECK-NEXT: .short 0
|
||||
; 13 locations
|
||||
; CHECK-NEXT: .short 13
|
||||
; Loc 0: Register <-- this is the return register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 1: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 2: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 3: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 4: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 5: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 6: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 7: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 8: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 9: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 10: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 11: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 12: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
define i64 @anyreg_test1(i8* %a1, i8* %a2, i8* %a3, i8* %a4, i8* %a5, i8* %a6, i8* %a7, i8* %a8, i8* %a9, i8* %a10, i8* %a11, i8* %a12) nounwind ssp uwtable {
|
||||
entry:
|
||||
%f = inttoptr i64 12297829382473034410 to i8*
|
||||
%ret = call anyregcc i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 4, i32 14, i8* %f, i32 12, i8* %a1, i8* %a2, i8* %a3, i8* %a4, i8* %a5, i8* %a6, i8* %a7, i8* %a8, i8* %a9, i8* %a10, i8* %a11, i8* %a12)
|
||||
ret i64 %ret
|
||||
}
|
||||
|
||||
; anyreg_test2
|
||||
; CHECK: .long .L{{.*}}-anyreg_test2
|
||||
; CHECK-NEXT: .short 0
|
||||
; 13 locations
|
||||
; CHECK-NEXT: .short 13
|
||||
; Loc 0: Register <-- this is the return register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 1: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 2: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 3: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 4: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 5: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 6: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 7: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 8: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 9: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 10: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 11: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 12: Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
define i64 @anyreg_test2(i8* %a1, i8* %a2, i8* %a3, i8* %a4, i8* %a5, i8* %a6, i8* %a7, i8* %a8, i8* %a9, i8* %a10, i8* %a11, i8* %a12) nounwind ssp uwtable {
|
||||
entry:
|
||||
%f = inttoptr i64 12297829382473034410 to i8*
|
||||
%ret = call anyregcc i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 5, i32 14, i8* %f, i32 8, i8* %a1, i8* %a2, i8* %a3, i8* %a4, i8* %a5, i8* %a6, i8* %a7, i8* %a8, i8* %a9, i8* %a10, i8* %a11, i8* %a12)
|
||||
ret i64 %ret
|
||||
}
|
||||
|
||||
; Test spilling the return value of an anyregcc call.
|
||||
;
|
||||
; <rdar://problem/15432754> [JS] Assertion: "Folded a def to a non-store!"
|
||||
;
|
||||
; CHECK: .long .L{{.*}}-patchpoint_spilldef
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .short 3
|
||||
; Loc 0: Register (some register that will be spilled to the stack)
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 1: Register %r2
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short 2
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 1: Register %r3
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short 3
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
define i64 @patchpoint_spilldef(i64 %p1, i64 %p2, i64 %p3, i64 %p4) {
|
||||
entry:
|
||||
%result = tail call anyregcc i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 12, i32 14, i8* inttoptr (i64 0 to i8*), i32 2, i64 %p1, i64 %p2)
|
||||
tail call void asm sideeffect "nopr %r0", "~{r0},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14}"() nounwind
|
||||
ret i64 %result
|
||||
}
|
||||
|
||||
; Test spilling the arguments of an anyregcc call.
|
||||
;
|
||||
; <rdar://problem/15487687> [JS] AnyRegCC argument ends up being spilled
|
||||
;
|
||||
; CHECK: .long .L{{.*}}-patchpoint_spillargs
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .short 5
|
||||
; Loc 0: Return a register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 1: Arg0 in a Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 2: Arg1 in a Register
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short {{[0-9]+}}
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; Loc 3: Arg2 spilled to %r15 +
|
||||
; CHECK-NEXT: .byte 3
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short 15
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long
|
||||
; Loc 4: Arg3 spilled to %r15 +
|
||||
; CHECK-NEXT: .byte 3
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 8
|
||||
; CHECK-NEXT: .short 15
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long
|
||||
define i64 @patchpoint_spillargs(i64 %p1, i64 %p2, i64 %p3, i64 %p4) {
|
||||
entry:
|
||||
tail call void asm sideeffect "nopr %r0", "~{r0},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14}"() nounwind
|
||||
%result = tail call anyregcc i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 13, i32 14, i8* inttoptr (i64 0 to i8*), i32 2, i64 %p1, i64 %p2, i64 %p3, i64 %p4)
|
||||
ret i64 %result
|
||||
}
|
||||
|
||||
declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
|
||||
declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
|
Loading…
Reference in New Issue