@@ -2094,6 +2094,49 @@ static bool shouldMergeGEPs(GEPOperator &GEP, GEPOperator &Src) {
20942094 return true ;
20952095}
20962096
2097+ // / Find a constant NewC that has property:
2098+ // / shuffle(NewC, ShMask) = C
2099+ // / Returns nullptr if such a constant does not exist e.g. ShMask=<0,0> C=<1,2>
2100+ // /
2101+ // / A 1-to-1 mapping is not required. Example:
2102+ // / ShMask = <1,1,2,2> and C = <5,5,6,6> --> NewC = <poison,5,6,poison>
2103+ static Constant *unshuffleConstant (ArrayRef<int > ShMask, Constant *C,
2104+ VectorType *NewCTy) {
2105+ if (isa<ScalableVectorType>(NewCTy)) {
2106+ Constant *Splat = C->getSplatValue ();
2107+ if (!Splat)
2108+ return nullptr ;
2109+ return ConstantVector::getSplat (NewCTy->getElementCount (), Splat);
2110+ }
2111+
2112+ if (cast<FixedVectorType>(NewCTy)->getNumElements () >
2113+ cast<FixedVectorType>(C->getType ())->getNumElements ())
2114+ return nullptr ;
2115+
2116+ unsigned NewCNumElts = cast<FixedVectorType>(NewCTy)->getNumElements ();
2117+ PoisonValue *PoisonScalar = PoisonValue::get (C->getType ()->getScalarType ());
2118+ SmallVector<Constant *, 16 > NewVecC (NewCNumElts, PoisonScalar);
2119+ unsigned NumElts = cast<FixedVectorType>(C->getType ())->getNumElements ();
2120+ for (unsigned I = 0 ; I < NumElts; ++I) {
2121+ Constant *CElt = C->getAggregateElement (I);
2122+ if (ShMask[I] >= 0 ) {
2123+ assert (ShMask[I] < (int )NumElts && " Not expecting narrowing shuffle" );
2124+ Constant *NewCElt = NewVecC[ShMask[I]];
2125+ // Bail out if:
2126+ // 1. The constant vector contains a constant expression.
2127+ // 2. The shuffle needs an element of the constant vector that can't
2128+ // be mapped to a new constant vector.
2129+ // 3. This is a widening shuffle that copies elements of V1 into the
2130+ // extended elements (extending with poison is allowed).
2131+ if (!CElt || (!isa<PoisonValue>(NewCElt) && NewCElt != CElt) ||
2132+ I >= NewCNumElts)
2133+ return nullptr ;
2134+ NewVecC[ShMask[I]] = CElt;
2135+ }
2136+ }
2137+ return ConstantVector::get (NewVecC);
2138+ }
2139+
20972140Instruction *InstCombinerImpl::foldVectorBinop (BinaryOperator &Inst) {
20982141 if (!isa<VectorType>(Inst.getType ()))
20992142 return nullptr ;
@@ -2213,53 +2256,18 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
22132256 // other binops, so they can be folded. It may also enable demanded elements
22142257 // transforms.
22152258 Constant *C;
2216- auto *InstVTy = dyn_cast<FixedVectorType>(Inst.getType ());
2217- if (InstVTy &&
2218- match (&Inst, m_c_BinOp (m_OneUse (m_Shuffle (m_Value (V1), m_Poison (),
2259+ if (match (&Inst, m_c_BinOp (m_OneUse (m_Shuffle (m_Value (V1), m_Poison (),
22192260 m_Mask (Mask))),
2220- m_ImmConstant (C))) &&
2221- cast<FixedVectorType>(V1->getType ())->getNumElements () <=
2222- InstVTy->getNumElements ()) {
2223- assert (InstVTy->getScalarType () == V1->getType ()->getScalarType () &&
2261+ m_ImmConstant (C)))) {
2262+ assert (Inst.getType ()->getScalarType () == V1->getType ()->getScalarType () &&
22242263 " Shuffle should not change scalar type" );
22252264
2226- // Find constant NewC that has property:
2227- // shuffle(NewC, ShMask) = C
2228- // If such constant does not exist (example: ShMask=<0,0> and C=<1,2>)
2229- // reorder is not possible. A 1-to-1 mapping is not required. Example:
2230- // ShMask = <1,1,2,2> and C = <5,5,6,6> --> NewC = <undef,5,6,undef>
22312265 bool ConstOp1 = isa<Constant>(RHS);
2232- ArrayRef<int > ShMask = Mask;
2233- unsigned SrcVecNumElts =
2234- cast<FixedVectorType>(V1->getType ())->getNumElements ();
2235- PoisonValue *PoisonScalar = PoisonValue::get (C->getType ()->getScalarType ());
2236- SmallVector<Constant *, 16 > NewVecC (SrcVecNumElts, PoisonScalar);
2237- bool MayChange = true ;
2238- unsigned NumElts = InstVTy->getNumElements ();
2239- for (unsigned I = 0 ; I < NumElts; ++I) {
2240- Constant *CElt = C->getAggregateElement (I);
2241- if (ShMask[I] >= 0 ) {
2242- assert (ShMask[I] < (int )NumElts && " Not expecting narrowing shuffle" );
2243- Constant *NewCElt = NewVecC[ShMask[I]];
2244- // Bail out if:
2245- // 1. The constant vector contains a constant expression.
2246- // 2. The shuffle needs an element of the constant vector that can't
2247- // be mapped to a new constant vector.
2248- // 3. This is a widening shuffle that copies elements of V1 into the
2249- // extended elements (extending with poison is allowed).
2250- if (!CElt || (!isa<PoisonValue>(NewCElt) && NewCElt != CElt) ||
2251- I >= SrcVecNumElts) {
2252- MayChange = false ;
2253- break ;
2254- }
2255- NewVecC[ShMask[I]] = CElt;
2256- }
2257- }
2258- if (MayChange) {
2259- Constant *NewC = ConstantVector::get (NewVecC);
2260- // Lanes of NewC not used by the shuffle will be poison which will cause
2261- // UB for div/rem. Mask them with a safe constant.
2262- if (Inst.isIntDivRem ())
2266+ if (Constant *NewC =
2267+ unshuffleConstant (Mask, C, cast<VectorType>(V1->getType ()))) {
2268+ // For fixed vectors, lanes of NewC not used by the shuffle will be poison
2269+ // which will cause UB for div/rem. Mask them with a safe constant.
2270+ if (isa<FixedVectorType>(V1->getType ()) && Inst.isIntDivRem ())
22632271 NewC = getSafeVectorConstantForBinop (Opcode, NewC, ConstOp1);
22642272
22652273 // Op(shuffle(V1, Mask), C) -> shuffle(Op(V1, NewC), Mask)
@@ -2270,27 +2278,6 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
22702278 }
22712279 }
22722280
2273- // Similar to the combine above, but handles the case for scalable vectors
2274- // where both shuffle(V1, 0) and C are splats.
2275- //
2276- // Op(shuffle(V1, 0), (splat C)) -> shuffle(Op(V1, (splat C)), 0)
2277- if (isa<ScalableVectorType>(Inst.getType ()) &&
2278- match (&Inst, m_c_BinOp (m_OneUse (m_Shuffle (m_Value (V1), m_Poison (),
2279- m_ZeroMask ())),
2280- m_ImmConstant (C)))) {
2281- if (Constant *Splat = C->getSplatValue ()) {
2282- bool ConstOp1 = isa<Constant>(RHS);
2283- VectorType *V1Ty = cast<VectorType>(V1->getType ());
2284- Constant *NewC = ConstantVector::getSplat (V1Ty->getElementCount (), Splat);
2285-
2286- Value *NewLHS = ConstOp1 ? V1 : NewC;
2287- Value *NewRHS = ConstOp1 ? NewC : V1;
2288- VectorType *VTy = cast<VectorType>(Inst.getType ());
2289- SmallVector<int > Mask (VTy->getElementCount ().getKnownMinValue (), 0 );
2290- return createBinOpShuffle (NewLHS, NewRHS, Mask);
2291- }
2292- }
2293-
22942281 // Try to reassociate to sink a splat shuffle after a binary operation.
22952282 if (Inst.isAssociative () && Inst.isCommutative ()) {
22962283 // Canonicalize shuffle operand as LHS.
0 commit comments