aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp30
1 files changed, 24 insertions, 6 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
index e2db9633bfb9..dfda7d8b9f81 100644
--- a/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
+++ b/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
@@ -990,6 +990,24 @@ SDValue SelectionDAGBuilder::LowerAsSTATEPOINT(
return ReturnVal;
}
+/// Return two gc.results if present. First result is a block local
+/// gc.result, second result is a non-block local gc.result. Corresponding
+/// entry will be nullptr if not present.
+static std::pair<const GCResultInst*, const GCResultInst*>
+getGCResultLocality(const GCStatepointInst &S) {
+ std::pair<const GCResultInst *, const GCResultInst*> Res(nullptr, nullptr);
+ for (auto *U : S.users()) {
+ auto *GRI = dyn_cast<GCResultInst>(U);
+ if (!GRI)
+ continue;
+ if (GRI->getParent() == S.getParent())
+ Res.first = GRI;
+ else
+ Res.second = GRI;
+ }
+ return Res;
+}
+
void
SelectionDAGBuilder::LowerStatepoint(const GCStatepointInst &I,
const BasicBlock *EHPadBB /*= nullptr*/) {
@@ -1075,12 +1093,11 @@ SelectionDAGBuilder::LowerStatepoint(const GCStatepointInst &I,
SDValue ReturnValue = LowerAsSTATEPOINT(SI);
// Export the result value if needed
- const std::pair<bool, bool> GCResultLocality = I.getGCResultLocality();
- Type *RetTy = I.getActualReturnType();
+ const auto GCResultLocality = getGCResultLocality(I);
- if (RetTy->isVoidTy() ||
- (!GCResultLocality.first && !GCResultLocality.second)) {
- // The return value is not needed, just generate a poison value.
+ if (!GCResultLocality.first && !GCResultLocality.second) {
+ // The return value is not needed, just generate a poison value.
+ // Note: This covers the void return case.
setValue(&I, DAG.getIntPtrConstant(-1, getCurSDLoc()));
return;
}
@@ -1102,6 +1119,7 @@ SelectionDAGBuilder::LowerStatepoint(const GCStatepointInst &I,
// manually.
// TODO: To eliminate this problem we can remove gc.result intrinsics
// completely and make statepoint call to return a tuple.
+ Type *RetTy = GCResultLocality.second->getType();
unsigned Reg = FuncInfo.CreateRegs(RetTy);
RegsForValue RFV(*DAG.getContext(), DAG.getTargetLoweringInfo(),
DAG.getDataLayout(), Reg, RetTy,
@@ -1168,7 +1186,7 @@ void SelectionDAGBuilder::visitGCResult(const GCResultInst &CI) {
// register because statepoint and actual call return types can be
// different, and getValue() will use CopyFromReg of the wrong type,
// which is always i32 in our case.
- Type *RetTy = SI->getActualReturnType();
+ Type *RetTy = CI.getType();
SDValue CopyFromReg = getCopyFromRegs(SI, RetTy);
assert(CopyFromReg.getNode());