@@ -1257,6 +1257,74 @@ static Instruction *foldToUnsignedSaturatedAdd(BinaryOperator &I) {
1257
1257
return nullptr ;
1258
1258
}
1259
1259
1260
+ static Value *foldCeilIdioms (BinaryOperator &I, InstCombinerImpl &IC) {
1261
+ assert (I.getOpcode () == Instruction::Add && " Expecting add instruction." );
1262
+ Value *A, *B;
1263
+ auto &ICB = IC.Builder ;
1264
+
1265
+ // Fold the log2 ceil idiom:
1266
+ // zext (ctpop(A) >u/!= 1) + (ctlz (A, true) ^ (BW - 1))
1267
+ // -> BW - ctlz (A - 1, false)
1268
+ const APInt *XorC;
1269
+ CmpPredicate Pred;
1270
+ if (match (&I,
1271
+ m_c_Add (
1272
+ m_ZExt (m_ICmp (Pred, m_Intrinsic<Intrinsic::ctpop>(m_Value (A)),
1273
+ m_One ())),
1274
+ m_OneUse (m_ZExtOrSelf (m_OneUse (m_Xor (
1275
+ m_OneUse (m_TruncOrSelf (m_OneUse (
1276
+ m_Intrinsic<Intrinsic::ctlz>(m_Deferred (A), m_One ())))),
1277
+ m_APInt (XorC))))))) &&
1278
+ (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_NE) &&
1279
+ *XorC == A->getType ()->getScalarSizeInBits () - 1 ) {
1280
+ Value *Sub = ICB.CreateAdd (A, Constant::getAllOnesValue (A->getType ()));
1281
+ Value *Ctlz = ICB.CreateIntrinsic (Intrinsic::ctlz, {A->getType ()},
1282
+ {Sub, ICB.getFalse ()});
1283
+ Value *Ret = ICB.CreateSub (
1284
+ ConstantInt::get (A->getType (), A->getType ()->getScalarSizeInBits ()),
1285
+ Ctlz, " " , /* HasNUW*/ true , /* HasNSW*/ true );
1286
+ return ICB.CreateZExtOrTrunc (Ret, I.getType ());
1287
+ }
1288
+
1289
+ // Fold the ceil division idiom:
1290
+ // add (udiv (sub A, Bias), B), Bias
1291
+ // -> udiv (add A, B - 1), B)
1292
+ // with Bias = A != 0; A + B not to overflow
1293
+ auto MatchDivision = [&IC](Instruction *Div, Value *&DivOp0, Value *&DivOp1) {
1294
+ if (match (Div, m_UDiv (m_Value (DivOp0), m_Value (DivOp1))))
1295
+ return true ;
1296
+
1297
+ Value *N;
1298
+ if (match (Div, m_LShr (m_Value (DivOp0), m_Value (N))) &&
1299
+ match (N,
1300
+ m_Sub (m_SpecificInt (Div->getType ()->getScalarSizeInBits () - 1 ),
1301
+ m_Intrinsic<Intrinsic::ctlz>(m_Value (DivOp1), m_Zero ()))) &&
1302
+ IC.isKnownToBeAPowerOfTwo (DivOp1, /* OrZero*/ false , 0 , Div))
1303
+ return true ;
1304
+
1305
+ return false ;
1306
+ };
1307
+
1308
+ Instruction *Div;
1309
+ Value *Bias, *Sub;
1310
+ if (match (&I, m_c_Add (m_Instruction (Div), m_Value (Bias))) &&
1311
+ MatchDivision (Div, Sub, B) &&
1312
+ match (Sub, m_Sub (m_Value (A), m_Value (Bias))) &&
1313
+ match (Bias, m_ZExt (m_SpecificICmp (ICmpInst::ICMP_NE, m_Specific (A),
1314
+ m_ZeroInt ()))) &&
1315
+ Bias->hasNUses (2 )) {
1316
+ WithCache<const Value *> LHSCache (A), RHSCache (B);
1317
+ auto OR = IC.computeOverflowForUnsignedAdd (LHSCache, RHSCache, &I);
1318
+ if (OR == OverflowResult::NeverOverflows) {
1319
+ auto *BMinusOne =
1320
+ ICB.CreateAdd (B, Constant::getAllOnesValue (I.getType ()));
1321
+ return ICB.CreateUDiv (ICB.CreateAdd (A, BMinusOne), B);
1322
+ }
1323
+ }
1324
+
1325
+ return nullptr ;
1326
+ }
1327
+
1260
1328
// Transform:
1261
1329
// (add A, (shl (neg B), Y))
1262
1330
// -> (sub A, (shl B, Y))
@@ -1838,30 +1906,8 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
1838
1906
I, Builder.CreateIntrinsic (Intrinsic::ctpop, {I.getType ()},
1839
1907
{Builder.CreateOr (A, B)}));
1840
1908
1841
- // Fold the log2_ceil idiom:
1842
- // zext(ctpop(A) >u/!= 1) + (ctlz(A, true) ^ (BW - 1))
1843
- // -->
1844
- // BW - ctlz(A - 1, false)
1845
- const APInt *XorC;
1846
- CmpPredicate Pred;
1847
- if (match (&I,
1848
- m_c_Add (
1849
- m_ZExt (m_ICmp (Pred, m_Intrinsic<Intrinsic::ctpop>(m_Value (A)),
1850
- m_One ())),
1851
- m_OneUse (m_ZExtOrSelf (m_OneUse (m_Xor (
1852
- m_OneUse (m_TruncOrSelf (m_OneUse (
1853
- m_Intrinsic<Intrinsic::ctlz>(m_Deferred (A), m_One ())))),
1854
- m_APInt (XorC))))))) &&
1855
- (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_NE) &&
1856
- *XorC == A->getType ()->getScalarSizeInBits () - 1 ) {
1857
- Value *Sub = Builder.CreateAdd (A, Constant::getAllOnesValue (A->getType ()));
1858
- Value *Ctlz = Builder.CreateIntrinsic (Intrinsic::ctlz, {A->getType ()},
1859
- {Sub, Builder.getFalse ()});
1860
- Value *Ret = Builder.CreateSub (
1861
- ConstantInt::get (A->getType (), A->getType ()->getScalarSizeInBits ()),
1862
- Ctlz, " " , /* HasNUW*/ true , /* HasNSW*/ true );
1863
- return replaceInstUsesWith (I, Builder.CreateZExtOrTrunc (Ret, I.getType ()));
1864
- }
1909
+ if (Value *V = foldCeilIdioms (I, *this ))
1910
+ return replaceInstUsesWith (I, V);
1865
1911
1866
1912
if (Instruction *Res = foldSquareSumInt (I))
1867
1913
return Res;
0 commit comments