Skip to content

Commit 1618341

Browse files
committed
[RISCV] Add Stackmap/Statepoint/Patchpoint support with targets
1 parent bbcfe6f commit 1618341

File tree

4 files changed

+120
-3
lines changed

4 files changed

+120
-3
lines changed

llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "MCTargetDesc/RISCVBaseInfo.h"
1515
#include "MCTargetDesc/RISCVInstPrinter.h"
1616
#include "MCTargetDesc/RISCVMCExpr.h"
17+
#include "MCTargetDesc/RISCVMatInt.h"
1718
#include "MCTargetDesc/RISCVTargetStreamer.h"
1819
#include "RISCV.h"
1920
#include "RISCVMachineFunctionInfo.h"
@@ -152,8 +153,35 @@ void RISCVAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
152153

153154
PatchPointOpers Opers(&MI);
154155

156+
const MachineOperand &CalleeMO = Opers.getCallTarget();
155157
unsigned EncodedBytes = 0;
156158

159+
if (CalleeMO.isImm()) {
160+
uint64_t CallTarget = CalleeMO.getImm();
161+
if (CallTarget) {
162+
assert((CallTarget & 0xFFFF'FFFF'FFFF) == CallTarget &&
163+
"High 16 bits of call target should be zero.");
164+
// Materialize the jump address:
165+
SmallVector<MCInst, 8> Seq;
166+
RISCVMatInt::generateMCInstSeq(CallTarget, *STI, RISCV::X1, Seq);
167+
for (MCInst &Inst : Seq) {
168+
EmitToStreamer(OutStreamer, Inst);
169+
}
170+
EncodedBytes += Seq.size() * 4;
171+
EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
172+
.addReg(RISCV::X1)
173+
.addReg(RISCV::X1)
174+
.addImm(0));
175+
EncodedBytes += 4;
176+
}
177+
} else if (CalleeMO.isGlobal()) {
178+
MCOperand CallTargetMCOp;
179+
lowerOperand(CalleeMO, CallTargetMCOp);
180+
EmitToStreamer(OutStreamer,
181+
MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));
182+
EncodedBytes += 8;
183+
}
184+
157185
// Emit padding.
158186
unsigned NumBytes = Opers.getNumPatchBytes();
159187
assert(NumBytes >= EncodedBytes &&
@@ -172,6 +200,35 @@ void RISCVAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
172200
assert(PatchBytes % NOPBytes == 0 &&
173201
"Invalid number of NOP bytes requested!");
174202
emitNops(PatchBytes / NOPBytes);
203+
} else {
204+
// Lower call target and choose correct opcode
205+
const MachineOperand &CallTarget = SOpers.getCallTarget();
206+
MCOperand CallTargetMCOp;
207+
switch (CallTarget.getType()) {
208+
case MachineOperand::MO_GlobalAddress:
209+
case MachineOperand::MO_ExternalSymbol:
210+
lowerOperand(CallTarget, CallTargetMCOp);
211+
EmitToStreamer(
212+
OutStreamer,
213+
MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));
214+
break;
215+
case MachineOperand::MO_Immediate:
216+
CallTargetMCOp = MCOperand::createImm(CallTarget.getImm());
217+
EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JAL)
218+
.addReg(RISCV::X1)
219+
.addOperand(CallTargetMCOp));
220+
break;
221+
case MachineOperand::MO_Register:
222+
CallTargetMCOp = MCOperand::createReg(CallTarget.getReg());
223+
EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
224+
.addReg(RISCV::X1)
225+
.addOperand(CallTargetMCOp)
226+
.addImm(0));
227+
break;
228+
default:
229+
llvm_unreachable("Unsupported operand type in statepoint call target");
230+
break;
231+
}
175232
}
176233

