llvm.org GIT mirror llvm / 2c9a12f
[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 Juergen Ributzka 5 years ago
3 changed file(s) with 271 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
2222 class AllocaInst;
2323 class Constant;
2424 class ConstantFP;
25 class CallInst;
2526 class DataLayout;
2627 class FunctionLoweringInfo;
2728 class Instruction;
410411 /// beginning of the block. It helps to avoid spilling cached variables across
411412 /// heavy instructions like calls.
412413 void flushLocalValueMap();
414
415 bool addStackMapLiveVars(SmallVectorImpl &Ops,
416 const CallInst *CI, unsigned StartIdx);
413417 };
414418
415419 }
4444 #include "llvm/Analysis/Loads.h"
4545 #include "llvm/CodeGen/Analysis.h"
4646 #include "llvm/CodeGen/FunctionLoweringInfo.h"
47 #include "llvm/CodeGen/MachineFrameInfo.h"
4748 #include "llvm/CodeGen/MachineInstrBuilder.h"
4849 #include "llvm/CodeGen/MachineModuleInfo.h"
4950 #include "llvm/CodeGen/MachineRegisterInfo.h"
51 #include "llvm/CodeGen/StackMaps.h"
5052 #include "llvm/IR/DataLayout.h"
5153 #include "llvm/IR/DebugInfo.h"
5254 #include "llvm/IR/Function.h"
554556
555557 // We successfully emitted code for the given LLVM Instruction.
556558 UpdateValueMap(I, N);
559 return true;
560 }
561
562 /// \brief Add a stack map intrinsic call's live variable operands to a stackmap
563 /// or patchpoint machine instruction.
564 ///
565 bool FastISel::addStackMapLiveVars(SmallVectorImpl &Ops,
566 const CallInst *CI, unsigned StartIdx) {
567 for (unsigned i = StartIdx, e = CI->getNumArgOperands(); i != e; ++i) {
568 Value *Val = CI->getArgOperand(i);
569 if (auto *C = dyn_cast(Val)) {
570 Ops.push_back(MachineOperand::CreateImm(StackMaps::ConstantOp));
571 Ops.push_back(MachineOperand::CreateImm(C->getSExtValue()));
572 } else if (isa(Val)) {
573 Ops.push_back(MachineOperand::CreateImm(StackMaps::ConstantOp));
574 Ops.push_back(MachineOperand::CreateImm(0));
575 } else if (auto *AI = dyn_cast(Val)) {
576 auto SI = FuncInfo.StaticAllocaMap.find(AI);
577 if (SI != FuncInfo.StaticAllocaMap.end())
578 Ops.push_back(MachineOperand::CreateFI(SI->second));
579 else
580 return false;
581 } else {
582 unsigned Reg = getRegForValue(Val);
583 if (Reg == 0)
584 return false;
585 Ops.push_back(MachineOperand::CreateReg(Reg, /*IsDef=*/false));
586 }
587 }
588
557589 return true;
558590 }
559591
710742 if (ResultReg == 0)
711743 return false;
712744 UpdateValueMap(Call, ResultReg);
745 return true;
746 }
747 case Intrinsic::experimental_stackmap: {
748 // void @llvm.experimental.stackmap(i64 , i32 ,
749 // [live variables...])
750
751 assert(Call->getCalledFunction()->getReturnType()->isVoidTy() &&
752 "Stackmap cannot return a value.");
753
754 // The stackmap intrinsic only records the live variables (the arguments
755 // passed to it) and emits NOPS (if requested). Unlike the patchpoint
756 // intrinsic, this won't be lowered to a function call. This means we don't
757 // have to worry about calling conventions and target-specific lowering
758 // code. Instead we perform the call lowering right here.
759 //
760 // CALLSEQ_START(0)
761 // STACKMAP(id, nbytes, ...)
762 // CALLSEQ_END(0, 0)
763 //
764
765 SmallVector Ops;
766
767 // Add the and constants.
768 assert(isa(Call->getOperand(PatchPointOpers::IDPos)) &&
769 "Expected a constant integer.");
770 auto IDVal = cast(Call->getOperand(PatchPointOpers::IDPos));
771 Ops.push_back(MachineOperand::CreateImm(IDVal->getZExtValue()));
772
773 assert(isa(Call->getOperand(PatchPointOpers::NBytesPos)) &&
774 "Expected a constant integer.");
775 auto NBytesVal =
776 cast(Call->getOperand(PatchPointOpers::NBytesPos));
777 Ops.push_back(MachineOperand::CreateImm(NBytesVal->getZExtValue()));
778
779 // Push live variables for the stack map.
780 if (!addStackMapLiveVars(Ops, Call, 2))
781 return false;
782
783 // We are not adding any register mask info here, because the stackmap
784 // doesn't clobber anything.
785
786 // Add scratch registers as implicit def and early clobber.
787 CallingConv::ID CC = Call->getCallingConv();
788 const MCPhysReg *ScratchRegs = TLI.getScratchRegisters(CC);
789 for (unsigned i = 0; ScratchRegs[i]; ++i)
790 Ops.push_back(MachineOperand::CreateReg(
791 ScratchRegs[i], /*IsDef=*/true, /*IsImp=*/true, /*IsKill=*/false,
792 /*IsDead=*/false, /*IsUndef=*/false, /*IsEarlyClobber=*/true));
793
794 // Issue CALLSEQ_START
795 unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
796 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AdjStackDown))
797 .addImm(0);
798
799 // Issue STACKMAP.
800 MachineInstrBuilder MIB;
801 MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
802 TII.get(TargetOpcode::STACKMAP));
803
804 for (auto const &MO : Ops)
805 MIB.addOperand(MO);
806
807 // Issue CALLSEQ_END
808 unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
809 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AdjStackUp))
810 .addImm(0).addImm(0);
811
812 // Inform the Frame Information that we have a stackmap in this function.
813 FuncInfo.MF->getFrameInfo()->setHasStackMap();
814
713815 return true;
714816 }
715817 }
0 ; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7 -disable-fp-elim | FileCheck %s
1 ; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7 -disable-fp-elim -fast-isel -fast-isel-abort | FileCheck %s
2
3 ; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps
4 ; CHECK-NEXT: __LLVM_StackMaps:
5 ; Header
6 ; CHECK-NEXT: .byte 1
7 ; CHECK-NEXT: .byte 0
8 ; CHECK-NEXT: .short 0
9 ; Num Functions
10 ; CHECK-NEXT: .long 4
11 ; Num LargeConstants
12 ; CHECK-NEXT: .long 3
13 ; Num Callsites
14 ; CHECK-NEXT: .long 7
15
16 ; Functions and stack size
17 ; CHECK-NEXT: .quad _constantargs
18 ; CHECK-NEXT: .quad 8
19 ; CHECK-NEXT: .quad _liveConstant
20 ; CHECK-NEXT: .quad 8
21 ; CHECK-NEXT: .quad _directFrameIdx
22 ; CHECK-NEXT: .quad 40
23 ; CHECK-NEXT: .quad _longid
24 ; CHECK-NEXT: .quad 8
25
26 ; Large Constants
27 ; CHECK-NEXT: .quad 2147483648
28 ; CHECK-NEXT: .quad 4294967295
29 ; CHECK-NEXT: .quad 4294967296
30
31 ; Callsites
32 ; Constant arguments
33 ;
34 ; CHECK-NEXT: .quad 1
35 ; CHECK-NEXT: .long L{{.*}}-_constantargs
36 ; CHECK-NEXT: .short 0
37 ; CHECK-NEXT: .short 12
38 ; SmallConstant
39 ; CHECK-NEXT: .byte 4
40 ; CHECK-NEXT: .byte 8
41 ; CHECK-NEXT: .short 0
42 ; CHECK-NEXT: .long -1
43 ; SmallConstant
44 ; CHECK-NEXT: .byte 4
45 ; CHECK-NEXT: .byte 8
46 ; CHECK-NEXT: .short 0
47 ; CHECK-NEXT: .long -1
48 ; SmallConstant
49 ; CHECK-NEXT: .byte 4
50 ; CHECK-NEXT: .byte 8
51 ; CHECK-NEXT: .short 0
52 ; CHECK-NEXT: .long 65536
53 ; SmallConstant
54 ; CHECK-NEXT: .byte 4
55 ; CHECK-NEXT: .byte 8
56 ; CHECK-NEXT: .short 0
57 ; CHECK-NEXT: .long 2000000000
58 ; SmallConstant
59 ; CHECK-NEXT: .byte 4
60 ; CHECK-NEXT: .byte 8
61 ; CHECK-NEXT: .short 0
62 ; CHECK-NEXT: .long 2147483647
63 ; SmallConstant
64 ; CHECK-NEXT: .byte 4
65 ; CHECK-NEXT: .byte 8
66 ; CHECK-NEXT: .short 0
67 ; CHECK-NEXT: .long -1
68 ; SmallConstant
69 ; CHECK-NEXT: .byte 4
70 ; CHECK-NEXT: .byte 8
71 ; CHECK-NEXT: .short 0
72 ; CHECK-NEXT: .long -1
73 ; SmallConstant
74 ; CHECK-NEXT: .byte 4
75 ; CHECK-NEXT: .byte 8
76 ; CHECK-NEXT: .short 0
77 ; CHECK-NEXT: .long 0
78 ; LargeConstant at index 0
79 ; CHECK-NEXT: .byte 5
80 ; CHECK-NEXT: .byte 8
81 ; CHECK-NEXT: .short 0
82 ; CHECK-NEXT: .long 0
83 ; LargeConstant at index 1
84 ; CHECK-NEXT: .byte 5
85 ; CHECK-NEXT: .byte 8
86 ; CHECK-NEXT: .short 0
87 ; CHECK-NEXT: .long 1
88 ; LargeConstant at index 2
89 ; CHECK-NEXT: .byte 5
90 ; CHECK-NEXT: .byte 8
91 ; CHECK-NEXT: .short 0
92 ; CHECK-NEXT: .long 2
93 ; SmallConstant
94 ; CHECK-NEXT: .byte 4
95 ; CHECK-NEXT: .byte 8
96 ; CHECK-NEXT: .short 0
97 ; CHECK-NEXT: .long -1
98
99 define void @constantargs() {
100 entry:
101 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)
102 ret void
103 }
104
105 ; Map a constant value.
106 ;
107 ; CHECK-LABEL: .long L{{.*}}-_liveConstant
108 ; CHECK-NEXT: .short 0
109 ; 1 location
110 ; CHECK-NEXT: .short 1
111 ; Loc 0: SmallConstant
112 ; CHECK-NEXT: .byte 4
113 ; CHECK-NEXT: .byte 8
114 ; CHECK-NEXT: .short 0
115 ; CHECK-NEXT: .long 33
116
117 define void @liveConstant() {
118 tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 15, i32 5, i32 33)
119 ret void
120 }
121
122 ; Directly map an alloca's address.
123 ;
124 ; Callsite 16
125 ; CHECK-LABEL: .long L{{.*}}-_directFrameIdx
126 ; CHECK-NEXT: .short 0
127 ; 1 location
128 ; CHECK-NEXT: .short 1
129 ; Loc 0: Direct RBP - ofs
130 ; CHECK-NEXT: .byte 2
131 ; CHECK-NEXT: .byte 8
132 ; CHECK-NEXT: .short 6
133 ; CHECK-NEXT: .long
134
135 define void @directFrameIdx() {
136 entry:
137 %metadata1 = alloca i64, i32 3, align 8
138 store i64 11, i64* %metadata1
139 store i64 12, i64* %metadata1
140 store i64 13, i64* %metadata1
141 call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 16, i32 0, i64* %metadata1)
142 ret void
143 }
144
145 ; Test a 64-bit ID.
146 ;
147 ; CHECK: .quad 4294967295
148 ; CHECK-LABEL: .long L{{.*}}-_longid
149 ; CHECK: .quad 4294967296
150 ; CHECK-LABEL: .long L{{.*}}-_longid
151 ; CHECK: .quad 9223372036854775807
152 ; CHECK-LABEL: .long L{{.*}}-_longid
153 ; CHECK: .quad -1
154 ; CHECK-LABEL: .long L{{.*}}-_longid
155 define void @longid() {
156 entry:
157 tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 4294967295, i32 0)
158 tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 4294967296, i32 0)
159 tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 9223372036854775807, i32 0)
160 tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 -1, i32 0)
161 ret void
162 }
163
164 declare void @llvm.experimental.stackmap(i64, i32, ...)