@@ -1199,6 +1199,34 @@ static Value *foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1,
1199
1199
return Builder.CreateBinOp (Logic.getOpcode (), Cmp0, SubstituteCmp);
1200
1200
}
1201
1201
1202
+ // / Fold (icmp Pred1 V1, C1) & (icmp Pred2 V2, C2)
1203
+ // / or (icmp Pred1 V1, C1) | (icmp Pred2 V2, C2)
1204
+ // / into a single comparison using range-based reasoning.
1205
+ static Value *foldAndOrOfICmpsUsingRanges (
1206
+ ICmpInst::Predicate Pred1, Value *V1, const APInt &C1,
1207
+ ICmpInst::Predicate Pred2, Value *V2, const APInt &C2,
1208
+ IRBuilderBase &Builder, bool IsAnd) {
1209
+ if (V1 != V2)
1210
+ return nullptr ;
1211
+
1212
+ ConstantRange CR1 = ConstantRange::makeExactICmpRegion (Pred1, C1);
1213
+ ConstantRange CR2 = ConstantRange::makeExactICmpRegion (Pred2, C2);
1214
+ Optional<ConstantRange> CR =
1215
+ IsAnd ? CR1.exactIntersectWith (CR2) : CR1.exactUnionWith (CR2);
1216
+ if (!CR)
1217
+ return nullptr ;
1218
+
1219
+ CmpInst::Predicate NewPred;
1220
+ APInt NewC, Offset;
1221
+ CR->getEquivalentICmp (NewPred, NewC, Offset);
1222
+
1223
+ Type *Ty = V1->getType ();
1224
+ Value *NewV = V1;
1225
+ if (Offset != 0 )
1226
+ NewV = Builder.CreateAdd (NewV, ConstantInt::get (Ty, Offset));
1227
+ return Builder.CreateICmp (NewPred, NewV, ConstantInt::get (Ty, NewC));
1228
+ }
1229
+
1202
1230
// / Fold (icmp)&(icmp) if possible.
1203
1231
Value *InstCombinerImpl::foldAndOfICmps (ICmpInst *LHS, ICmpInst *RHS,
1204
1232
BinaryOperator &And) {
@@ -1317,28 +1345,9 @@ Value *InstCombinerImpl::foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS,
1317
1345
}
1318
1346
}
1319
1347
1320
- // From here on, we only handle:
1321
- // (icmp1 A, C1) & (icmp2 A, C2) --> something simpler.
1322
- if (LHS0 != RHS0)
1323
- return nullptr ;
1324
-
1325
- ConstantRange CR1 =
1326
- ConstantRange::makeExactICmpRegion (PredL, LHSC->getValue ());
1327
- ConstantRange CR2 =
1328
- ConstantRange::makeExactICmpRegion (PredR, RHSC->getValue ());
1329
- Optional<ConstantRange> CR = CR1.exactIntersectWith (CR2);
1330
- if (!CR)
1331
- return nullptr ;
1332
-
1333
- CmpInst::Predicate Pred;
1334
- APInt NewRHS, Offset;
1335
- CR->getEquivalentICmp (Pred, NewRHS, Offset);
1336
-
1337
- Type *Ty = LHS0->getType ();
1338
- Value *NewLHS = LHS0;
1339
- if (Offset != 0 )
1340
- NewLHS = Builder.CreateAdd (NewLHS, ConstantInt::get (Ty, Offset));
1341
- return Builder.CreateICmp (Pred, NewLHS, ConstantInt::get (Ty, NewRHS));
1348
+ return foldAndOrOfICmpsUsingRanges (PredL, LHS0, LHSC->getValue (),
1349
+ PredR, RHS0, RHSC->getValue (),
1350
+ Builder, /* IsAnd */ true );
1342
1351
}
1343
1352
1344
1353
Value *InstCombinerImpl::foldLogicOfFCmps (FCmpInst *LHS, FCmpInst *RHS,
@@ -2462,28 +2471,9 @@ Value *InstCombinerImpl::foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
2462
2471
return Builder.CreateICmpULE (LHS0, LHSC);
2463
2472
}
2464
2473
2465
- // From here on, we only handle:
2466
- // (icmp1 A, C1) | (icmp2 A, C2) --> something simpler.
2467
- if (LHS0 != RHS0)
2468
- return nullptr ;
2469
-
2470
- ConstantRange CR1 =
2471
- ConstantRange::makeExactICmpRegion (PredL, LHSC->getValue ());
2472
- ConstantRange CR2 =
2473
- ConstantRange::makeExactICmpRegion (PredR, RHSC->getValue ());
2474
- Optional<ConstantRange> CR = CR1.exactUnionWith (CR2);
2475
- if (!CR)
2476
- return nullptr ;
2477
-
2478
- CmpInst::Predicate Pred;
2479
- APInt NewRHS, Offset;
2480
- CR->getEquivalentICmp (Pred, NewRHS, Offset);
2481
-
2482
- Type *Ty = LHS0->getType ();
2483
- Value *NewLHS = LHS0;
2484
- if (Offset != 0 )
2485
- NewLHS = Builder.CreateAdd (NewLHS, ConstantInt::get (Ty, Offset));
2486
- return Builder.CreateICmp (Pred, NewLHS, ConstantInt::get (Ty, NewRHS));
2474
+ return foldAndOrOfICmpsUsingRanges (PredL, LHS0, LHSC->getValue (),
2475
+ PredR, RHS0, RHSC->getValue (),
2476
+ Builder, /* IsAnd */ false );
2487
2477
}
2488
2478
2489
2479
// FIXME: We use commutative matchers (m_c_*) for some, but not all, matches
0 commit comments