177234
auto &Ctx = OutStreamer.getContext();

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17789,6 +17789,17 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
1778917789
case RISCV::PseudoFROUND_D_IN32X:
1779017790
return emitFROUND(MI, BB, Subtarget);
1779117791
case TargetOpcode::STATEPOINT:
17792+
// STATEPOINT is a pseudo instruction which has no implicit defs/uses
17793+
// while jal call instruction (where statepoint will be lowered at the end)
17794+
// has implicit def. This def is early-clobber as it will be set at
17795+
// the moment of the call and earlier than any use is read.
17796+
// Add this implicit dead def here as a workaround.
17797+
MI.addOperand(*MI.getMF(),
17798+
MachineOperand::CreateReg(
17799+
RISCV::X1, /*isDef*/ true,
17800+
/*isImp*/ true, /*isKill*/ false, /*isDead*/ true,
17801+
/*isUndef*/ false, /*isEarlyClobber*/ true));
17802+
[[fallthrough]];
1779217803
case TargetOpcode::STACKMAP:
1779317804
case TargetOpcode::PATCHPOINT:
1779417805
if (!Subtarget.is64Bit())

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,9 +1523,14 @@ unsigned RISCVInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
15231523
case TargetOpcode::PATCHPOINT:
15241524
// The size of the patchpoint intrinsic is the number of bytes requested
15251525
return PatchPointOpers(&MI).getNumPatchBytes();
1526-
case TargetOpcode::STATEPOINT:
1526+
case TargetOpcode::STATEPOINT: {
15271527
// The size of the statepoint intrinsic is the number of bytes requested
1528-
return StatepointOpers(&MI).getNumPatchBytes();
1528+
unsigned NumBytes = StatepointOpers(&MI).getNumPatchBytes();
1529+
// A statepoint is at least a PseudoCALL
1530+
if (NumBytes < 8)
1531+
NumBytes = 8;
1532+
return NumBytes;
1533+
}
15291534
default:
15301535
return get(Opcode).getSize();
15311536
}

llvm/test/CodeGen/RISCV/rv64-patchpoint.ll

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,56 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
22
; RUN: llc -mtriple=riscv64 -debug-entry-values -enable-misched=0 < %s | FileCheck %s
33

4+
; Trivial patchpoint codegen
5+
;
6+
define i64 @trivial_patchpoint_codegen(i64 %p1, i64 %p2, i64 %p3, i64 %p4) {
7+
; CHECK-LABEL: trivial_patchpoint_codegen:
8+
; CHECK: # %bb.0: # %entry
9+
; CHECK-NEXT: addi sp, sp, -16
10+
; CHECK-NEXT: .cfi_def_cfa_offset 16
11+
; CHECK-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
12+
; CHECK-NEXT: sd s1, 0(sp) # 8-byte Folded Spill
13+
; CHECK-NEXT: .cfi_offset s0, -8
14+
; CHECK-NEXT: .cfi_offset s1, -16
15+
; CHECK-NEXT: mv s0, a0
16+
; CHECK-NEXT: .Ltmp0:
17+
; CHECK-NEXT: lui ra, 3563
18+
; CHECK-NEXT: addiw ra, ra, -577
19+
; CHECK-NEXT: slli ra, ra, 12
20+
; CHECK-NEXT: addi ra, ra, -259
21+
; CHECK-NEXT: slli ra, ra, 12
22+
; CHECK-NEXT: addi ra, ra, -1282
23+
; CHECK-NEXT: jalr ra
24+
; CHECK-NEXT: mv s1, a0
25+
; CHECK-NEXT: mv a0, s0
26+
; CHECK-NEXT: mv a1, s1
27+
; CHECK-NEXT: .Ltmp1:
28+
; CHECK-NEXT: lui ra, 3563
29+
; CHECK-NEXT: addiw ra, ra, -577
30+
; CHECK-NEXT: slli ra, ra, 12
31+
; CHECK-NEXT: addi ra, ra, -259
32+
; CHECK-NEXT: slli ra, ra, 12
33+
; CHECK-NEXT: addi ra, ra, -1281
34+
; CHECK-NEXT: jalr ra
35+
; CHECK-NEXT: mv a0, s1
36+
; CHECK-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
37+
; CHECK-NEXT: ld s1, 0(sp) # 8-byte Folded Reload
38+
; CHECK-NEXT: addi sp, sp, 16
39+
; CHECK-NEXT: ret
40+
entry:
41+
%resolveCall2 = inttoptr i64 244837814094590 to i8*
42+
%result = tail call i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 2, i32 28, i8* %resolveCall2, i32 4, i64 %p1, i64 %p2, i64 %p3, i64 %p4)
43+
%resolveCall3 = inttoptr i64 244837814094591 to i8*
44+
tail call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 3, i32 28, i8* %resolveCall3, i32 2, i64 %p1, i64 %result)
45+
ret i64 %result
46+
}
47+
448
; Test small patchpoints that don't emit calls.
549
define void @small_patchpoint_codegen(i64 %p1, i64 %p2, i64 %p3, i64 %p4) {
650
; CHECK-LABEL: small_patchpoint_codegen:
751
; CHECK: # %bb.0: # %entry
852
; CHECK-NEXT: .cfi_def_cfa_offset 0
9-
; CHECK-NEXT: .Ltmp0:
53+
; CHECK-NEXT: .Ltmp2:
1054
; CHECK-NEXT: nop
1155
; CHECK-NEXT: nop
1256
; CHECK-NEXT: nop

0 commit comments

Comments
 (0)