llvm.org GIT mirror llvm / ade705c
Revert "r225811 - Revert "r225808 - [PowerPC] Add StackMap/PatchPoint support"" This re-applies r225808, fixed to avoid problems with SDAG dependencies along with the preceding fix to ScheduleDAGSDNodes::RegDefIter::InitNodeNumDefs. These problems caused the original regression tests to assert/segfault on many (but not all) systems. Original commit message: This commit does two things: 1. Refactors PPCFastISel to use more of the common infrastructure for call lowering (this lets us take advantage of this common code for lowering some common intrinsics, stackmap/patchpoint among them). 2. Adds support for stackmap/patchpoint lowering. For the most part, this is very similar to the support in the AArch64 target, with the obvious differences (different registers, NOP instructions, etc.). The test cases are adapted from the AArch64 test cases. One difference of note is that the patchpoint call sequence takes 24 bytes, so you can't use less than that (on AArch64 you can go down to 16). Also, as noted in the docs, we take the patchpoint address to be the actual code address (assuming the call is local in the TOC-sharing sense), which should yield higher performance than generating the full cross-DSO indirect-call sequence and is likely just as useful for JITed code (if not, we'll change it). StackMaps and Patchpoints are still marked as experimental, and so this support is doubly experimental. So go ahead and experiment! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225909 91177308-0d34-0410-b5e6-96231b3b80d8 Hal Finkel 4 years ago
17 changed file(s) with 1127 addition(s) and 100 deletion(s). Raw diff Collapse all Expand all
219219 lowered according to the calling convention specified at the
220220 intrinsic's callsite. Variants of the intrinsic with non-void return
221221 type also return a value according to calling convention.
222
223 On PowerPC, note that the ```` must be the actual intended target of
224 the indirect call, not the function-descriptor address normally used as the
225 C/C++ function-pointer representation. As a result, the call target must be
226 local because no adjustment or restoration of the TOC pointer (in register r2)
227 will be performed.
222228
223229 Requesting zero patch point arguments is valid. In this case, all
224230 variable operands are handled just like
3333 #include "llvm/CodeGen/MachineInstrBuilder.h"
3434 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
3535 #include "llvm/CodeGen/MachineRegisterInfo.h"
36 #include "llvm/CodeGen/StackMaps.h"
3637 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
3738 #include "llvm/IR/Constants.h"
3839 #include "llvm/IR/DebugInfo.h"
6869 MapVector TOC;
6970 const PPCSubtarget &Subtarget;
7071 uint64_t TOCLabelID;
72 StackMaps SM;
7173 public:
7274 explicit PPCAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
7375 : AsmPrinter(TM, Streamer),
74 Subtarget(TM.getSubtarget()), TOCLabelID(0) {}
76 Subtarget(TM.getSubtarget()), TOCLabelID(0), SM(*this) {}
7577
7678 const char *getPassName() const override {
7779 return "PowerPC Assembly Printer";
8991 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
9092 unsigned AsmVariant, const char *ExtraCode,
9193 raw_ostream &O) override;
94
95 void EmitEndOfAsmFile(Module &M) override;
96
97 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
98 const MachineInstr &MI);
99 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
100 const MachineInstr &MI);
92101 };
93102
94103 /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux
315324 return TOCEntry;
316325 }
317326
327 void PPCAsmPrinter::EmitEndOfAsmFile(Module &M) {
328 SM.serializeToStackMapSection();
329 }
330
331 void PPCAsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
332 const MachineInstr &MI) {
333 unsigned NumNOPBytes = MI.getOperand(1).getImm();
334
335 SM.recordStackMap(MI);
336 assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
337
338 // Scan ahead to trim the shadow.
339 const MachineBasicBlock &MBB = *MI.getParent();
340 MachineBasicBlock::const_iterator MII(MI);
341 ++MII;
342 while (NumNOPBytes > 0) {
343 if (MII == MBB.end() || MII->isCall() ||
344 MII->getOpcode() == PPC::DBG_VALUE ||
345 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
346 MII->getOpcode() == TargetOpcode::STACKMAP)
347 break;
348 ++MII;
349 NumNOPBytes -= 4;
350 }
351
352 // Emit nops.
353 for (unsigned i = 0; i < NumNOPBytes; i += 4)
354 EmitToStreamer(OutStreamer, MCInstBuilder(PPC::NOP));
355 }
356
357 // Lower a patchpoint of the form:
358 // [], , , ,
359 void PPCAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
360 const MachineInstr &MI) {
361 SM.recordPatchPoint(MI);
362 PatchPointOpers Opers(&MI);
363
364 int64_t CallTarget = Opers.getMetaOper(PatchPointOpers::TargetPos).getImm();
365 unsigned EncodedBytes = 0;
366 if (CallTarget) {
367 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
368 "High 16 bits of call target should be zero.");
369 unsigned ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
370 EncodedBytes = 6*4;
371 // Materialize the jump address:
372 EmitToStreamer(OutStreamer, MCInstBuilder(PPC::LI8)
373 .addReg(ScratchReg)
374 .addImm((CallTarget >> 32) & 0xFFFF));
375 EmitToStreamer(OutStreamer, MCInstBuilder(PPC::RLDIC)
376 .addReg(ScratchReg)
377 .addReg(ScratchReg)
378 .addImm(32).addImm(16));
379 EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ORIS8)
380 .addReg(ScratchReg)
381 .addReg(ScratchReg)
382 .addImm((CallTarget >> 16) & 0xFFFF));
383 EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ORI8)
384 .addReg(ScratchReg)
385 .addReg(ScratchReg)
386 .addImm(CallTarget & 0xFFFF));
387
388 EmitToStreamer(OutStreamer, MCInstBuilder(PPC::MTCTR8).addReg(ScratchReg));
389 EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BCTRL8));
390 }
391
392 // Emit padding.
393 unsigned NumBytes = Opers.getMetaOper(PatchPointOpers::NBytesPos).getImm();
394 assert(NumBytes >= EncodedBytes &&
395 "Patchpoint can't request size less than the length of a call.");
396 assert((NumBytes - EncodedBytes) % 4 == 0 &&
397 "Invalid number of NOP bytes requested!");
398 for (unsigned i = EncodedBytes; i < NumBytes; i += 4)
399 EmitToStreamer(OutStreamer, MCInstBuilder(PPC::NOP));
400 }
318401
319402 /// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to
320403 /// the current output stream.
331414 default: break;
332415 case TargetOpcode::DBG_VALUE:
333416 llvm_unreachable("Should be handled target independently");
417 case TargetOpcode::STACKMAP:
418 return LowerSTACKMAP(OutStreamer, SM, *MI);
419 case TargetOpcode::PATCHPOINT:
420 return LowerPATCHPOINT(OutStreamer, SM, *MI);
421
334422 case PPC::MoveGOTtoLR: {
335423 // Transform %LR = MoveGOTtoLR
336424 // Into this: bl _GLOBAL_OFFSET_TABLE_@local-4
0 //=== PPCCallingConv.h - PPC Custom Calling Convention Routines -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the custom routines for the PPC Calling Convention that
10 // aren't done by tablegen.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_LIB_TARGET_PPC_PPCCALLINGCONV_H
15 #define LLVM_LIB_TARGET_PPC_PPCCALLINGCONV_H
16
17 #include "llvm/CodeGen/CallingConvLower.h"
18 #include "llvm/IR/CallingConv.h"
19
20 namespace llvm {
21
22 inline bool CC_PPC_AnyReg_Error(unsigned &, MVT &, MVT &,
23 CCValAssign::LocInfo &, ISD::ArgFlagsTy &,
24 CCState &) {
25 llvm_unreachable("The AnyReg calling convention is only supported by the " \
26 "stackmap and patchpoint intrinsics.");
27 // gracefully fallback to PPC C calling convention on Release builds.
28 return false;
29 }
30
31 } // End llvm namespace
32
33 #endif
34
2727 // Return Value Calling Convention
2828 //===----------------------------------------------------------------------===//
2929
30 // PPC64 AnyReg return-value convention. No explicit register is specified for
31 // the return-value. The register allocator is allowed and expected to choose
32 // any free register.
33 //
34 // This calling convention is currently only supported by the stackmap and
35 // patchpoint intrinsics. All other uses will result in an assert on Debug
36 // builds. On Release builds we fallback to the PPC C calling convention.
37 def RetCC_PPC64_AnyReg : CallingConv<[
38 CCCustom<"CC_PPC_AnyReg_Error">
39 ]>;
40
3041 // Return-value convention for PowerPC
3142 def RetCC_PPC : CallingConv<[
43 CCIfCC<"CallingConv::AnyReg", CCDelegateTo>,
44
3245 // On PPC64, integer return values are always promoted to i64
3346 CCIfType<[i32, i1], CCIfSubtarget<"isPPC64()", CCPromoteToType>>,
3447 CCIfType<[i1], CCIfNotSubtarget<"isPPC64()", CCPromoteToType>>,
5063 CCAssignToReg<[VSH2, VSH3, VSH4, VSH5, VSH6, VSH7, VSH8, VSH9]>>
5164 ]>;
5265
66 // No explicit register is specified for the AnyReg calling convention. The
67 // register allocator may assign the arguments to any free register.
68 //
69 // This calling convention is currently only supported by the stackmap and
70 // patchpoint intrinsics. All other uses will result in an assert on Debug
71 // builds. On Release builds we fallback to the PPC C calling convention.
72 def CC_PPC64_AnyReg : CallingConv<[
73 CCCustom<"CC_PPC_AnyReg_Error">
74 ]>;
5375
5476 // Note that we don't currently have calling conventions for 64-bit
5577 // PowerPC, but handle all the complexities of the ABI in the lowering
6082 // Only handle ints and floats. All ints are promoted to i64.
6183 // Vector types and quadword ints are not handled.
6284 def CC_PPC64_ELF_FIS : CallingConv<[
85 CCIfCC<"CallingConv::AnyReg", CCDelegateTo>,
86
6387 CCIfType<[i1], CCPromoteToType>,
6488 CCIfType<[i8], CCPromoteToType>,
6589 CCIfType<[i16], CCPromoteToType>,
7397 // and multiple register returns are "supported" to avoid compile
7498 // errors, but none are handled by the fast selector.
7599 def RetCC_PPC64_ELF_FIS : CallingConv<[
100 CCIfCC<"CallingConv::AnyReg", CCDelegateTo>,
101
76102 CCIfType<[i1], CCPromoteToType>,
77103 CCIfType<[i8], CCPromoteToType>,
78104 CCIfType<[i16], CCPromoteToType>,
202228
203229 def CSR_NoRegs : CalleeSavedRegs<(add)>;
204230
231 def CSR_64_AllRegs: CalleeSavedRegs<(add X0, (sequence "X%u", 3, 10),
232 (sequence "X%u", 14, 31),
233 (sequence "F%u", 0, 31),
234 (sequence "CR%u", 0, 7))>;
235
236 def CSR_64_AllRegs_Altivec : CalleeSavedRegs<(add CSR_64_AllRegs,
237 (sequence "V%u", 0, 31))>;
238
239 def CSR_64_AllRegs_VSX : CalleeSavedRegs<(add CSR_64_AllRegs_Altivec,
240 (sequence "VSL%u", 0, 31),
241 (sequence "VSH%u", 0, 31))>;
242
1414
1515 #include "PPC.h"
1616 #include "MCTargetDesc/PPCPredicates.h"
17 #include "PPCCallingConv.h"
1718 #include "PPCISelLowering.h"
1819 #include "PPCSubtarget.h"
1920 #include "PPCTargetMachine.h"
118119 unsigned Op0, bool Op0IsKill,
119120 unsigned Op1, bool Op1IsKill);
120121
122 bool fastLowerCall(CallLoweringInfo &CLI) override;
123
121124 // Instruction selection routines.
122125 private:
123126 bool SelectLoad(const Instruction *I);
129132 bool SelectIToFP(const Instruction *I, bool IsSigned);
130133 bool SelectFPToI(const Instruction *I, bool IsSigned);
131134 bool SelectBinaryIntOp(const Instruction *I, unsigned ISDOpcode);
132 bool SelectCall(const Instruction *I);
133135 bool SelectRet(const Instruction *I);
134136 bool SelectTrunc(const Instruction *I);
135137 bool SelectIntExt(const Instruction *I);
173175 CallingConv::ID CC,
174176 unsigned &NumBytes,
175177 bool IsVarArg);
176 void finishCall(MVT RetVT, SmallVectorImpl &UsedRegs,
177 const Instruction *I, CallingConv::ID CC,
178 unsigned &NumBytes, bool IsVarArg);
178 bool finishCall(MVT RetVT, CallLoweringInfo &CLI, unsigned &NumBytes);
179179 CCAssignFn *usePPC32CCs(unsigned Flag);
180180
181181 private:
13381338
13391339 // For a call that we've determined we can fast-select, finish the
13401340 // call sequence and generate a copy to obtain the return value (if any).
1341 void PPCFastISel::finishCall(MVT RetVT, SmallVectorImpl &UsedRegs,
1342 const Instruction *I, CallingConv::ID CC,
1343 unsigned &NumBytes, bool IsVarArg) {
1341 bool PPCFastISel::finishCall(MVT RetVT, CallLoweringInfo &CLI, unsigned &NumBytes) {
1342 CallingConv::ID CC = CLI.CallConv;
1343
13441344 // Issue CallSEQ_END.
13451345 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
13461346 TII.get(TII.getCallFrameDestroyOpcode()))
13511351 // any real difficulties there.
13521352 if (RetVT != MVT::isVoid) {
13531353 SmallVector RVLocs;
1354 CCState CCInfo(CC, IsVarArg, *FuncInfo.MF, RVLocs, *Context);
1354 CCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context);
13551355 CCInfo.AnalyzeCallResult(RetVT, RetCC_PPC64_ELF_FIS);
13561356 CCValAssign &VA = RVLocs[0];
13571357 assert(RVLocs.size() == 1 && "No support for multi-reg return values!");
13961396 }
13971397
13981398 assert(ResultReg && "ResultReg unset!");
1399 UsedRegs.push_back(SourcePhysReg);
1400 updateValueMap(I, ResultReg);
1401 }
1402 }
1403
1404 // Attempt to fast-select a call instruction.
1405 bool PPCFastISel::SelectCall(const Instruction *I) {
1406 const CallInst *CI = cast(I);
1407 const Value *Callee = CI->getCalledValue();
1408
1409 // Can't handle inline asm.
1410 if (isa(Callee))
1399 CLI.InRegs.push_back(SourcePhysReg);
1400 CLI.ResultReg = ResultReg;
1401 CLI.NumResultRegs = 1;
1402 }
1403
1404 return true;
1405 }
1406
1407 bool PPCFastISel::fastLowerCall(CallLoweringInfo &CLI) {
1408 CallingConv::ID CC = CLI.CallConv;
1409 bool IsTailCall = CLI.IsTailCall;
1410 bool IsVarArg = CLI.IsVarArg;
1411 const Value *Callee = CLI.Callee;
1412 const char *SymName = CLI.SymName;
1413
1414 if (!Callee && !SymName)
14111415 return false;
14121416
14131417 // Allow SelectionDAG isel to handle tail calls.
1414 if (CI->isTailCall())
1415 return false;
1416
1417 // Obtain calling convention.
1418 ImmutableCallSite CS(CI);
1419 CallingConv::ID CC = CS.getCallingConv();
1420
1421 PointerType *PT = cast(CS.getCalledValue()->getType());
1422 FunctionType *FTy = cast(PT->getElementType());
1423 bool IsVarArg = FTy->isVarArg();
1424
1425 // Not ready for varargs yet.
1418 if (IsTailCall)
1419 return false;
1420
1421 // Let SDISel handle vararg functions.
14261422 if (IsVarArg)
14271423 return false;
14281424
14291425 // Handle simple calls for now, with legal return types and
14301426 // those that can be extended.
1431 Type *RetTy = I->getType();
1427 Type *RetTy = CLI.RetTy;
14321428 MVT RetVT;
14331429 if (RetTy->isVoidTy())
14341430 RetVT = MVT::isVoid;
14491445
14501446 // Bail early if more than 8 arguments, as we only currently
14511447 // handle arguments passed in registers.
1452 unsigned NumArgs = CS.arg_size();
1448 unsigned NumArgs = CLI.OutVals.size();
14531449 if (NumArgs > 8)
14541450 return false;
14551451
14641460 ArgVTs.reserve(NumArgs);
14651461 ArgFlags.reserve(NumArgs);
14661462
1467 for (ImmutableCallSite::arg_iterator II = CS.arg_begin(), IE = CS.arg_end();
1468 II != IE; ++II) {
1469 // FIXME: ARM does something for intrinsic calls here, check into that.
1470
1471 unsigned AttrIdx = II - CS.arg_begin() + 1;
1472
1463 for (unsigned i = 0, ie = NumArgs; i != ie; ++i) {
14731464 // Only handle easy calls for now. It would be reasonably easy
14741465 // to handle <= 8-byte structures passed ByVal in registers, but we
14751466 // have to ensure they are right-justified in the register.
1476 if (CS.paramHasAttr(AttrIdx, Attribute::InReg) ||
1477 CS.paramHasAttr(AttrIdx, Attribute::StructRet) ||
1478 CS.paramHasAttr(AttrIdx, Attribute::Nest) ||
1479 CS.paramHasAttr(AttrIdx, Attribute::ByVal))
1467 ISD::ArgFlagsTy Flags = CLI.OutFlags[i];
1468 if (Flags.isInReg() || Flags.isSRet() || Flags.isNest() || Flags.isByVal())
14801469 return false;
14811470
1482 ISD::ArgFlagsTy Flags;
1483 if (CS.paramHasAttr(AttrIdx, Attribute::SExt))
1484 Flags.setSExt();
1485 if (CS.paramHasAttr(AttrIdx, Attribute::ZExt))
1486 Flags.setZExt();
1487
1488 Type *ArgTy = (*II)->getType();
1471 Value *ArgValue = CLI.OutVals[i];
1472 Type *ArgTy = ArgValue->getType();
14891473 MVT ArgVT;
14901474 if (!isTypeLegal(ArgTy, ArgVT) && ArgVT != MVT::i16 && ArgVT != MVT::i8)
14911475 return false;
14931477 if (ArgVT.isVector())
14941478 return false;
14951479
1496 unsigned Arg = getRegForValue(*II);
1480 unsigned Arg = getRegForValue(ArgValue);
14971481 if (Arg == 0)
14981482 return false;
14991483
1500 unsigned OriginalAlignment = DL.getABITypeAlignment(ArgTy);
1501 Flags.setOrigAlign(OriginalAlignment);
1502
1503 Args.push_back(*II);
1484 Args.push_back(ArgValue);
15041485 ArgRegs.push_back(Arg);
15051486 ArgVTs.push_back(ArgVT);
15061487 ArgFlags.push_back(Flags);
15141495 RegArgs, CC, NumBytes, IsVarArg))
15151496 return false;
15161497
1498 MachineInstrBuilder MIB;
15171499 // FIXME: No handling for function pointers yet. This requires
15181500 // implementing the function descriptor (OPD) setup.
15191501 const GlobalValue *GV = dyn_cast(Callee);
1520 if (!GV)
1521 return false;
1522
1523 // Build direct call with NOP for TOC restore.
1524 // FIXME: We can and should optimize away the NOP for local calls.
1525 MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1526 TII.get(PPC::BL8_NOP));
1527 // Add callee.
1528 MIB.addGlobalAddress(GV);
1502 if (!GV) {
1503 // patchpoints are a special case; they always dispatch to a pointer value.
1504 // However, we don't actually want to generate the indirect call sequence
1505 // here (that will be generated, as necessary, during asm printing), and
1506 // the call we generate here will be erased by FastISel::selectPatchpoint,
1507 // so don't try very hard...
1508 if (CLI.IsPatchPoint)
1509 MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(PPC::NOP));
1510 else
1511 return false;
1512 } else {
1513 // Build direct call with NOP for TOC restore.
1514 // FIXME: We can and should optimize away the NOP for local calls.
1515 MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1516 TII.get(PPC::BL8_NOP));
1517 // Add callee.
1518 MIB.addGlobalAddress(GV);
1519 }
15291520
15301521 // Add implicit physical register uses to the call.
15311522 for (unsigned II = 0, IE = RegArgs.size(); II != IE; ++II)
15391530 // defs for return values will be added by setPhysRegsDeadExcept().
15401531 MIB.addRegMask(TRI.getCallPreservedMask(CC));
15411532
1533 CLI.Call = MIB;
1534
15421535 // Finish off the call including any return values.
1543 SmallVector UsedRegs;
1544 finishCall(RetVT, UsedRegs, I, CC, NumBytes, IsVarArg);
1545
1546 // Set all unused physregs defs as dead.
1547 static_cast(MIB)->setPhysRegsDeadExcept(UsedRegs, TRI);
1548
1549 return true;
1536 return finishCall(RetVT, CLI, NumBytes);
15501537 }
15511538
15521539 // Attempt to fast-select a return instruction.
18361823 case Instruction::Sub:
18371824 return SelectBinaryIntOp(I, ISD::SUB);
18381825 case Instruction::Call:
1839 if (dyn_cast(I))
1840 return false;
1841 return SelectCall(I);
1826 return selectCall(I);
18421827 case Instruction::Ret:
18431828 return SelectRet(I);
18441829 case Instruction::Trunc:
449449
450450 return MF.getTarget().Options.DisableFramePointerElim(MF) ||
451451 MFI->hasVarSizedObjects() ||
452 MFI->hasStackMap() || MFI->hasPatchPoint() ||
452453 (MF.getTarget().Options.GuaranteedTailCallOpt &&
453454 MF.getInfo()->hasFastCall());
454455 }
1212
1313 #include "PPCISelLowering.h"
1414 #include "MCTargetDesc/PPCPredicates.h"
15 #include "PPCCallingConv.h"
1516 #include "PPCMachineFunctionInfo.h"
1617 #include "PPCPerfectShuffle.h"
1718 #include "PPCTargetMachine.h"
35893590 static
35903591 unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag,
35913592 SDValue &Chain, SDLoc dl, int SPDiff, bool isTailCall,
3593 bool IsPatchPoint,
35923594 SmallVectorImpl > &RegsToPass,
35933595 SmallVectorImpl &Ops, std::vector &NodeTys,
35943596 const PPCSubtarget &Subtarget) {
36543656
36553657 Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType(),
36563658 OpFlags);
3659 needIndirectCall = false;
3660 }
3661
3662 if (IsPatchPoint) {
3663 // We'll form an invalid direct call when lowering a patchpoint; the full
3664 // sequence for an indirect call is complicated, and many of the
3665 // instructions introduced might have side effects (and, thus, can't be
3666 // removed later). The call itself will be removed as soon as the
3667 // argument/return lowering is complete, so the fact that it has the wrong
3668 // kind of operands should not really matter.
36573669 needIndirectCall = false;
36583670 }
36593671
37823794 RegsToPass[i].second.getValueType()));
37833795
37843796 // Direct calls in the ELFv2 ABI need the TOC register live into the call.
3785 if (Callee.getNode() && isELFv2ABI)
3797 if (Callee.getNode() && isELFv2ABI && !IsPatchPoint)
37863798 Ops.push_back(DAG.getRegister(PPC::X2, PtrVT));
37873799
37883800 return CallOpc;
38453857
38463858 SDValue
38473859 PPCTargetLowering::FinishCall(CallingConv::ID CallConv, SDLoc dl,
3848 bool isTailCall, bool isVarArg,
3860 bool isTailCall, bool isVarArg, bool IsPatchPoint,
38493861 SelectionDAG &DAG,
38503862 SmallVector, 8>
38513863 &RegsToPass,
38593871 std::vector NodeTys;
38603872 SmallVector Ops;
38613873 unsigned CallOpc = PrepareCall(DAG, Callee, InFlag, Chain, dl, SPDiff,
3862 isTailCall, RegsToPass, Ops, NodeTys,
3863 Subtarget);
3874 isTailCall, IsPatchPoint, RegsToPass, Ops,
3875 NodeTys, Subtarget);
38643876
38653877 // Add implicit use of CR bit 6 for 32-bit SVR4 vararg calls
38663878 if (isVarArg && Subtarget.isSVR4ABI() && !Subtarget.isPPC64())
39043916 // stack frame. If caller and callee belong to the same module (and have the
39053917 // same TOC), the NOP will remain unchanged.
39063918
3907 if (!isTailCall && Subtarget.isSVR4ABI()&& Subtarget.isPPC64()) {
3919 if (!isTailCall && Subtarget.isSVR4ABI()&& Subtarget.isPPC64() &&
3920 !IsPatchPoint) {
39083921 if (CallOpc == PPCISD::BCTRL) {
39093922 // This is a call through a function pointer.
39103923 // Restore the caller TOC from the save area into R2.
39623975 bool &isTailCall = CLI.IsTailCall;
39633976 CallingConv::ID CallConv = CLI.CallConv;
39643977 bool isVarArg = CLI.IsVarArg;
3978 bool IsPatchPoint = CLI.IsPatchPoint;
39653979
39663980 if (isTailCall)
39673981 isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv, isVarArg,
39743988 if (Subtarget.isSVR4ABI()) {
39753989 if (Subtarget.isPPC64())
39763990 return LowerCall_64SVR4(Chain, Callee, CallConv, isVarArg,
3977 isTailCall, Outs, OutVals, Ins,
3991 isTailCall, IsPatchPoint, Outs, OutVals, Ins,
39783992 dl, DAG, InVals);
39793993 else
39803994 return LowerCall_32SVR4(Chain, Callee, CallConv, isVarArg,
3981 isTailCall, Outs, OutVals, Ins,
3995 isTailCall, IsPatchPoint, Outs, OutVals, Ins,
39823996 dl, DAG, InVals);
39833997 }
39843998
39853999 return LowerCall_Darwin(Chain, Callee, CallConv, isVarArg,
3986 isTailCall, Outs, OutVals, Ins,
4000 isTailCall, IsPatchPoint, Outs, OutVals, Ins,
39874001 dl, DAG, InVals);
39884002 }
39894003
39904004 SDValue
39914005 PPCTargetLowering::LowerCall_32SVR4(SDValue Chain, SDValue Callee,
39924006 CallingConv::ID CallConv, bool isVarArg,
3993 bool isTailCall,
4007 bool isTailCall, bool IsPatchPoint,
39944008 const SmallVectorImpl &Outs,
39954009 const SmallVectorImpl &OutVals,
39964010 const SmallVectorImpl &Ins,
42004214 PrepareTailCall(DAG, InFlag, Chain, dl, false, SPDiff, NumBytes, LROp, FPOp,
42014215 false, TailCallArguments);
42024216
4203 return FinishCall(CallConv, dl, isTailCall, isVarArg, DAG,
4217 return FinishCall(CallConv, dl, isTailCall, isVarArg, IsPatchPoint, DAG,
42044218 RegsToPass, InFlag, Chain, Callee, SPDiff, NumBytes,
42054219 Ins, InVals);
42064220 }
42284242 SDValue
42294243 PPCTargetLowering::LowerCall_64SVR4(SDValue Chain, SDValue Callee,
42304244 CallingConv::ID CallConv, bool isVarArg,
4231 bool isTailCall,
4245 bool isTailCall, bool IsPatchPoint,
42324246 const SmallVectorImpl &Outs,
42334247 const SmallVectorImpl &OutVals,
42344248 const SmallVectorImpl &Ins,
46644678 // Check if this is an indirect call (MTCTR/BCTRL).
46654679 // See PrepareCall() for more information about calls through function
46664680 // pointers in the 64-bit SVR4 ABI.
4667 if (!isTailCall &&
4681 if (!isTailCall && !IsPatchPoint &&
46684682 !isFunctionGlobalAddress(Callee) &&
46694683 !isa(Callee)) {
46704684 // Load r2 into a virtual register and store it to the TOC save area.
46784692 // In the ELFv2 ABI, R12 must contain the address of an indirect callee.
46794693 // This does not mean the MTCTR instruction must use R12; it's easier
46804694 // to model this as an extra parameter, so do that.
4681 if (isELFv2ABI)
4695 if (isELFv2ABI && !IsPatchPoint)
46824696 RegsToPass.push_back(std::make_pair((unsigned)PPC::X12, Callee));
46834697 }
46844698
46954709 PrepareTailCall(DAG, InFlag, Chain, dl, true, SPDiff, NumBytes, LROp,
46964710 FPOp, true, TailCallArguments);
46974711
4698 return FinishCall(CallConv, dl, isTailCall, isVarArg, DAG,
4712 return FinishCall(CallConv, dl, isTailCall, isVarArg, IsPatchPoint, DAG,
46994713 RegsToPass, InFlag, Chain, Callee, SPDiff, NumBytes,
47004714 Ins, InVals);
47014715 }
47034717 SDValue
47044718 PPCTargetLowering::LowerCall_Darwin(SDValue Chain, SDValue Callee,
47054719 CallingConv::ID CallConv, bool isVarArg,
4706 bool isTailCall,
4720 bool isTailCall, bool IsPatchPoint,
47074721 const SmallVectorImpl &Outs,
47084722 const SmallVectorImpl &OutVals,
47094723 const SmallVectorImpl &Ins,
50885102 PrepareTailCall(DAG, InFlag, Chain, dl, isPPC64, SPDiff, NumBytes, LROp,
50895103 FPOp, true, TailCallArguments);
50905104
5091 return FinishCall(CallConv, dl, isTailCall, isVarArg, DAG,
5105 return FinishCall(CallConv, dl, isTailCall, isVarArg, IsPatchPoint, DAG,
50925106 RegsToPass, InFlag, Chain, Callee, SPDiff, NumBytes,
50935107 Ins, InVals);
50945108 }
72457259 MachineBasicBlock *
72467260 PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
72477261 MachineBasicBlock *BB) const {
7262 if (MI->getOpcode() == TargetOpcode::STACKMAP ||
7263 MI->getOpcode() == TargetOpcode::PATCHPOINT)
7264 return emitPatchPoint(MI, BB);
7265
72487266 if (MI->getOpcode() == PPC::EH_SjLj_SetJmp32 ||
72497267 MI->getOpcode() == PPC::EH_SjLj_SetJmp64) {
72507268 return emitEHSjLjSetJmp(MI, BB);
98819899 return false;
98829900 }
98839901
9902 const MCPhysReg *
9903 PPCTargetLowering::getScratchRegisters(CallingConv::ID) const {
9904 // LR is a callee-save register, but we must treat it as clobbered by any call
9905 // site. Hence we include LR in the scratch registers, which are in turn added
9906 // as implicit-defs for stackmaps and patchpoints. The same reasoning applies
9907 // to CTR, which is used by any indirect call.
9908 static const MCPhysReg ScratchRegs[] = {
9909 PPC::X11, PPC::X12, PPC::LR8, PPC::CTR8, 0
9910 };
9911
9912 return ScratchRegs;
9913 }
9914
98849915 bool
98859916 PPCTargetLowering::shouldExpandBuildVectorWithShuffles(
98869917 EVT VT , unsigned DefinedValues) const {
568568 /// expanded to FMAs when this method returns true, otherwise fmuladd is
569569 /// expanded to fmul + fadd.
570570 bool isFMAFasterThanFMulAndFAdd(EVT VT) const override;
571
572 const MCPhysReg *getScratchRegisters(CallingConv::ID CC) const override;
571573
572574 // Should we expand the build vector with shuffles?
573575 bool
680682 SDLoc dl, SelectionDAG &DAG,
681683 SmallVectorImpl &InVals) const;
682684 SDValue FinishCall(CallingConv::ID CallConv, SDLoc dl, bool isTailCall,
683 bool isVarArg,
685 bool isVarArg, bool IsPatchPoint,
684686 SelectionDAG &DAG,
685687 SmallVector, 8>
686688 &RegsToPass,
745747 SDValue
746748 LowerCall_Darwin(SDValue Chain, SDValue Callee,
747749 CallingConv::ID CallConv,
748 bool isVarArg, bool isTailCall,
750 bool isVarArg, bool isTailCall, bool IsPatchPoint,
749751 const SmallVectorImpl &Outs,
750752 const SmallVectorImpl &OutVals,
751753 const SmallVectorImpl &Ins,
754756 SDValue
755757 LowerCall_64SVR4(SDValue Chain, SDValue Callee,
756758 CallingConv::ID CallConv,
757 bool isVarArg, bool isTailCall,
759 bool isVarArg, bool isTailCall, bool IsPatchPoint,
758760 const SmallVectorImpl &Outs,
759761 const SmallVectorImpl &OutVals,
760762 const SmallVectorImpl &Ins,
762764 SmallVectorImpl &InVals) const;
763765 SDValue
764766 LowerCall_32SVR4(SDValue Chain, SDValue Callee, CallingConv::ID CallConv,
765 bool isVarArg, bool isTailCall,
767 bool isVarArg, bool isTailCall, bool IsPatchPoint,
766768 const SmallVectorImpl &Outs,
767769 const SmallVectorImpl &OutVals,
768770 const SmallVectorImpl &Ins,
2828 #include "llvm/CodeGen/PseudoSourceValue.h"
2929 #include "llvm/CodeGen/ScheduleDAG.h"
3030 #include "llvm/CodeGen/SlotIndexes.h"
31 #include "llvm/CodeGen/StackMaps.h"
3132 #include "llvm/MC/MCAsmInfo.h"
3233 #include "llvm/Support/CommandLine.h"
3334 #include "llvm/Support/Debug.h"
15951596 const MachineFunction *MF = MI->getParent()->getParent();
15961597 const char *AsmStr = MI->getOperand(0).getSymbolName();
15971598 return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
1599 } else if (Opcode == TargetOpcode::STACKMAP) {
1600 return MI->getOperand(1).getImm();
1601 } else if (Opcode == TargetOpcode::PATCHPOINT) {
1602 PatchPointOpers Opers(MI);
1603 return Opers.getMetaOper(PatchPointOpers::NBytesPos).getImm();
15981604 } else {
15991605 const MCInstrDesc &Desc = get(Opcode);
16001606 return Desc.getSize();
9898
9999 const MCPhysReg*
100100 PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
101 if (MF->getFunction()->getCallingConv() == CallingConv::AnyReg) {
102 if (Subtarget.hasVSX())
103 return CSR_64_AllRegs_VSX_SaveList;
104 if (Subtarget.hasAltivec())
105 return CSR_64_AllRegs_Altivec_SaveList;
106 return CSR_64_AllRegs_SaveList;
107 }
108
101109 if (Subtarget.isDarwinABI())
102110 return Subtarget.isPPC64() ? (Subtarget.hasAltivec() ?
103111 CSR_Darwin64_Altivec_SaveList :
116124
117125 const uint32_t*
118126 PPCRegisterInfo::getCallPreservedMask(CallingConv::ID CC) const {
127 if (CC == CallingConv::AnyReg) {
128 if (Subtarget.hasVSX())
129 return CSR_64_AllRegs_VSX_RegMask;
130 if (Subtarget.hasAltivec())
131 return CSR_64_AllRegs_Altivec_RegMask;
132 return CSR_64_AllRegs_RegMask;
133 }
134
119135 if (Subtarget.isDarwinABI())
120136 return Subtarget.isPPC64() ? (Subtarget.hasAltivec() ?
121137 CSR_Darwin64_Altivec_RegMask :
135151 const uint32_t*
136152 PPCRegisterInfo::getNoPreservedMask() const {
137153 return CSR_NoRegs_RegMask;
154 }
155
156 void PPCRegisterInfo::adjustStackMapLiveOutMask(uint32_t *Mask) const {
157 unsigned PseudoRegs[] = { PPC::ZERO, PPC::ZERO8, PPC::RM };
158 for (unsigned i = 0, ie = array_lengthof(PseudoRegs); i != ie; ++i) {
159 unsigned Reg = PseudoRegs[i];
160 Mask[Reg / 32] &= ~(1u << (Reg % 32));
161 }
138162 }
139163
140164 BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
699723 // Take into account whether it's an add or mem instruction
700724 unsigned OffsetOperandNo = (FIOperandNum == 2) ? 1 : 2;
701725 if (MI.isInlineAsm())
702 OffsetOperandNo = FIOperandNum-1;
726 OffsetOperandNo = FIOperandNum - 1;
727 else if (MI.getOpcode() == TargetOpcode::STACKMAP ||
728 MI.getOpcode() == TargetOpcode::PATCHPOINT)
729 OffsetOperandNo = FIOperandNum + 1;
703730
704731 return OffsetOperandNo;
705732 }
771798
772799 // If the instruction is not present in ImmToIdxMap, then it has no immediate
773800 // form (and must be r+r).
774 bool noImmForm = !MI.isInlineAsm() && !ImmToIdxMap.count(OpC);
801 bool noImmForm = !MI.isInlineAsm() && OpC != TargetOpcode::STACKMAP &&
802 OpC != TargetOpcode::PATCHPOINT && !ImmToIdxMap.count(OpC);
775803
776804 // Now add the frame object offset to the offset from r1.
777805 int Offset = MFI->getObjectOffset(FrameIndex);
795823 // only "std" to a stack slot that is at least 4-byte aligned, but it can
796824 // happen in invalid code.
797825 assert(OpC != PPC::DBG_VALUE &&
798 "This should be handle in a target independent way");
799 if (!noImmForm && isInt<16>(Offset) && (!isIXAddr || (Offset & 3) == 0)) {
826 "This should be handled in a target-independent way");
827 if (!noImmForm && ((isInt<16>(Offset) && (!isIXAddr || (Offset & 3) == 0)) ||
828 OpC == TargetOpcode::STACKMAP ||
829 OpC == TargetOpcode::PATCHPOINT)) {
800830 MI.getOperand(OffsetOperandNo).ChangeToImmediate(Offset);
801831 return;
802832 }
10071037 Offset += MI->getOperand(OffsetOperandNo).getImm();
10081038
10091039 return MI->getOpcode() == PPC::DBG_VALUE || // DBG_VALUE is always Reg+Imm
1040 MI->getOpcode() == TargetOpcode::STACKMAP ||
1041 MI->getOpcode() == TargetOpcode::PATCHPOINT ||
10101042 (isInt<16>(Offset) && (!usesIXAddr(*MI) || (Offset & 3) == 0));
10111043 }
10121044
4747 getCalleeSavedRegs(const MachineFunction* MF =nullptr) const override;
4848 const uint32_t *getCallPreservedMask(CallingConv::ID CC) const override;
4949 const uint32_t *getNoPreservedMask() const;
50
51 void adjustStackMapLiveOutMask(uint32_t *Mask) const override;
5052
5153 BitVector getReservedRegs(const MachineFunction &MF) const override;
5254
180180 case Intrinsic::ssub_with_overflow:
181181 case Intrinsic::usub_with_overflow:
182182 if ((Idx == 1) && Imm.getBitWidth() <= 64 && isInt<16>(Imm.getSExtValue()))
183 return TCC_Free;
184 break;
185 case Intrinsic::experimental_stackmap:
186 if ((Idx < 2) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))
187 return TCC_Free;
188 break;
189 case Intrinsic::experimental_patchpoint_void:
190 case Intrinsic::experimental_patchpoint_i64:
191 if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))
183192 return TCC_Free;
184193 break;
185194 }
0 ; RUN: not llc < %s -mtriple=powerpc64-unknown-linux-gnu 2>&1 | FileCheck %s
1 ;
2 ; Check that misuse of anyregcc results in a compile time error.
3
4 ; CHECK: LLVM ERROR: ran out of registers during register allocation
5 define i64 @anyreglimit(i64 %v1, i64 %v2, i64 %v3, i64 %v4, i64 %v5, i64 %v6, i64 %v7, i64 %v8,
6 i64 %v9, i64 %v10, i64 %v11, i64 %v12, i64 %v13, i64 %v14, i64 %v15, i64 %v16,
7 i64 %v17, i64 %v18, i64 %v19, i64 %v20, i64 %v21, i64 %v22, i64 %v23, i64 %v24,
8 i64 %v25, i64 %v26, i64 %v27, i64 %v28, i64 %v29, i64 %v30, i64 %v31, i64 %v32) {
9 entry:
10 %result = tail call anyregcc i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 12, i32 15, i8* inttoptr (i64 0 to i8*), i32 32,
11 i64 %v1, i64 %v2, i64 %v3, i64 %v4, i64 %v5, i64 %v6, i64 %v7, i64 %v8,
12 i64 %v9, i64 %v10, i64 %v11, i64 %v12, i64 %v13, i64 %v14, i64 %v15, i64 %v16,
13 i64 %v17, i64 %v18, i64 %v19, i64 %v20, i64 %v21, i64 %v22, i64 %v23, i64 %v24,
14 i64 %v25, i64 %v26, i64 %v27, i64 %v28, i64 %v29, i64 %v30, i64 %v31, i64 %v32)
15 ret i64 %result
16 }
17
18 declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
0 ; RUN: llc < %s | FileCheck %s
1 target datalayout = "E-m:e-i64:64-n32:64"
2 target triple = "powerpc64-unknown-linux-gnu"
3
4 ; Stackmap Header: no constants - 6 callsites
5 ; CHECK-LABEL: .section .llvm_stackmaps
6 ; CHECK-NEXT: __LLVM_StackMaps:
7 ; Header
8 ; CHECK-NEXT: .byte 1
9 ; CHECK-NEXT: .byte 0
10 ; CHECK-NEXT: .short 0
11 ; Num Functions
12 ; CHECK-NEXT: .long 8
13 ; Num LargeConstants
14 ; CHECK-NEXT: .long 0
15 ; Num Callsites
16 ; CHECK-NEXT: .long 8
17
18 ; Functions and stack size
19 ; CHECK-NEXT: .quad test
20 ; CHECK-NEXT: .quad 128
21 ; CHECK-NEXT: .quad property_access1
22 ; CHECK-NEXT: .quad 128
23 ; CHECK-NEXT: .quad property_access2
24 ; CHECK-NEXT: .quad 128
25 ; CHECK-NEXT: .quad property_access3
26 ; CHECK-NEXT: .quad 128
27 ; CHECK-NEXT: .quad anyreg_test1
28 ; CHECK-NEXT: .quad 160
29 ; CHECK-NEXT: .quad anyreg_test2
30 ; CHECK-NEXT: .quad 160
31 ; CHECK-NEXT: .quad patchpoint_spilldef
32 ; CHECK-NEXT: .quad 256
33 ; CHECK-NEXT: .quad patchpoint_spillargs
34 ; CHECK-NEXT: .quad 288
35
36
37 ; test
38 ; CHECK-LABEL: .long .L{{.*}}-.L.test
39 ; CHECK-NEXT: .short 0
40 ; 3 locations
41 ; CHECK-NEXT: .short 3
42 ; Loc 0: Register
43 ; CHECK-NEXT: .byte 1
44 ; CHECK-NEXT: .byte 4
45 ; CHECK-NEXT: .short {{[0-9]+}}
46 ; CHECK-NEXT: .long 0
47 ; Loc 1: Register
48 ; CHECK-NEXT: .byte 1
49 ; CHECK-NEXT: .byte 4
50 ; CHECK-NEXT: .short {{[0-9]+}}
51 ; CHECK-NEXT: .long 0
52 ; Loc 2: Constant 3
53 ; CHECK-NEXT: .byte 4
54 ; CHECK-NEXT: .byte 8
55 ; CHECK-NEXT: .short 0
56 ; CHECK-NEXT: .long 3
57 define i64 @test() nounwind ssp uwtable {
58 entry:
59 call anyregcc void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 0, i32 24, i8* null, i32 2, i32 1, i32 2, i64 3)
60 ret i64 0
61 }
62
63 ; property access 1 - %obj is an anyreg call argument and should therefore be in a register
64 ; CHECK-LABEL: .long .L{{.*}}-.L.property_access1
65 ; CHECK-NEXT: .short 0
66 ; 2 locations
67 ; CHECK-NEXT: .short 2
68 ; Loc 0: Register <-- this is the return register
69 ; CHECK-NEXT: .byte 1
70 ; CHECK-NEXT: .byte 8
71 ; CHECK-NEXT: .short {{[0-9]+}}
72 ; CHECK-NEXT: .long 0
73 ; Loc 1: Register
74 ; CHECK-NEXT: .byte 1
75 ; CHECK-NEXT: .byte 8
76 ; CHECK-NEXT: .short {{[0-9]+}}
77 ; CHECK-NEXT: .long 0
78 define i64 @property_access1(i8* %obj) nounwind ssp uwtable {
79 entry:
80 %f = inttoptr i64 281474417671919 to i8*
81 %ret = call anyregcc i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 1, i32 24, i8* %f, i32 1, i8* %obj)
82 ret i64 %ret
83 }
84
85 ; property access 2 - %obj is an anyreg call argument and should therefore be in a register
86 ; CHECK-LABEL: .long .L{{.*}}-.L.property_access2
87 ; CHECK-NEXT: .short 0
88 ; 2 locations
89 ; CHECK-NEXT: .short 2
90 ; Loc 0: Register <-- this is the return register
91 ; CHECK-NEXT: .byte 1
92 ; CHECK-NEXT: .byte 8
93 ; CHECK-NEXT: .short {{[0-9]+}}
94 ; CHECK-NEXT: .long 0
95 ; Loc 1: Register
96 ; CHECK-NEXT: .byte 1
97 ; CHECK-NEXT: .byte 8
98 ; CHECK-NEXT: .short {{[0-9]+}}
99 ; CHECK-NEXT: .long 0
100 define i64 @property_access2() nounwind ssp uwtable {
101 entry:
102 %obj = alloca i64, align 8
103 %f = inttoptr i64 281474417671919 to i8*
104 %ret = call anyregcc i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 2, i32 24, i8* %f, i32 1, i64* %obj)
105 ret i64 %ret
106 }
107
108 ; property access 3 - %obj is a frame index
109 ; CHECK-LABEL: .long .L{{.*}}-.L.property_access3
110 ; CHECK-NEXT: .short 0
111 ; 2 locations
112 ; CHECK-NEXT: .short 2
113 ; Loc 0: Register <-- this is the return register
114 ; CHECK-NEXT: .byte 1
115 ; CHECK-NEXT: .byte 8
116 ; CHECK-NEXT: .short {{[0-9]+}}
117 ; CHECK-NEXT: .long 0
118 ; Loc 1: Direct FP - 8
119 ; CHECK-NEXT: .byte 2
120 ; CHECK-NEXT: .byte 8
121 ; CHECK-NEXT: .short 31
122 ; CHECK-NEXT: .long 112
123 define i64 @property_access3() nounwind ssp uwtable {
124 entry:
125 %obj = alloca i64, align 8
126 %f = inttoptr i64 281474417671919 to i8*
127 %ret = call anyregcc i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 3, i32 24, i8* %f, i32 0, i64* %obj)
128 ret i64 %ret
129 }
130
131 ; anyreg_test1
132 ; CHECK-LABEL: .long .L{{.*}}-.L.anyreg_test1
133 ; CHECK-NEXT: .short 0
134 ; 14 locations
135 ; CHECK-NEXT: .short 14
136 ; Loc 0: Register <-- this is the return register
137 ; CHECK-NEXT: .byte 1
138 ; CHECK-NEXT: .byte 8
139 ; CHECK-NEXT: .short {{[0-9]+}}
140 ; CHECK-NEXT: .long 0
141 ; Loc 1: Register
142 ; CHECK-NEXT: .byte 1
143 ; CHECK-NEXT: .byte 8
144 ; CHECK-NEXT: .short {{[0-9]+}}
145 ; CHECK-NEXT: .long 0
146 ; Loc 2: Register
147 ; CHECK-NEXT: .byte 1
148 ; CHECK-NEXT: .byte 8
149 ; CHECK-NEXT: .short {{[0-9]+}}
150 ; CHECK-NEXT: .long 0
151 ; Loc 3: Register
152 ; CHECK-NEXT: .byte 1
153 ; CHECK-NEXT: .byte 8
154 ; CHECK-NEXT: .short {{[0-9]+}}
155 ; CHECK-NEXT: .long 0
156 ; Loc 4: Register
157 ; CHECK-NEXT: .byte 1
158 ; CHECK-NEXT: .byte 8
159 ; CHECK-NEXT: .short {{[0-9]+}}
160 ; CHECK-NEXT: .long 0
161 ; Loc 5: Register
162 ; CHECK-NEXT: .byte 1
163 ; CHECK-NEXT: .byte 8
164 ; CHECK-NEXT: .short {{[0-9]+}}
165 ; CHECK-NEXT: .long 0
166 ; Loc 6: Register
167 ; CHECK-NEXT: .byte 1
168 ; CHECK-NEXT: .byte 8
169 ; CHECK-NEXT: .short {{[0-9]+}}
170 ; CHECK-NEXT: .long 0
171 ; Loc 7: Register
172 ; CHECK-NEXT: .byte 1
173 ; CHECK-NEXT: .byte 8
174 ; CHECK-NEXT: .short {{[0-9]+}}
175 ; CHECK-NEXT: .long 0
176 ; Loc 8: Register
177 ; CHECK-NEXT: .byte 1
178 ; CHECK-NEXT: .byte 8
179 ; CHECK-NEXT: .short {{[0-9]+}}
180 ; CHECK-NEXT: .long 0
181 ; Loc 9: Register
182 ; CHECK-NEXT: .byte 1
183 ; CHECK-NEXT: .byte 8
184 ; CHECK-NEXT: .short {{[0-9]+}}
185 ; CHECK-NEXT: .long 0
186 ; Loc 10: Register
187 ; CHECK-NEXT: .byte 1
188 ; CHECK-NEXT: .byte 8
189 ; CHECK-NEXT: .short {{[0-9]+}}
190 ; CHECK-NEXT: .long 0
191 ; Loc 11: Register
192 ; CHECK-NEXT: .byte 1
193 ; CHECK-NEXT: .byte 8
194 ; CHECK-NEXT: .short {{[0-9]+}}
195 ; CHECK-NEXT: .long 0
196 ; Loc 12: Register
197 ; CHECK-NEXT: .byte 1
198 ; CHECK-NEXT: .byte 8
199 ; CHECK-NEXT: .short {{[0-9]+}}
200 ; CHECK-NEXT: .long 0
201 ; Loc 13: Register
202 ; CHECK-NEXT: .byte 1
203 ; CHECK-NEXT: .byte 8
204 ; CHECK-NEXT: .short {{[0-9]+}}
205 ; CHECK-NEXT: .long 0
206 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, i8* %a13) nounwind ssp uwtable {
207 entry:
208 %f = inttoptr i64 281474417671919 to i8*
209 %ret = call anyregcc i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 4, i32 24, i8* %f, i32 13, i8* %a1, i8* %a2, i8* %a3, i8* %a4, i8* %a5, i8* %a6, i8* %a7, i8* %a8, i8* %a9, i8* %a10, i8* %a11, i8* %a12, i8* %a13)
210 ret i64 %ret
211 }
212
213 ; anyreg_test2
214 ; CHECK-LABEL: .long .L{{.*}}-.L.anyreg_test2
215 ; CHECK-NEXT: .short 0
216 ; 14 locations
217 ; CHECK-NEXT: .short 14
218 ; Loc 0: Register <-- this is the return register
219 ; CHECK-NEXT: .byte 1
220 ; CHECK-NEXT: .byte 8
221 ; CHECK-NEXT: .short {{[0-9]+}}
222 ; CHECK-NEXT: .long 0
223 ; Loc 1: Register
224 ; CHECK-NEXT: .byte 1
225 ; CHECK-NEXT: .byte 8
226 ; CHECK-NEXT: .short {{[0-9]+}}
227 ; CHECK-NEXT: .long 0
228 ; Loc 2: Register
229 ; CHECK-NEXT: .byte 1
230 ; CHECK-NEXT: .byte 8
231 ; CHECK-NEXT: .short {{[0-9]+}}
232 ; CHECK-NEXT: .long 0
233 ; Loc 3: Register
234 ; CHECK-NEXT: .byte 1
235 ; CHECK-NEXT: .byte 8
236 ; CHECK-NEXT: .short {{[0-9]+}}
237 ; CHECK-NEXT: .long 0
238 ; Loc 4: Register
239 ; CHECK-NEXT: .byte 1
240 ; CHECK-NEXT: .byte 8
241 ; CHECK-NEXT: .short {{[0-9]+}}
242 ; CHECK-NEXT: .long 0
243 ; Loc 5: Register
244 ; CHECK-NEXT: .byte 1
245 ; CHECK-NEXT: .byte 8
246 ; CHECK-NEXT: .short {{[0-9]+}}
247 ; CHECK-NEXT: .long 0
248 ; Loc 6: Register
249 ; CHECK-NEXT: .byte 1
250 ; CHECK-NEXT: .byte 8
251 ; CHECK-NEXT: .short {{[0-9]+}}
252 ; CHECK-NEXT: .long 0
253 ; Loc 7: Register
254 ; CHECK-NEXT: .byte 1
255 ; CHECK-NEXT: .byte 8
256 ; CHECK-NEXT: .short {{[0-9]+}}
257 ; CHECK-NEXT: .long 0
258 ; Loc 8: Register
259 ; CHECK-NEXT: .byte 1
260 ; CHECK-NEXT: .byte 8
261 ; CHECK-NEXT: .short {{[0-9]+}}
262 ; CHECK-NEXT: .long 0
263 ; Loc 9: Register
264 ; CHECK-NEXT: .byte 1
265 ; CHECK-NEXT: .byte 8
266 ; CHECK-NEXT: .short {{[0-9]+}}
267 ; CHECK-NEXT: .long 0
268 ; Loc 10: Register
269 ; CHECK-NEXT: .byte 1
270 ; CHECK-NEXT: .byte 8
271 ; CHECK-NEXT: .short {{[0-9]+}}
272 ; CHECK-NEXT: .long 0
273 ; Loc 11: Register
274 ; CHECK-NEXT: .byte 1
275 ; CHECK-NEXT: .byte 8
276 ; CHECK-NEXT: .short {{[0-9]+}}
277 ; CHECK-NEXT: .long 0
278 ; Loc 12: Register
279 ; CHECK-NEXT: .byte 1
280 ; CHECK-NEXT: .byte 8
281 ; CHECK-NEXT: .short {{[0-9]+}}
282 ; CHECK-NEXT: .long 0
283 ; Loc 13: Register
284 ; CHECK-NEXT: .byte 1
285 ; CHECK-NEXT: .byte 8
286 ; CHECK-NEXT: .short {{[0-9]+}}
287 ; CHECK-NEXT: .long 0
288 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, i8* %a13) nounwind ssp uwtable {
289 entry:
290 %f = inttoptr i64 281474417671919 to i8*
291 %ret = call anyregcc i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 5, i32 24, 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, i8* %a13)
292 ret i64 %ret
293 }
294
295 ; Test spilling the return value of an anyregcc call.
296 ;
297 ; [JS] Assertion: "Folded a def to a non-store!"
298 ;
299 ; CHECK-LABEL: .long .L{{.*}}-.L.patchpoint_spilldef
300 ; CHECK-NEXT: .short 0
301 ; CHECK-NEXT: .short 3
302 ; Loc 0: Register (some register that will be spilled to the stack)
303 ; CHECK-NEXT: .byte 1
304 ; CHECK-NEXT: .byte 8
305 ; CHECK-NEXT: .short {{[0-9]+}}
306 ; CHECK-NEXT: .long 0
307 ; Loc 1: Register
308 ; CHECK-NEXT: .byte 1
309 ; CHECK-NEXT: .byte 8
310 ; CHECK-NEXT: .short {{[0-9]+}}
311 ; CHECK-NEXT: .long 0
312 ; Loc 1: Register
313 ; CHECK-NEXT: .byte 1
314 ; CHECK-NEXT: .byte 8
315 ; CHECK-NEXT: .short {{[0-9]+}}
316 ; CHECK-NEXT: .long 0
317 define i64 @patchpoint_spilldef(i64 %p1, i64 %p2, i64 %p3, i64 %p4) {
318 entry:
319 %result = tail call anyregcc i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 12, i32 24, i8* inttoptr (i64 0 to i8*), i32 2, i64 %p1, i64 %p2)
320 tail call void asm sideeffect "nop", "~{r0},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r14},~{r15},~{r16},~{r17
321 },~{r18},~{r19},~{r20},~{r21},~{r22},~{r23},~{r24},~{r25},~{r26},~{r27},~{r28},~{r29},~{r30},~{r31}"() nounwind
322 ret i64 %result
323 }
324
325 ; Test spilling the arguments of an anyregcc call.
326 ;
327 ; [JS] AnyRegCC argument ends up being spilled
328 ;
329 ; CHECK-LABEL: .long .L{{.*}}-.L.patchpoint_spillargs
330 ; CHECK-NEXT: .short 0
331 ; CHECK-NEXT: .short 5
332 ; Loc 0: Return a register
333 ; CHECK-NEXT: .byte 1
334 ; CHECK-NEXT: .byte 8
335 ; CHECK-NEXT: .short {{[0-9]+}}
336 ; CHECK-NEXT: .long 0
337 ; Loc 1: Arg0 in a Register
338 ; CHECK-NEXT: .byte 1
339 ; CHECK-NEXT: .byte 8
340 ; CHECK-NEXT: .short {{[0-9]+}}
341 ; CHECK-NEXT: .long 0
342 ; Loc 2: Arg1 in a Register
343 ; CHECK-NEXT: .byte 1
344 ; CHECK-NEXT: .byte 8
345 ; CHECK-NEXT: .short {{[0-9]+}}
346 ; CHECK-NEXT: .long 0
347 ; Loc 3: Arg2 spilled to FP -96
348 ; CHECK-NEXT: .byte 3
349 ; CHECK-NEXT: .byte 8
350 ; CHECK-NEXT: .short 31
351 ; CHECK-NEXT: .long 128
352 ; Loc 4: Arg3 spilled to FP - 88
353 ; CHECK-NEXT: .byte 3
354 ; CHECK-NEXT: .byte 8
355 ; CHECK-NEXT: .short 31
356 ; CHECK-NEXT: .long 136
357 define i64 @patchpoint_spillargs(i64 %p1, i64 %p2, i64 %p3, i64 %p4) {
358 entry:
359 tail call void asm sideeffect "nop", "~{r0},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r14},~{r15},~{r16},~{r17
360 },~{r18},~{r19},~{r20},~{r21},~{r22},~{r23},~{r24},~{r25},~{r26},~{r27},~{r28},~{r29},~{r30},~{r31}"() nounwind
361 %result = tail call anyregcc i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 13, i32 24, i8* inttoptr (i64 0 to i8*), i32 2, i64 %p1, i64 %p2, i64 %p3, i64 %p4)
362 ret i64 %result
363 }
364
365 declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
366 declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
0 ; RUN: llc < %s | FileCheck %s
1 ; RUN: llc -fast-isel -fast-isel-abort < %s | FileCheck %s
2 target datalayout = "E-m:e-i64:64-n32:64"
3 target triple = "powerpc64-unknown-linux-gnu"
4
5 ; Trivial patchpoint codegen
6 ;
7 define i64 @trivial_patchpoint_codegen(i64 %p1, i64 %p2, i64 %p3, i64 %p4) {
8 entry:
9 ; CHECK-LABEL: trivial_patchpoint_codegen:
10
11 ; CHECK: li 11, -8531
12 ; CHECK-NEXT: rldic 11, 11, 32, 16
13 ; CHECK-NEXT: oris 11, 11, 48879
14 ; CHECK-NEXT: ori 11, 11, 51966
15 ; CHECK-NEXT: mtctr 11
16 ; CHECK-NEXT: bctrl
17
18 ; CHECK: li 11, -8531
19 ; CHECK-NEXT: rldic 11, 11, 32, 16
20 ; CHECK-NEXT: oris 11, 11, 48879
21 ; CHECK-NEXT: ori 11, 11, 51967
22 ; CHECK-NEXT: mtctr 11
23 ; CHECK-NEXT: bctrl
24
25 ; CHECK: blr
26
27 %resolveCall2 = inttoptr i64 244837814094590 to i8*
28 %result = tail call i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 2, i32 24, i8* %resolveCall2, i32 4, i64 %p1, i64 %p2, i64 %p3, i64 %p4)
29 %resolveCall3 = inttoptr i64 244837814094591 to i8*
30 tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 3, i32 24, i8* %resolveCall3, i32 2, i64 %p1, i64 %result)
31 ret i64 %result
32 }
33
34 ; Caller frame metadata with stackmaps. This should not be optimized
35 ; as a leaf function.
36 ;
37 ; CHECK-LABEL: caller_meta_leaf
38 ; CHECK: stdu 1, -80(1)
39 ; CHECK: Ltmp
40 ; CHECK: addi 1, 1, 80
41 ; CHECK: blr
42
43 define void @caller_meta_leaf() {
44 entry:
45 %metadata = alloca i64, i32 3, align 8
46 store i64 11, i64* %metadata
47 store i64 12, i64* %metadata
48 store i64 13, i64* %metadata
49 call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 4, i32 0, i64* %metadata)
50 ret void
51 }
52
53 ; Test patchpoints reusing the same TargetConstant.
54 ; Assertion failed: (CI.getNumArgOperands() >= NumArgs + 4)
55 ; There is no way to verify this, since it depends on memory allocation.
56 ; But I think it's useful to include as a working example.
57 define i64 @testLowerConstant(i64 %arg, i64 %tmp2, i64 %tmp10, i64* %tmp33, i64 %tmp79) {
58 entry:
59 %tmp80 = add i64 %tmp79, -16
60 %tmp81 = inttoptr i64 %tmp80 to i64*
61 %tmp82 = load i64* %tmp81, align 8
62 tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 14, i32 8, i64 %arg, i64 %tmp2, i64 %tmp10, i64 %tmp82)
63 tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 15, i32 32, i8* null, i32 3, i64 %arg, i64 %tmp10, i64 %tmp82)
64 %tmp83 = load i64* %tmp33, align 8
65 %tmp84 = add i64 %tmp83, -24
66 %tmp85 = inttoptr i64 %tmp84 to i64*
67 %tmp86 = load i64* %tmp85, align 8
68 tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 17, i32 8, i64 %arg, i64 %tmp10, i64 %tmp86)
69 tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 18, i32 32, i8* null, i32 3, i64 %arg, i64 %tmp10, i64 %tmp86)
70 ret i64 10
71 }
72
73 ; Test small patchpoints that don't emit calls.
74 define void @small_patchpoint_codegen(i64 %p1, i64 %p2, i64 %p3, i64 %p4) {
75 entry:
76 ; CHECK-LABEL: small_patchpoint_codegen:
77 ; CHECK: Ltmp
78 ; CHECK: nop
79 ; CHECK-NEXT: nop
80 ; CHECK-NEXT: nop
81 ; CHECK-NEXT: nop
82 ; CHECK-NEXT: nop
83 ; CHECK-NOT: nop
84 ; CHECK: blr
85 %result = tail call i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 5, i32 20, i8* null, i32 2, i64 %p1, i64 %p2)
86 ret void
87 }
88
89 declare void @llvm.experimental.stackmap(i64, i32, ...)
90 declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
91 declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
92
0 ; RUN: llc < %s -mtriple=powerpc64-unknown-gnu-linux | FileCheck %s
1
2 define void @test_shadow_optimization() {
3 entry:
4 ; Expect 12 bytes worth of nops here rather than 32: With the shadow optimization
5 ; in place, 20 bytes will be consumed by the frame teardown and return instr.
6 ; CHECK-LABEL: test_shadow_optimization:
7
8 ; CHECK: nop
9 ; CHECK-NEXT: nop
10 ; CHECK-NEXT: nop
11 ; CHECK-NOT: nop
12 ; CHECK: addi 1, 1, 64
13 ; CHECK: ld [[REG1:[0-9]+]], 16(1)
14 ; CHECK: ld 31, -8(1)
15 ; CHECK: mtlr [[REG1]]
16 ; CHECK: blr
17
18 tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 0, i32 32)
19 ret void
20 }
21
22 declare void @llvm.experimental.stackmap(i64, i32, ...)
23
0 ; RUN: llc < %s | FileCheck %s
1 ;
2 ; Note: Print verbose stackmaps using -debug-only=stackmaps.
3
4 ; We are not getting the correct stack alignment when cross compiling for arm64.
5 ; So specify a datalayout here.
6 target datalayout = "E-m:e-i64:64-n32:64"
7 target triple = "powerpc64-unknown-linux-gnu"
8
9 ; CHECK-LABEL: .section .llvm_stackmaps
10 ; CHECK-NEXT: __LLVM_StackMaps:
11 ; Header
12 ; CHECK-NEXT: .byte 1
13 ; CHECK-NEXT: .byte 0
14 ; CHECK-NEXT: .short 0
15 ; Num Functions
16 ; CHECK-NEXT: .long 11
17 ; Num LargeConstants
18 ; CHECK-NEXT: .long 2
19 ; Num Callsites
20 ; CHECK-NEXT: .long 11
21
22 ; Functions and stack size
23 ; CHECK-NEXT: .quad constantargs
24 ; CHECK-NEXT: .quad 128
25 ; CHECK-NEXT: .quad osrinline
26 ; CHECK-NEXT: .quad 144
27 ; CHECK-NEXT: .quad osrcold
28 ; CHECK-NEXT: .quad 128
29 ; CHECK-NEXT: .quad propertyRead
30 ; CHECK-NEXT: .quad 128
31 ; CHECK-NEXT: .quad propertyWrite
32 ; CHECK-NEXT: .quad 128
33 ; CHECK-NEXT: .quad jsVoidCall
34 ; CHECK-NEXT: .quad 128
35 ; CHECK-NEXT: .quad jsIntCall
36 ; CHECK-NEXT: .quad 128
37 ; CHECK-NEXT: .quad spilledValue
38 ; CHECK-NEXT: .quad 320
39 ; CHECK-NEXT: .quad spilledStackMapValue
40 ; CHECK-NEXT: .quad 224
41 ; CHECK-NEXT: .quad liveConstant
42 ; CHECK-NEXT: .quad 64
43 ; CHECK-NEXT: .quad clobberLR
44 ; CHECK-NEXT: .quad 208
45
46 ; Num LargeConstants
47 ; CHECK-NEXT: .quad 4294967295
48 ; CHECK-NEXT: .quad 4294967296
49
50 ; Constant arguments
51 ;
52 ; CHECK-NEXT: .quad 1
53 ; CHECK-NEXT: .long .L{{.*}}-.L.constantargs
54 ; CHECK-NEXT: .short 0
55 ; CHECK-NEXT: .short 4
56 ; SmallConstant
57 ; CHECK-NEXT: .byte 4
58 ; CHECK-NEXT: .byte 8
59 ; CHECK-NEXT: .short 0
60 ; CHECK-NEXT: .long 65535
61 ; SmallConstant
62 ; CHECK-NEXT: .byte 4
63 ; CHECK-NEXT: .byte 8
64 ; CHECK-NEXT: .short 0
65 ; CHECK-NEXT: .long 65536
66 ; SmallConstant
67 ; CHECK-NEXT: .byte 5
68 ; CHECK-NEXT: .byte 8
69 ; CHECK-NEXT: .short 0
70 ; CHECK-NEXT: .long 0
71 ; LargeConstant at index 0
72 ; CHECK-NEXT: .byte 5
73 ; CHECK-NEXT: .byte 8
74 ; CHECK-NEXT: .short 0
75 ; CHECK-NEXT: .long 1
76
77 define void @constantargs() {
78 entry:
79 %0 = inttoptr i64 244837814094590 to i8*
80 tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 1, i32 24, i8* %0, i32 0, i64 65535, i64 65536, i64 4294967295, i64 4294967296)
81 ret void
82 }
83
84 ; Inline OSR Exit
85 ;
86 ; CHECK-LABEL: .long .L{{.*}}-.L.osrinline
87 ; CHECK-NEXT: .short 0
88 ; CHECK-NEXT: .short 2
89 ; CHECK-NEXT: .byte 1
90 ; CHECK-NEXT: .byte 8
91 ; CHECK-NEXT: .short {{[0-9]+}}
92 ; CHECK-NEXT: .long 0
93 ; CHECK-NEXT: .byte 1
94 ; CHECK-NEXT: .byte 8
95 ; CHECK-NEXT: .short {{[0-9]+}}
96 ; CHECK-NEXT: .long 0
97 define void @osrinline(i64 %a, i64 %b) {
98 entry:
99 ; Runtime void->void call.
100 call void inttoptr (i64 244837814094590 to void ()*)()
101 ; Followed by inline OSR patchpoint with 12-byte shadow and 2 live vars.
102 call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 3, i32 12, i64 %a, i64 %b)
103 ret void
104 }
105
106 ; Cold OSR Exit
107 ;
108 ; 2 live variables in register.
109 ;
110 ; CHECK-LABEL: .long .L{{.*}}-.L.osrcold
111 ; CHECK-NEXT: .short 0
112 ; CHECK-NEXT: .short 2
113 ; CHECK-NEXT: .byte 1
114 ; CHECK-NEXT: .byte 8
115 ; CHECK-NEXT: .short {{[0-9]+}}
116 ; CHECK-NEXT: .long 0
117 ; CHECK-NEXT: .byte 1
118 ; CHECK-NEXT: .byte 8
119 ; CHECK-NEXT: .short {{[0-9]+}}
120 ; CHECK-NEXT: .long 0
121 define void @osrcold(i64 %a, i64 %b) {
122 entry:
123 %test = icmp slt i64 %a, %b
124 br i1 %test, label %ret, label %cold
125 cold:
126 ; OSR patchpoint with 12-byte nop-slide and 2 live vars.
127 %thunk = inttoptr i64 244837814094590 to i8*
128 call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 4, i32 24, i8* %thunk, i32 0, i64 %a, i64 %b)
129 unreachable
130 ret:
131 ret void
132 }
133
134 ; Property Read
135 ; CHECK-LABEL: .long .L{{.*}}-.L.propertyRead
136 ; CHECK-NEXT: .short 0
137 ; CHECK-NEXT: .short 0
138 ;
139 ; FIXME: There are currently no stackmap entries. After moving to
140 ; AnyRegCC, we will have entries for the object and return value.
141 define i64 @propertyRead(i64* %obj) {
142 entry:
143 %resolveRead = inttoptr i64 244837814094590 to i8*
144 %result = call i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 5, i32 24, i8* %resolveRead, i32 1, i64* %obj)
145 %add = add i64 %result, 3
146 ret i64 %add
147 }
148
149 ; Property Write
150 ; CHECK-LABEL: .long .L{{.*}}-.L.propertyWrite
151 ; CHECK-NEXT: .short 0
152 ; CHECK-NEXT: .short 2
153 ; CHECK-NEXT: .byte 1
154 ; CHECK-NEXT: .byte 8
155 ; CHECK-NEXT: .short {{[0-9]+}}
156 ; CHECK-NEXT: .long 0
157 ; CHECK-NEXT: .byte 1
158 ; CHECK-NEXT: .byte 8
159 ; CHECK-NEXT: .short {{[0-9]+}}
160 ; CHECK-NEXT: .long 0
161 define void @propertyWrite(i64 %dummy1, i64* %obj, i64 %dummy2, i64 %a) {
162 entry:
163 %resolveWrite = inttoptr i64 244837814094590 to i8*
164 call anyregcc void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 6, i32 24, i8* %resolveWrite, i32 2, i64* %obj, i64 %a)
165 ret void
166 }
167
168 ; Void JS Call
169 ;
170 ; 2 live variables in registers.
171 ;
172 ; CHECK-LABEL: .long .L{{.*}}-.L.jsVoidCall
173 ; CHECK-NEXT: .short 0
174 ; CHECK-NEXT: .short 2
175 ; CHECK-NEXT: .byte 1
176 ; CHECK-NEXT: .byte 8
177 ; CHECK-NEXT: .short {{[0-9]+}}
178 ; CHECK-NEXT: .long 0
179 ; CHECK-NEXT: .byte 1
180 ; CHECK-NEXT: .byte 8
181 ; CHECK-NEXT: .short {{[0-9]+}}
182 ; CHECK-NEXT: .long 0
183 define void @jsVoidCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) {
184 entry:
185 %resolveCall = inttoptr i64 244837814094590 to i8*
186 call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 7, i32 24, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2)
187 ret void
188 }
189
190 ; i64 JS Call
191 ;
192 ; 2 live variables in registers.
193 ;
194 ; CHECK-LABEL: .long .L{{.*}}-.L.jsIntCall
195 ; CHECK-NEXT: .short 0
196 ; CHECK-NEXT: .short 2
197 ; CHECK-NEXT: .byte 1
198 ; CHECK-NEXT: .byte 8
199 ; CHECK-NEXT: .short {{[0-9]+}}
200 ; CHECK-NEXT: .long 0
201 ; CHECK-NEXT: .byte 1
202 ; CHECK-NEXT: .byte 8
203 ; CHECK-NEXT: .short {{[0-9]+}}
204 ; CHECK-NEXT: .long 0
205 define i64 @jsIntCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) {
206 entry:
207 %resolveCall = inttoptr i64 244837814094590 to i8*
208 %result = call i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 8, i32 24, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2)
209 %add = add i64 %result, 3
210 ret i64 %add
211 }
212
213 ; Spilled stack map values.
214 ;
215 ; Verify 28 stack map entries.
216 ;
217 ; CHECK-LABEL: .long .L{{.*}}-.L.spilledValue
218 ; CHECK-NEXT: .short 0
219 ; CHECK-NEXT: .short 28
220 ;
221 ; Check that at least one is a spilled entry from r31.
222 ; Location: Indirect FP + ...
223 ; CHECK: .byte 3
224 ; CHECK-NEXT: .byte 8
225 ; CHECK-NEXT: .short 31
226 define void @spilledValue(i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16, i64 %l17, i64 %l18, i64 %l19, i64 %l20, i64 %l21, i64 %l22, i64 %l23, i64 %l24, i64 %l25, i64 %l26, i64 %l27) {
227 entry:
228 call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 11, i32 24, i8* null, i32 5, i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16, i64 %l17, i64 %l18, i64 %l19, i64 %l20, i64 %l21, i64 %l22, i64 %l23, i64 %l24, i64 %l25, i64 %l26, i64 %l27)
229 ret void
230 }
231
232 ; Spilled stack map values.
233 ;
234 ; Verify 30 stack map entries.
235 ;
236 ; CHECK-LABEL: .long .L{{.*}}-.L.spilledStackMapValue
237 ; CHECK-NEXT: .short 0
238 ; CHECK-NEXT: .short 30
239 ;
240 ; Check that at least one is a spilled entry from r31.
241 ; Location: Indirect FP + ...
242 ; CHECK: .byte 3
243 ; CHECK-NEXT: .byte 8
244 ; CHECK-NEXT: .short 31
245 define webkit_jscc void @spilledStackMapValue(i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16, i64 %l17, i64 %l18, i64 %l19, i64 %l20, i64 %l21, i64 %l22, i64 %l23, i64 %l24, i64 %l25, i64 %l26, i64 %l27, i64 %l28, i64 %l29) {
246 entry:
247 call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 12, i32 16, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16, i64 %l17, i64 %l18, i64 %l19, i64 %l20, i64 %l21, i64 %l22, i64 %l23, i64 %l24, i64 %l25, i64 %l26, i64 %l27, i64 %l28, i64 %l29)
248 ret void
249 }
250
251
252 ; Map a constant value.
253 ;
254 ; CHECK-LABEL: .long .L{{.*}}-.L.liveConstant
255 ; CHECK-NEXT: .short 0
256 ; 1 location
257 ; CHECK-NEXT: .short 1
258 ; Loc 0: SmallConstant
259 ; CHECK-NEXT: .byte 4
260 ; CHECK-NEXT: .byte 8
261 ; CHECK-NEXT: .short 0
262 ; CHECK-NEXT: .long 33
263
264 define void @liveConstant() {
265 tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 15, i32 8, i32 33)
266 ret void
267 }
268
269 ; Map a value when LR is the only free register.
270 ;
271 ; CHECK-LABEL: .long .L{{.*}}-.L.clobberLR
272 ; CHECK-NEXT: .short 0
273 ; 1 location
274 ; CHECK-NEXT: .short 1
275 ; Loc 0: Indirect FP (r31) - offset
276 ; CHECK-NEXT: .byte 3
277 ; CHECK-NEXT: .byte 4
278 ; CHECK-NEXT: .short 31
279 ; CHECK-NEXT: .long {{[0-9]+}}
280 define void @clobberLR(i32 %a) {
281 tail call void asm sideeffect "nop", "~{r0},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r14},~{r15},~{r16},~{r17},~{r18},~{r19},~{r20},~{r21},~{r22},~{r23},~{r24},~{r25},~{r26},~{r27},~{r28},~{r29},~{r30},~{r31}"() nounwind
282 tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 16, i32 8, i32 %a)
283 ret void
284 }
285
286 declare void @llvm.experimental.stackmap(i64, i32, ...)
287 declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
288 declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)