@@ -1402,7 +1402,7 @@ SDValue NVPTXTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
1402
1402
// After all vararg is processed, 'VAOffset' holds the size of the
1403
1403
// vararg byte array.
1404
1404
1405
- SDValue VADeclareParam; // vararg byte array
1405
+ SDValue VADeclareParam = SDValue (); // vararg byte array
1406
1406
const unsigned FirstVAArg = CLI.NumFixedArgs ; // position of first variadic
1407
1407
unsigned VAOffset = 0 ; // current offset in the param array
1408
1408
@@ -1605,8 +1605,6 @@ SDValue NVPTXTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
1605
1605
VAOffset += TypeSize;
1606
1606
}
1607
1607
1608
- GlobalAddressSDNode *Func = dyn_cast<GlobalAddressSDNode>(Callee.getNode ());
1609
-
1610
1608
// Handle Result
1611
1609
if (!Ins.empty ()) {
1612
1610
const SDValue RetSymbol = DAG.getExternalSymbol (" retval0" , MVT::i32 );
@@ -1619,10 +1617,9 @@ SDValue NVPTXTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
1619
1617
}
1620
1618
}
1621
1619
1622
- const bool HasVAArgs = CLI.IsVarArg && (CLI.Args .size () > CLI.NumFixedArgs );
1623
1620
// Set the size of the vararg param byte array if the callee is a variadic
1624
1621
// function and the variadic part is not empty.
1625
- if (HasVAArgs ) {
1622
+ if (VADeclareParam ) {
1626
1623
SDValue DeclareParamOps[] = {VADeclareParam.getOperand (0 ),
1627
1624
VADeclareParam.getOperand (1 ),
1628
1625
VADeclareParam.getOperand (2 ), GetI32 (VAOffset),
@@ -1631,6 +1628,7 @@ SDValue NVPTXTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
1631
1628
VADeclareParam->getVTList (), DeclareParamOps);
1632
1629
}
1633
1630
1631
+ const auto *Func = dyn_cast<GlobalAddressSDNode>(Callee.getNode ());
1634
1632
// If the type of the callsite does not match that of the function, convert
1635
1633
// the callsite to an indirect call.
1636
1634
const bool ConvertToIndirectCall = shouldConvertToIndirectCall (CB, Func);
@@ -1660,6 +1658,7 @@ SDValue NVPTXTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
1660
1658
// instruction.
1661
1659
// The prototype is embedded in a string and put as the operand for a
1662
1660
// CallPrototype SDNode which will print out to the value of the string.
1661
+ const bool HasVAArgs = CLI.IsVarArg && (CLI.Args .size () > CLI.NumFixedArgs );
1663
1662
std::string Proto =
1664
1663
getPrototype (DL, RetTy, Args, CLI.Outs ,
1665
1664
HasVAArgs ? std::optional (FirstVAArg) : std::nullopt, *CB,
@@ -5729,6 +5728,15 @@ static SDValue combinePRMT(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
5729
5728
}
5730
5729
5731
5730
5731
+ // During call lowering we wrap the return values in a ProxyReg node which
5732
+ // depend on the chain value produced by the completed call. This ensures that
5733
+ // the full call is emitted in cases where libcalls are used to legalize
5734
+ // operations. To improve the functioning of other DAG combines we pull all
5735
+ // operations we can through one of these nodes, ensuring that the ProxyReg
5736
+ // directly wraps a load. That is:
5737
+ //
5738
+ // (ProxyReg (zext (load retval0))) => (zext (ProxyReg (load retval0)))
5739
+ //
5732
5740
static SDValue sinkProxyReg (SDValue R, SDValue Chain,
5733
5741
TargetLowering::DAGCombinerInfo &DCI) {
5734
5742
switch (R.getOpcode ()) {
@@ -5782,6 +5790,8 @@ static SDValue combineProxyReg(SDNode *N,
5782
5790
SDValue Chain = N->getOperand (0 );
5783
5791
SDValue Reg = N->getOperand (1 );
5784
5792
5793
+ // If the ProxyReg is not wrapping a load, try to pull the operations through
5794
+ // the ProxyReg.
5785
5795
if (Reg.getOpcode () != ISD::LOAD) {
5786
5796
if (SDValue V = sinkProxyReg (Reg, Chain, DCI))
5787
5797
return V;
0 commit comments