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