@@ -2094,6 +2094,49 @@ static bool shouldMergeGEPs(GEPOperator &GEP, GEPOperator &Src) {
2094
2094
return true ;
2095
2095
}
2096
2096
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
+
2097
2140
Instruction *InstCombinerImpl::foldVectorBinop (BinaryOperator &Inst) {
2098
2141
if (!isa<VectorType>(Inst.getType ()))
2099
2142
return nullptr ;
@@ -2213,53 +2256,18 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
2213
2256
// other binops, so they can be folded. It may also enable demanded elements
2214
2257
// transforms.
2215
2258
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 (),
2219
2260
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 () &&
2224
2263
" Shuffle should not change scalar type" );
2225
2264
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>
2231
2265
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 ())
2263
2271
NewC = getSafeVectorConstantForBinop (Opcode, NewC, ConstOp1);
2264
2272
2265
2273
// Op(shuffle(V1, Mask), C) -> shuffle(Op(V1, NewC), Mask)
@@ -2270,27 +2278,6 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
2270
2278
}
2271
2279
}
2272
2280
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
-
2294
2281
// Try to reassociate to sink a splat shuffle after a binary operation.
2295
2282
if (Inst.isAssociative () && Inst.isCommutative ()) {
2296
2283
// Canonicalize shuffle operand as LHS.
0 commit comments