@@ -4590,6 +4590,9 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
45904590 break ;
45914591 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR (N); break ;
45924592 case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT (N); break ;
4593+ case ISD::ATOMIC_LOAD:
4594+ Res = WidenVecRes_ATOMIC_LOAD (cast<AtomicSDNode>(N));
4595+ break ;
45934596 case ISD::LOAD: Res = WidenVecRes_LOAD (N); break ;
45944597 case ISD::STEP_VECTOR:
45954598 case ISD::SPLAT_VECTOR:
@@ -5978,6 +5981,87 @@ SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
59785981 N->getOperand (1 ), N->getOperand (2 ));
59795982}
59805983
5984+ static SDValue loadElement (SDValue LdOp, EVT FirstVT, EVT WidenVT,
5985+ TypeSize LdWidth, TypeSize FirstVTWidth, SDLoc dl) {
5986+ assert (TypeSize::isKnownLE (LdWidth, FirstVTWidth));
5987+ if (!FirstVT->isVector ()) {
5988+ unsigned NumElts =
5989+ WidenWidth.getFixedValue () / FirstVTWidth.getFixedValue ();
5990+ EVT NewVecVT = EVT::getVectorVT (*DAG.getContext (), *FirstVT, NumElts);
5991+ SDValue VecOp = DAG.getNode (ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
5992+ return DAG.getNode (ISD::BITCAST, dl, WidenVT, VecOp);
5993+ } else if (FirstVT == WidenVT)
5994+ return LdOp;
5995+ else {
5996+ // TODO: We don't currently have any tests that exercise this code path.
5997+ assert (WidenWidth.getFixedValue () % FirstVTWidth.getFixedValue () == 0 );
5998+ unsigned NumConcat =
5999+ WidenWidth.getFixedValue () / FirstVTWidth.getFixedValue ();
6000+ SmallVector<SDValue, 16 > ConcatOps (NumConcat);
6001+ SDValue UndefVal = DAG.getUNDEF (*FirstVT);
6002+ ConcatOps[0 ] = LdOp;
6003+ for (unsigned i = 1 ; i != NumConcat; ++i)
6004+ ConcatOps[i] = UndefVal;
6005+ return DAG.getNode (ISD::CONCAT_VECTORS, dl, WidenVT, ConcatOps);
6006+ }
6007+ }
6008+
6009+ static std::optional<EVT> findMemType (SelectionDAG &DAG,
6010+ const TargetLowering &TLI, unsigned Width,
6011+ EVT WidenVT, unsigned Align,
6012+ unsigned WidenEx);
6013+
6014+ SDValue DAGTypeLegalizer::WidenVecRes_ATOMIC_LOAD (AtomicSDNode *LD) {
6015+ EVT WidenVT =
6016+ TLI.getTypeToTransformTo (*DAG.getContext (),LD->getValueType (0 ));
6017+ EVT LdVT = LD->getMemoryVT ();
6018+ SDLoc dl (LD);
6019+ assert (LdVT.isVector () && WidenVT.isVector ());
6020+ assert (LdVT.isScalableVector () == WidenVT.isScalableVector ());
6021+ assert (LdVT.getVectorElementType () == WidenVT.getVectorElementType ());
6022+
6023+ // Load information
6024+ SDValue Chain = LD->getChain ();
6025+ SDValue BasePtr = LD->getBasePtr ();
6026+ MachineMemOperand::Flags MMOFlags = LD->getMemOperand ()->getFlags ();
6027+ AAMDNodes AAInfo = LD->getAAInfo ();
6028+
6029+ TypeSize LdWidth = LdVT.getSizeInBits ();
6030+ TypeSize WidenWidth = WidenVT.getSizeInBits ();
6031+ TypeSize WidthDiff = WidenWidth - LdWidth;
6032+ // Allow wider loads if they are sufficiently aligned to avoid memory faults
6033+ // and if the original load is simple.
6034+ unsigned LdAlign =
6035+ (!LD->isSimple () || LdVT.isScalableVector ()) ? 0 : LD->getAlign ().value ();
6036+
6037+ // Find the vector type that can load from.
6038+ std::optional<EVT> FirstVT =
6039+ findMemType (DAG, TLI, LdWidth.getKnownMinValue (), WidenVT, LdAlign,
6040+ WidthDiff.getKnownMinValue ());
6041+
6042+ if (!FirstVT)
6043+ return SDValue ();
6044+
6045+ SmallVector<EVT, 8 > MemVTs;
6046+ TypeSize FirstVTWidth = FirstVT->getSizeInBits ();
6047+
6048+ SDValue LdOp = DAG.getAtomic (ISD::ATOMIC_LOAD, dl, *FirstVT, *FirstVT, Chain,
6049+ BasePtr, LD->getMemOperand ());
6050+
6051+ // Load the element with one instruction.
6052+ SDValue Result = loadElement (LdOp, *FirstVT, WidenVT, LdWidth, FirstVTWidth,
6053+ dl);
6054+
6055+ if (Result) {
6056+ // Modified the chain - switch anything that used the old chain to use
6057+ // the new one.
6058+ ReplaceValueWith (SDValue (LD, 1 ), LdOp.getValue (1 ));
6059+ return Result;
6060+ }
6061+
6062+ report_fatal_error (" Unable to widen atomic vector load" );
6063+ }
6064+
59816065SDValue DAGTypeLegalizer::WidenVecRes_LOAD (SDNode *N) {
59826066 LoadSDNode *LD = cast<LoadSDNode>(N);
59836067 ISD::LoadExtType ExtType = LD->getExtensionType ();
@@ -7861,27 +7945,7 @@ SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
78617945
78627946 // Check if we can load the element with one instruction.
78637947 if (MemVTs.empty ()) {
7864- assert (TypeSize::isKnownLE (LdWidth, FirstVTWidth));
7865- if (!FirstVT->isVector ()) {
7866- unsigned NumElts =
7867- WidenWidth.getFixedValue () / FirstVTWidth.getFixedValue ();
7868- EVT NewVecVT = EVT::getVectorVT (*DAG.getContext (), *FirstVT, NumElts);
7869- SDValue VecOp = DAG.getNode (ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
7870- return DAG.getNode (ISD::BITCAST, dl, WidenVT, VecOp);
7871- }
7872- if (FirstVT == WidenVT)
7873- return LdOp;
7874-
7875- // TODO: We don't currently have any tests that exercise this code path.
7876- assert (WidenWidth.getFixedValue () % FirstVTWidth.getFixedValue () == 0 );
7877- unsigned NumConcat =
7878- WidenWidth.getFixedValue () / FirstVTWidth.getFixedValue ();
7879- SmallVector<SDValue, 16 > ConcatOps (NumConcat);
7880- SDValue UndefVal = DAG.getUNDEF (*FirstVT);
7881- ConcatOps[0 ] = LdOp;
7882- for (unsigned i = 1 ; i != NumConcat; ++i)
7883- ConcatOps[i] = UndefVal;
7884- return DAG.getNode (ISD::CONCAT_VECTORS, dl, WidenVT, ConcatOps);
7948+ return loadElement (LdOp, *FirstVT, WidenVT, LdWidth, FirstVTWidth, dl);
78857949 }
78867950
78877951 // Load vector by using multiple loads from largest vector to scalar.
0 commit comments