Skip to content

Commit

Permalink
Ensure that vectors are reported correctly in stackmaps.
Browse files Browse the repository at this point in the history
To get an accurate view of a vector live variable, we have to
recursively search the DAG for the initial `BUILD_VECTOR` DAG node and
then look for `INSERT_VECTOR_ELT` nodes (element insertions) as we
bubble up from recursion, updating our view as we go.

Also Updated tests to cover this use case.

(The search technique was inspired by the `getUnderlyingArgRegs()`
function from the same file, which does something similar: recursively
searches for `CopyFromReg` nodes)
  • Loading branch information
vext01 committed Aug 31, 2022
1 parent 22e35b8 commit 72842cf
Show file tree
Hide file tree
Showing 3 changed files with 343 additions and 10 deletions.
36 changes: 30 additions & 6 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9288,6 +9288,34 @@ void SelectionDAGBuilder::populateCallLoweringInfo(
Call->countOperandBundlesOfType(LLVMContext::OB_preallocated) != 0);
}

/// Given the stackmap live variable `N`, search its sub-DAG and return all of
/// the constituent values that need to be reported in the stackmap table.
static std::vector<SDValue> findLiveConstituents(SelectionDAG &DAG,
const SDValue &N) {
std::vector<SDValue> V;

switch (N.getOpcode()) {
case ISD::BUILD_PAIR:
case ISD::CONCAT_VECTORS:
case ISD::MERGE_VALUES:
case ISD::BUILD_VECTOR:
for (SDValue Op : N->op_values())
V.push_back(Op);
break;
case ISD::INSERT_VECTOR_ELT: {
V = findLiveConstituents(DAG, N.getOperand(0));
unsigned Idx =
cast<ConstantSDNode>(N.getOperand(2).getNode())->getZExtValue();
V[Idx] = N.getOperand(1);
break;
}
default:
V.push_back(N);
}

return V;
}

/// Add a stack map intrinsic call's live variable operands to a stackmap
/// or patchpoint target node's operand list.
///
Expand Down Expand Up @@ -9320,12 +9348,8 @@ static void addStackMapLiveVars(const CallBase &Call, unsigned StartIdx,
Ops.push_back(DAG.getTargetFrameIndex(FI->getIndex(), Op.getValueType()));
} else {
// Otherwise emit a target independent node to be legalised.
if (Op.getOpcode() == ISD::MERGE_VALUES) {
for (unsigned J = 0; J < Op.getNumOperands(); J++)
Ops.push_back(Op.getOperand(J));
} else {
Ops.push_back(Op);
}
for (SDValue &V : findLiveConstituents(DAG, Op))
Ops.push_back(V);
}
Ops.push_back(DAG.getTargetConstant(StackMaps::NextLive, DL, MVT::i64));
}
Expand Down
190 changes: 188 additions & 2 deletions llvm/test/CodeGen/X86/selectiondag-patchpoint-legalize.ll
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
; CHECK-NEXT: .long {{.*}}
; CHECK-NEXT: .short {{.*}}
; NumLiveVars
; CHECK-NEXT: .short 11
; CHECK-NEXT: .short 16
; LiveVar[NumLiveVars]
; LiveVar[0]
; CHECK-NEXT: .byte 1
Expand Down Expand Up @@ -165,6 +165,184 @@
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; LiveVars[11]
; CHECK-NEXT: .byte 4
; Locations[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
; Locations[1]
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 1
; Locations[1]
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 2
; Locations[1]
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 3
; LiveVars[12]
; CHECK-NEXT: .byte 4
; Locations[0]
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 4
; CHECK-NEXT: .short {{.*}}
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; Locations[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
; Locations[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
; Locations[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
; LiveVars[13]
; CHECK-NEXT: .byte 4
; Locations[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
; Locations[1]
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 4
; CHECK-NEXT: .short {{.*}}
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; Locations[2]
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; Locations[3]
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; LiveVars[14]
; CHECK-NEXT: .byte 8
; Locations[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
; Locations[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
; Locations[2]
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; Locations[3]
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; Locations[4]
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; Locations[5]
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; Locations[6]
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; Locations[7]
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 4
; CHECK-NEXT: .short {{.*}}
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 0
; LiveVars[14]
; CHECK-NEXT: .byte 4
; Locations[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
; Locations[1]
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 1
; Locations[2]
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 2
; Locations[3]
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 3

@p32 = external global i8 addrspace(270)*

Expand All @@ -181,6 +359,9 @@ entry:
%ptr32 = load i8 addrspace(270)*, i8 addrspace(270)** @p32
%structreg1 = insertvalue %struct1 zeroinitializer, i32 %argc, 0
%structreg2 = insertvalue %struct2 zeroinitializer, i1 %i1reg, 0
%arrayreg = insertvalue [4 x i32] zeroinitializer, i32 %argc, 0
%vec = insertelement <4 x i32> zeroinitializer, i32 %argc, i32 1
%bigvec = insertelement <8 x i32> zeroinitializer, i32 %argc, i32 7
call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(
i64 0,
i32 0,
Expand All @@ -206,6 +387,11 @@ entry:
%struct1 zeroinitializer,
%struct1 %structreg1,
%struct2 zeroinitializer,
%struct2 %structreg2)
%struct2 %structreg2,
[4 x i32] [i32 0, i32 1, i32 2, i32 3],
[4 x i32] %arrayreg,
<4 x i32> %vec,
<8 x i32> %bigvec,
<4 x i8> <i8 0, i8 1, i8 2, i8 3>)
ret i32 0
}
Loading

0 comments on commit 72842cf

Please sign in to comment.