diff options
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZCallingConv.td | 9 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp | 39 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp | 8 | ||||
-rw-r--r-- | llvm/test/CodeGen/SystemZ/anyregcc-novec.ll | 65 | ||||
-rw-r--r-- | llvm/test/CodeGen/SystemZ/anyregcc-vec.ll | 99 | ||||
-rw-r--r-- | llvm/test/CodeGen/SystemZ/anyregcc.ll | 449 |
6 files changed, 657 insertions, 12 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZCallingConv.td b/llvm/lib/Target/SystemZ/SystemZCallingConv.td index 2bf5ac29865..deba27fee7f 100644 --- a/llvm/lib/Target/SystemZ/SystemZCallingConv.td +++ b/llvm/lib/Target/SystemZ/SystemZCallingConv.td @@ -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))>; + diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp index b2d59b1706d..565299c9013 100644 --- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp @@ -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,19 +444,26 @@ 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); - unsigned IgnoredFrameReg; - int64_t Offset = - getFrameIndexReference(MF, Save.getFrameIdx(), IgnoredFrameReg); + // Add CFI for the this save. + unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); + unsigned IgnoredFrameReg; + int64_t Offset = + getFrameIndexReference(MF, Save.getFrameIdx(), IgnoredFrameReg); - unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( + unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( nullptr, DwarfReg, SPOffsetFromCFA + Offset)); - CFIIndexes.push_back(CFIIndex); - } + 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)) diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp index 856505e00a1..91c7d1f6e85 100644 --- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -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)) diff --git a/llvm/test/CodeGen/SystemZ/anyregcc-novec.ll b/llvm/test/CodeGen/SystemZ/anyregcc-novec.ll new file mode 100644 index 00000000000..72bf00c2265 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/anyregcc-novec.ll @@ -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, ...) diff --git a/llvm/test/CodeGen/SystemZ/anyregcc-vec.ll b/llvm/test/CodeGen/SystemZ/anyregcc-vec.ll new file mode 100644 index 00000000000..02f1c4d483c --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/anyregcc-vec.ll @@ -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, ...) diff --git a/llvm/test/CodeGen/SystemZ/anyregcc.ll b/llvm/test/CodeGen/SystemZ/anyregcc.ll new file mode 100644 index 00000000000..2480f8c36b3 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/anyregcc.ll @@ -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, ...) |