@@ -1876,6 +1876,51 @@ static bool isConstantOrUndefBUILD_VECTOR(const BuildVectorSDNode *Op) {
18761876 return false ;
18771877}
18781878
1879+ // Lower BUILD_VECTOR as broadcast load (if possible).
1880+ // For example:
1881+ // %a = load i8, ptr %ptr
1882+ // %b = build_vector %a, %a, %a, %a
1883+ // is lowered to :
1884+ // (VLDREPL_B $a0, 0)
1885+ static SDValue lowerBUILD_VECTORAsBroadCastLoad (BuildVectorSDNode *BVOp,
1886+ const SDLoc &DL,
1887+ SelectionDAG &DAG) {
1888+ MVT VT = BVOp->getSimpleValueType (0 );
1889+ int NumOps = BVOp->getNumOperands ();
1890+
1891+ assert ((VT.is128BitVector () || VT.is256BitVector ()) &&
1892+ " Unsupported vector type for broadcast." );
1893+
1894+ SDValue IdentitySrc;
1895+ bool IsIdeneity = true ;
1896+
1897+ for (int i = 0 ; i != NumOps; i++) {
1898+ SDValue Op = BVOp->getOperand (i);
1899+ if (Op.getOpcode () != ISD::LOAD || (IdentitySrc && Op != IdentitySrc)) {
1900+ IsIdeneity = false ;
1901+ break ;
1902+ }
1903+ IdentitySrc = BVOp->getOperand (0 );
1904+ }
1905+
1906+ // make sure that this load is valid and only has one user.
1907+ if (!IdentitySrc || !BVOp->isOnlyUserOf (IdentitySrc.getNode ()))
1908+ return SDValue ();
1909+
1910+ if (IsIdeneity) {
1911+ auto *LN = cast<LoadSDNode>(IdentitySrc);
1912+ SDVTList Tys =
1913+ LN->isIndexed ()
1914+ ? DAG.getVTList (VT, LN->getBasePtr ().getValueType (), MVT::Other)
1915+ : DAG.getVTList (VT, MVT::Other);
1916+ SDValue Ops[] = {LN->getChain (), LN->getBasePtr (), LN->getOffset ()};
1917+ SDValue BCast = DAG.getNode (LoongArchISD::VLDREPL, DL, Tys, Ops);
1918+ DAG.ReplaceAllUsesOfValueWith (SDValue (LN, 1 ), BCast.getValue (1 ));
1919+ return BCast;
1920+ }
1921+ return SDValue ();
1922+ }
1923+
18791924SDValue LoongArchTargetLowering::lowerBUILD_VECTOR (SDValue Op,
18801925 SelectionDAG &DAG) const {
18811926 BuildVectorSDNode *Node = cast<BuildVectorSDNode>(Op);
@@ -1891,6 +1936,9 @@ SDValue LoongArchTargetLowering::lowerBUILD_VECTOR(SDValue Op,
18911936 (!Subtarget.hasExtLASX () || !Is256Vec))
18921937 return SDValue ();
18931938
1939+ if (SDValue Result = lowerBUILD_VECTORAsBroadCastLoad (Node, DL, DAG))
1940+ return Result;
1941+
18941942 if (Node->isConstantSplat (SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
18951943 /* MinSplatBits=*/ 8 ) &&
18961944 SplatBitSize <= 64 ) {
@@ -5326,6 +5374,7 @@ const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const {
53265374 NODE_NAME_CASE (VSRLI)
53275375 NODE_NAME_CASE (VBSLL)
53285376 NODE_NAME_CASE (VBSRL)
5377+ NODE_NAME_CASE (VLDREPL)
53295378 }
53305379#undef NODE_NAME_CASE
53315380 return nullptr ;
0 commit comments