Skip to content

Commit

Permalink
MIR Statepoint refactoring. Part 1: Basic MI level changes.
Browse files Browse the repository at this point in the history
Basic support for variadic-def MIR Statepoint:
- Change TableGen STATEPOINT description to variadic out list
  (For self-documentation purpose; by itself it does not affect
  code generation in any way).
- Update StatepointOpers helper class to handle variadic defs.
- Update MachineVerifier to properly handle them, too.

With this change, new Statepoint instruction can be passed through
backend (excluding ISEL) without errors.

Full change set is available at D81603.
Reviewed By: reames
Differential Revision: https://reviews.llvm.org/D81645
  • Loading branch information
dantrushin committed Jul 16, 2020
1 parent d909764 commit ef658eb
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 9 deletions.
19 changes: 11 additions & 8 deletions llvm/include/llvm/CodeGen/StackMaps.h
Expand Up @@ -166,21 +166,23 @@ class StatepointOpers {
enum { CCOffset = 1, FlagsOffset = 3, NumDeoptOperandsOffset = 5 };

public:
explicit StatepointOpers(const MachineInstr *MI) : MI(MI) {}
explicit StatepointOpers(const MachineInstr *MI) : MI(MI) {
NumDefs = MI->getNumDefs();
}

/// Get index of statepoint ID operand.
unsigned getIDPos() const { return IDPos; }
unsigned getIDPos() const { return NumDefs + IDPos; }

/// Get index of Num Patch Bytes operand.
unsigned getNBytesPos() const { return NBytesPos; }
unsigned getNBytesPos() const { return NumDefs + NBytesPos; }

/// Get index of Num Call Arguments operand.
unsigned getNCallArgsPos() const { return NCallArgsPos; }
unsigned getNCallArgsPos() const { return NumDefs + NCallArgsPos; }

/// Get starting index of non call related arguments
/// (calling convention, statepoint flags, vm state and gc state).
unsigned getVarIdx() const {
return MI->getOperand(NCallArgsPos).getImm() + MetaEnd;
return MI->getOperand(NumDefs + NCallArgsPos).getImm() + MetaEnd + NumDefs;
}

/// Get index of Calling Convention operand.
Expand All @@ -195,16 +197,16 @@ class StatepointOpers {
}

/// Return the ID for the given statepoint.
uint64_t getID() const { return MI->getOperand(IDPos).getImm(); }
uint64_t getID() const { return MI->getOperand(NumDefs + IDPos).getImm(); }

/// Return the number of patchable bytes the given statepoint should emit.
uint32_t getNumPatchBytes() const {
return MI->getOperand(NBytesPos).getImm();
return MI->getOperand(NumDefs + NBytesPos).getImm();
}

/// Return the target of the underlying call.
const MachineOperand &getCallTarget() const {
return MI->getOperand(CallTargetPos);
return MI->getOperand(NumDefs + CallTargetPos);
}

/// Return the calling convention.
Expand All @@ -217,6 +219,7 @@ class StatepointOpers {

private:
const MachineInstr *MI;
unsigned NumDefs;
};

class StackMaps {
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Target/Target.td
Expand Up @@ -1157,7 +1157,7 @@ def PATCHPOINT : StandardPseudoInstruction {
let usesCustomInserter = 1;
}
def STATEPOINT : StandardPseudoInstruction {
let OutOperandList = (outs);
let OutOperandList = (outs variable_ops);
let InOperandList = (ins variable_ops);
let usesCustomInserter = 1;
let mayLoad = 1;
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/CodeGen/MachineVerifier.cpp
Expand Up @@ -1565,6 +1565,9 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
if (MCID.getOpcode() == TargetOpcode::PATCHPOINT)
NumDefs = (MONum == 0 && MO->isReg()) ? NumDefs : 0;

if (MCID.getOpcode() == TargetOpcode::STATEPOINT)
NumDefs = MI->getNumDefs();

// The first MCID.NumDefs operands must be explicit register defines
if (MONum < NumDefs) {
const MCOperandInfo &MCOI = MCID.OpInfo[MONum];
Expand Down
156 changes: 156 additions & 0 deletions llvm/test/CodeGen/X86/statepoint-vreg.mir
@@ -0,0 +1,156 @@
# NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
# RUN: llc -o - %s -start-after=finalize-isel | FileCheck %s

--- |
; ModuleID = 'test/CodeGen/X86/statepoint-vreg.ll'
source_filename = "test/CodeGen/X86/statepoint-vreg.ll"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

declare void @bar()

define i32 @test_basic(i32 addrspace(1)* %obj1, i32 addrspace(1)* %obj2) gc "statepoint-example" {
; CHECK-LABEL: test_basic:
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %r14
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 24
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 32
; CHECK-NEXT: .cfi_offset %rbx, -24
; CHECK-NEXT: .cfi_offset %r14, -16
; CHECK-NEXT: movq %rsi, %r14
; CHECK-NEXT: movq %rdi, %rbx
; CHECK-NEXT: callq bar
; CHECK-NEXT: .Ltmp0:
; CHECK-NEXT: movl (%rbx), %eax
; CHECK-NEXT: addl (%r14), %eax
; CHECK-NEXT: addq $8, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 24
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: popq %r14
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
%token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* %obj1, i32 addrspace(1)* %obj2) ]
%rel1 = call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %token, i32 0, i32 0) ; (%obj1, %obj1)
%rel2 = call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %token, i32 1, i32 1) ; (%obj2, %obj2)
%a = load i32, i32 addrspace(1)* %rel1, align 4
%b = load i32, i32 addrspace(1)* %rel2, align 4
%c = add i32 %a, %b
ret i32 %c
}

