@@ -4521,6 +4521,9 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
4521
4521
break ;
4522
4522
case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR (N); break ;
4523
4523
case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT (N); break ;
4524
+ case ISD::ATOMIC_LOAD:
4525
+ Res = WidenVecRes_ATOMIC_LOAD (cast<AtomicSDNode>(N));
4526
+ break ;
4524
4527
case ISD::LOAD: Res = WidenVecRes_LOAD (N); break ;
4525
4528
case ISD::STEP_VECTOR:
4526
4529
case ISD::SPLAT_VECTOR:
@@ -5907,6 +5910,91 @@ SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
5907
5910
N->getOperand (1 ), N->getOperand (2 ));
5908
5911
}
5909
5912
5913
+ static std::optional<EVT> findMemType (SelectionDAG &DAG,
5914
+ const TargetLowering &TLI, unsigned Width,
5915
+ EVT WidenVT, unsigned Align,
5916
+ unsigned WidenEx);
5917
+
5918
+ SDValue DAGTypeLegalizer::WidenVecRes_ATOMIC_LOAD (AtomicSDNode *LD) {
5919
+ SmallVector<SDValue, 16 > LdChain; // Chain for the series of load
5920
+
5921
+ EVT WidenVT = TLI.getTypeToTransformTo (*DAG.getContext (),LD->getValueType (0 ));
5922
+ EVT LdVT = LD->getMemoryVT ();
5923
+ SDLoc dl (LD);
5924
+ assert (LdVT.isVector () && WidenVT.isVector ());
5925
+ assert (LdVT.isScalableVector () == WidenVT.isScalableVector ());
5926
+ assert (LdVT.getVectorElementType () == WidenVT.getVectorElementType ());
5927
+
5928
+ // Load information
5929
+ SDValue Chain = LD->getChain ();
5930
+ SDValue BasePtr = LD->getBasePtr ();
5931
+ MachineMemOperand::Flags MMOFlags = LD->getMemOperand ()->getFlags ();
5932
+ AAMDNodes AAInfo = LD->getAAInfo ();
5933
+
5934
+ TypeSize LdWidth = LdVT.getSizeInBits ();
5935
+ TypeSize WidenWidth = WidenVT.getSizeInBits ();
5936
+ TypeSize WidthDiff = WidenWidth - LdWidth;
5937
+ // Allow wider loads if they are sufficiently aligned to avoid memory faults
5938
+ // and if the original load is simple.
5939
+ unsigned LdAlign =
5940
+ (!LD->isSimple () || LdVT.isScalableVector ()) ? 0 : LD->getAlign ().value ();
5941
+
5942
+ // Find the vector type that can load from.
5943
+ std::optional<EVT> FirstVT =
5944
+ findMemType (DAG, TLI, LdWidth.getKnownMinValue (), WidenVT, LdAlign,
5945
+ WidthDiff.getKnownMinValue ());
5946
+
5947
+ if (!FirstVT)
5948
+ return SDValue ();
5949
+
5950
+ SmallVector<EVT, 8 > MemVTs;
5951
+ TypeSize FirstVTWidth = FirstVT->getSizeInBits ();
5952
+
5953
+ SDValue LdOp = DAG.getAtomic (ISD::ATOMIC_LOAD, dl, *FirstVT, *FirstVT, Chain,
5954
+ BasePtr, LD->getMemOperand ());
5955
+ LdChain.push_back (LdOp.getValue (1 ));
5956
+
5957
+ // Load the element with one instruction.
5958
+ SDValue Result;
5959
+ assert (TypeSize::isKnownLE (LdWidth, FirstVTWidth));
5960
+ if (!FirstVT->isVector ()) {
5961
+ unsigned NumElts =
5962
+ WidenWidth.getFixedValue () / FirstVTWidth.getFixedValue ();
5963
+ EVT NewVecVT = EVT::getVectorVT (*DAG.getContext (), *FirstVT, NumElts);
5964
+ SDValue VecOp = DAG.getNode (ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
5965
+ Result = DAG.getNode (ISD::BITCAST, dl, WidenVT, VecOp);
5966
+ }
5967
+ else if (FirstVT == WidenVT)
5968
+ Result = LdOp;
5969
+ else {
5970
+ // TODO: We don't currently have any tests that exercise this code path.
5971
+ assert (WidenWidth.getFixedValue () % FirstVTWidth.getFixedValue () == 0 );
5972
+ unsigned NumConcat =
5973
+ WidenWidth.getFixedValue () / FirstVTWidth.getFixedValue ();
5974
+ SmallVector<SDValue, 16 > ConcatOps (NumConcat);
5975
+ SDValue UndefVal = DAG.getUNDEF (*FirstVT);
5976
+ ConcatOps[0 ] = LdOp;
5977
+ for (unsigned i = 1 ; i != NumConcat; ++i)
5978
+ ConcatOps[i] = UndefVal;
5979
+ Result = DAG.getNode (ISD::CONCAT_VECTORS, dl, WidenVT, ConcatOps);
5980
+ }
5981
+
5982
+ if (Result) {
5983
+ // Build a factor node to remember the multiple loads are independent and
5984
+ // chain to that.
5985
+ SDValue NewChain =
5986
+ DAG.getNode (ISD::TokenFactor, SDLoc (LD), MVT::Other, LdChain);
5987
+
5988
+ // Modified the chain - switch anything that used the old chain to use
5989
+ // the new one.
5990
+ ReplaceValueWith (SDValue (LD, 1 ), NewChain);
5991
+
5992
+ return Result;
5993
+ }
5994
+
5995
+ report_fatal_error (" Unable to widen atomic vector load" );
5996
+ }
5997
+
5910
5998
SDValue DAGTypeLegalizer::WidenVecRes_LOAD (SDNode *N) {
5911
5999
LoadSDNode *LD = cast<LoadSDNode>(N);
5912
6000
ISD::LoadExtType ExtType = LD->getExtensionType ();
0 commit comments