mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-24 13:06:56 +00:00
[FastISel] Add support for the stackmap intrinsic.
This implements target-independent FastISel lowering for the stackmap intrinsic. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210742 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7411b432e6
commit
2c9a12f081
@ -23,6 +23,7 @@ namespace llvm {
|
||||
class AllocaInst;
|
||||
class Constant;
|
||||
class ConstantFP;
|
||||
class CallInst;
|
||||
class DataLayout;
|
||||
class FunctionLoweringInfo;
|
||||
class Instruction;
|
||||
@ -411,6 +412,9 @@ private:
|
||||
/// beginning of the block. It helps to avoid spilling cached variables across
|
||||
/// heavy instructions like calls.
|
||||
void flushLocalValueMap();
|
||||
|
||||
bool addStackMapLiveVars(SmallVectorImpl<MachineOperand> &Ops,
|
||||
const CallInst *CI, unsigned StartIdx);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -45,9 +45,11 @@
|
||||
#include "llvm/Analysis/Loads.h"
|
||||
#include "llvm/CodeGen/Analysis.h"
|
||||
#include "llvm/CodeGen/FunctionLoweringInfo.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/StackMaps.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
@ -558,6 +560,36 @@ bool FastISel::SelectGetElementPtr(const User *I) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Add a stack map intrinsic call's live variable operands to a stackmap
|
||||
/// or patchpoint machine instruction.
|
||||
///
|
||||
bool FastISel::addStackMapLiveVars(SmallVectorImpl<MachineOperand> &Ops,
|
||||
const CallInst *CI, unsigned StartIdx) {
|
||||
for (unsigned i = StartIdx, e = CI->getNumArgOperands(); i != e; ++i) {
|
||||
Value *Val = CI->getArgOperand(i);
|
||||
if (auto *C = dyn_cast<ConstantInt>(Val)) {
|
||||
Ops.push_back(MachineOperand::CreateImm(StackMaps::ConstantOp));
|
||||
Ops.push_back(MachineOperand::CreateImm(C->getSExtValue()));
|
||||
} else if (isa<ConstantPointerNull>(Val)) {
|
||||
Ops.push_back(MachineOperand::CreateImm(StackMaps::ConstantOp));
|
||||
Ops.push_back(MachineOperand::CreateImm(0));
|
||||
} else if (auto *AI = dyn_cast<AllocaInst>(Val)) {
|
||||
auto SI = FuncInfo.StaticAllocaMap.find(AI);
|
||||
if (SI != FuncInfo.StaticAllocaMap.end())
|
||||
Ops.push_back(MachineOperand::CreateFI(SI->second));
|
||||
else
|
||||
return false;
|
||||
} else {
|
||||
unsigned Reg = getRegForValue(Val);
|
||||
if (Reg == 0)
|
||||
return false;
|
||||
Ops.push_back(MachineOperand::CreateReg(Reg, /*IsDef=*/false));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FastISel::SelectCall(const User *I) {
|
||||
const CallInst *Call = cast<CallInst>(I);
|
||||
|
||||
@ -713,6 +745,76 @@ bool FastISel::SelectCall(const User *I) {
|
||||
UpdateValueMap(Call, ResultReg);
|
||||
return true;
|
||||
}
|
||||
case Intrinsic::experimental_stackmap: {
|
||||
// void @llvm.experimental.stackmap(i64 <id>, i32 <numShadowBytes>,
|
||||
// [live variables...])
|
||||
|
||||
assert(Call->getCalledFunction()->getReturnType()->isVoidTy() &&
|
||||
"Stackmap cannot return a value.");
|
||||
|
||||
// The stackmap intrinsic only records the live variables (the arguments
|
||||
// passed to it) and emits NOPS (if requested). Unlike the patchpoint
|
||||
// intrinsic, this won't be lowered to a function call. This means we don't
|
||||
// have to worry about calling conventions and target-specific lowering
|
||||
// code. Instead we perform the call lowering right here.
|
||||
//
|
||||
// CALLSEQ_START(0)
|
||||
// STACKMAP(id, nbytes, ...)
|
||||
// CALLSEQ_END(0, 0)
|
||||
//
|
||||
|
||||
SmallVector<MachineOperand, 32> Ops;
|
||||
|
||||
// Add the <id> and <numBytes> constants.
|
||||
assert(isa<ConstantInt>(Call->getOperand(PatchPointOpers::IDPos)) &&
|
||||
"Expected a constant integer.");
|
||||
auto IDVal = cast<ConstantInt>(Call->getOperand(PatchPointOpers::IDPos));
|
||||
Ops.push_back(MachineOperand::CreateImm(IDVal->getZExtValue()));
|
||||
|
||||
assert(isa<ConstantInt>(Call->getOperand(PatchPointOpers::NBytesPos)) &&
|
||||
"Expected a constant integer.");
|
||||
auto NBytesVal =
|
||||
cast<ConstantInt>(Call->getOperand(PatchPointOpers::NBytesPos));
|
||||
Ops.push_back(MachineOperand::CreateImm(NBytesVal->getZExtValue()));
|
||||
|
||||
// Push live variables for the stack map.
|
||||
if (!addStackMapLiveVars(Ops, Call, 2))
|
||||
return false;
|
||||
|
||||
// We are not adding any register mask info here, because the stackmap
|
||||
// doesn't clobber anything.
|
||||
|
||||
// Add scratch registers as implicit def and early clobber.
|
||||
CallingConv::ID CC = Call->getCallingConv();
|
||||
const MCPhysReg *ScratchRegs = TLI.getScratchRegisters(CC);
|
||||
for (unsigned i = 0; ScratchRegs[i]; ++i)
|
||||
Ops.push_back(MachineOperand::CreateReg(
|
||||
ScratchRegs[i], /*IsDef=*/true, /*IsImp=*/true, /*IsKill=*/false,
|
||||
/*IsDead=*/false, /*IsUndef=*/false, /*IsEarlyClobber=*/true));
|
||||
|
||||
// Issue CALLSEQ_START
|
||||
unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AdjStackDown))
|
||||
.addImm(0);
|
||||
|
||||
// Issue STACKMAP.
|
||||
MachineInstrBuilder MIB;
|
||||
MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(TargetOpcode::STACKMAP));
|
||||
|
||||
for (auto const &MO : Ops)
|
||||
MIB.addOperand(MO);
|
||||
|
||||
// Issue CALLSEQ_END
|
||||
unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AdjStackUp))
|
||||
.addImm(0).addImm(0);
|
||||
|
||||
// Inform the Frame Information that we have a stackmap in this function.
|
||||
FuncInfo.MF->getFrameInfo()->setHasStackMap();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Usually, it does not make sense to initialize a value,
|
||||
|
165
test/CodeGen/X86/stackmap-fast-isel.ll
Normal file
165
test/CodeGen/X86/stackmap-fast-isel.ll
Normal file
@ -0,0 +1,165 @@
|
||||
; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7 -disable-fp-elim | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7 -disable-fp-elim -fast-isel -fast-isel-abort | FileCheck %s
|
||||
|
||||
; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps
|
||||
; CHECK-NEXT: __LLVM_StackMaps:
|
||||
; Header
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 0
|
||||
; Num Functions
|
||||
; CHECK-NEXT: .long 4
|
||||
; Num LargeConstants
|
||||
; CHECK-NEXT: .long 3
|
||||
; Num Callsites
|
||||
; CHECK-NEXT: .long 7
|
||||
|
||||
; Functions and stack size
|
||||
; CHECK-NEXT: .quad _constantargs
|
||||
; CHECK-NEXT: .quad 8
|
||||
; CHECK-NEXT: .quad _liveConstant
|
||||
; CHECK-NEXT: .quad 8
|
||||
; CHECK-NEXT: .quad _directFrameIdx
|
||||
; CHECK-NEXT: .quad 40
|
||||
; CHECK-NEXT: .quad _longid
|
||||
; CHECK-NEXT: .quad 8
|
||||
|
||||
; Large Constants
|
||||
; CHECK-NEXT: .quad 2147483648
|
||||
; CHECK-NEXT: .quad 4294967295
|
||||
; CHECK-NEXT: .quad 4294967296
|
||||
|
||||
; Callsites
|
||||
; Constant arguments
|
||||
;
|
||||
; CHECK-NEXT: .quad 1
|
||||
; CHECK-NEXT: .long L{{.*}}-_constantargs
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .short 12
|
||||
; SmallConstant
|
||||
; CHECK-NEXT: .byte 4
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long -1
|
||||
; SmallConstant
|
||||
; CHECK-NEXT: .byte 4
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long -1
|
||||
; SmallConstant
|
||||
; CHECK-NEXT: .byte 4
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 65536
|
||||
; SmallConstant
|
||||
; CHECK-NEXT: .byte 4
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 2000000000
|
||||
; SmallConstant
|
||||
; CHECK-NEXT: .byte 4
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 2147483647
|
||||
; SmallConstant
|
||||
; CHECK-NEXT: .byte 4
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long -1
|
||||
; SmallConstant
|
||||
; CHECK-NEXT: .byte 4
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long -1
|
||||
; SmallConstant
|
||||
; CHECK-NEXT: .byte 4
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; LargeConstant at index 0
|
||||
; CHECK-NEXT: .byte 5
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 0
|
||||
; LargeConstant at index 1
|
||||
; CHECK-NEXT: .byte 5
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 1
|
||||
; LargeConstant at index 2
|
||||
; CHECK-NEXT: .byte 5
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 2
|
||||
; SmallConstant
|
||||
; CHECK-NEXT: .byte 4
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long -1
|
||||
|
||||
define void @constantargs() {
|
||||
entry:
|
||||
tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 1, i32 15, i16 65535, i16 -1, i32 65536, i32 2000000000, i32 2147483647, i32 -1, i32 4294967295, i32 4294967296, i64 2147483648, i64 4294967295, i64 4294967296, i64 -1)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Map a constant value.
|
||||
;
|
||||
; CHECK-LABEL: .long L{{.*}}-_liveConstant
|
||||
; CHECK-NEXT: .short 0
|
||||
; 1 location
|
||||
; CHECK-NEXT: .short 1
|
||||
; Loc 0: SmallConstant
|
||||
; CHECK-NEXT: .byte 4
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 0
|
||||
; CHECK-NEXT: .long 33
|
||||
|
||||
define void @liveConstant() {
|
||||
tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 15, i32 5, i32 33)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Directly map an alloca's address.
|
||||
;
|
||||
; Callsite 16
|
||||
; CHECK-LABEL: .long L{{.*}}-_directFrameIdx
|
||||
; CHECK-NEXT: .short 0
|
||||
; 1 location
|
||||
; CHECK-NEXT: .short 1
|
||||
; Loc 0: Direct RBP - ofs
|
||||
; CHECK-NEXT: .byte 2
|
||||
; CHECK-NEXT: .byte 8
|
||||
; CHECK-NEXT: .short 6
|
||||
; CHECK-NEXT: .long
|
||||
|
||||
define void @directFrameIdx() {
|
||||
entry:
|
||||
%metadata1 = alloca i64, i32 3, align 8
|
||||
store i64 11, i64* %metadata1
|
||||
store i64 12, i64* %metadata1
|
||||
store i64 13, i64* %metadata1
|
||||
call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 16, i32 0, i64* %metadata1)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Test a 64-bit ID.
|
||||
;
|
||||
; CHECK: .quad 4294967295
|
||||
; CHECK-LABEL: .long L{{.*}}-_longid
|
||||
; CHECK: .quad 4294967296
|
||||
; CHECK-LABEL: .long L{{.*}}-_longid
|
||||
; CHECK: .quad 9223372036854775807
|
||||
; CHECK-LABEL: .long L{{.*}}-_longid
|
||||
; CHECK: .quad -1
|
||||
; CHECK-LABEL: .long L{{.*}}-_longid
|
||||
define void @longid() {
|
||||
entry:
|
||||
tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 4294967295, i32 0)
|
||||
tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 4294967296, i32 0)
|
||||
tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 9223372036854775807, i32 0)
|
||||
tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 -1, i32 0)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @llvm.experimental.stackmap(i64, i32, ...)
|
Loading…
Reference in New Issue
Block a user