; CHECK-LABEL: __LLVM_StackMaps:
; CHECK-NEXT: .byte 3
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 1
; CHECK-NEXT: .long 0
; CHECK-NEXT: .long 1
; CHECK-NEXT: .quad test_basic
; CHECK-NEXT: .quad 24
; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad 2882400000
; CHECK-NEXT: .long .Ltmp0-test_basic
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 1
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 14
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 14
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 3
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 3
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; CHECK-NEXT: .p2align 3
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .p2align 3

declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 immarg, i32 immarg, void ()*, i32 immarg, i32 immarg, ...)

; Function Attrs: nounwind readonly
declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32 immarg, i32 immarg) #0

attributes #0 = { nounwind readonly }
attributes #1 = { nounwind }

...
---
name: test_basic
alignment: 16
selected: false
failedISel: false
tracksRegLiveness: true
registers:
- { id: 0, class: gr64, preferred-register: '' }
- { id: 1, class: gr64, preferred-register: '' }
- { id: 2, class: gr64, preferred-register: '' }
- { id: 3, class: gr64, preferred-register: '' }
- { id: 4, class: gr32, preferred-register: '' }
- { id: 5, class: gr32, preferred-register: '' }
liveins:
- { reg: '$rdi', virtual-reg: '%0' }
- { reg: '$rsi', virtual-reg: '%1' }
fixedStack: []
stack: []
callSites: []
constants: []
machineFunctionInfo: {}
body: |
bb.0 (%ir-block.0):
liveins: $rdi, $rsi
%1:gr64 = COPY $rsi
%0:gr64 = COPY $rdi
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
%2:gr64, %3:gr64 = STATEPOINT 2882400000, 0, 0, @bar, 2, 0, 2, 0, 2, 1, 2, 0, %1, %1(tied-def 0), %0, %0(tied-def 1), csr_64, implicit-def $rsp, implicit-def $ssp
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
%4:gr32 = MOV32rm killed %3, 1, $noreg, 0, $noreg :: (load 4 from %ir.rel1, addrspace 1)
%5:gr32 = ADD32rm %4, killed %2, 1, $noreg, 0, $noreg, implicit-def dead $eflags :: (load 4 from %ir.rel2, addrspace 1)
$eax = COPY %5
RET 0, $eax
...

0 comments on commit ef658eb

Please sign in to comment.