@@ -1120,28 +1120,17 @@ void State::addInfoFor(BasicBlock &BB) {
1120
1120
}
1121
1121
break ;
1122
1122
}
1123
- // Enqueue ssub_with_overflow for simplification.
1123
+ // Enqueue intrinsic for simplification.
1124
1124
case Intrinsic::ssub_with_overflow:
1125
1125
case Intrinsic::ucmp:
1126
1126
case Intrinsic::scmp:
1127
- WorkList.push_back (
1128
- FactOrCheck::getCheck (DT.getNode (&BB), cast<CallInst>(&I)));
1129
- break ;
1130
- // Enqueue the intrinsics to add extra info.
1131
1127
case Intrinsic::umin:
1132
1128
case Intrinsic::umax:
1133
1129
case Intrinsic::smin:
1134
1130
case Intrinsic::smax:
1135
1131
// TODO: handle llvm.abs as well
1136
1132
WorkList.push_back (
1137
1133
FactOrCheck::getCheck (DT.getNode (&BB), cast<CallInst>(&I)));
1138
- // TODO: Check if it is possible to instead only added the min/max facts
1139
- // when simplifying uses of the min/max intrinsics.
1140
- if (!isGuaranteedNotToBePoison (&I))
1141
- break ;
1142
- [[fallthrough]];
1143
- case Intrinsic::abs :
1144
- WorkList.push_back (FactOrCheck::getInstFact (DT.getNode (&BB), &I));
1145
1134
break ;
1146
1135
}
1147
1136
@@ -1385,10 +1374,64 @@ static void generateReproducer(CmpInst *Cond, Module *M,
1385
1374
assert (!verifyFunction (*F, &dbgs ()));
1386
1375
}
1387
1376
1377
+ static void addNonPoisonIntrinsicInstFact (
1378
+ IntrinsicInst *II,
1379
+ function_ref<void (CmpPredicate, Value *, Value *)> AddFact) {
1380
+ Intrinsic::ID IID = II->getIntrinsicID ();
1381
+ switch (IID) {
1382
+ case Intrinsic::umin:
1383
+ case Intrinsic::umax:
1384
+ case Intrinsic::smin:
1385
+ case Intrinsic::smax: {
1386
+ ICmpInst::Predicate Pred =
1387
+ ICmpInst::getNonStrictPredicate (MinMaxIntrinsic::getPredicate (IID));
1388
+ AddFact (Pred, II, II->getArgOperand (0 ));
1389
+ AddFact (Pred, II, II->getArgOperand (1 ));
1390
+ break ;
1391
+ }
1392
+ case Intrinsic::abs : {
1393
+ if (cast<ConstantInt>(II->getArgOperand (1 ))->isOne ())
1394
+ AddFact (CmpInst::ICMP_SGE, II, ConstantInt::get (II->getType (), 0 ));
1395
+ AddFact (CmpInst::ICMP_SGE, II, II->getArgOperand (0 ));
1396
+ break ;
1397
+ }
1398
+ default :
1399
+ break ;
1400
+ }
1401
+ }
1402
+
1403
+ static void
1404
+ removeEntryFromStack (const StackEntry &E, ConstraintInfo &Info,
1405
+ SmallVectorImpl<StackEntry> &DFSInStack,
1406
+ SmallVectorImpl<ReproducerEntry> *ReproducerCondStack) {
1407
+ Info.popLastConstraint (E.IsSigned );
1408
+ // Remove variables in the system that went out of scope.
1409
+ auto &Mapping = Info.getValue2Index (E.IsSigned );
1410
+ for (Value *V : E.ValuesToRelease )
1411
+ Mapping.erase (V);
1412
+ Info.popLastNVariables (E.IsSigned , E.ValuesToRelease .size ());
1413
+ DFSInStack.pop_back ();
1414
+ if (ReproducerCondStack)
1415
+ ReproducerCondStack->pop_back ();
1416
+ }
1417
+
1388
1418
static std::optional<bool > checkCondition (CmpInst::Predicate Pred, Value *A,
1389
1419
Value *B, Instruction *CheckInst,
1390
1420
ConstraintInfo &Info) {
1391
1421
LLVM_DEBUG (dbgs () << " Checking " << *CheckInst << " \n " );
1422
+ SmallVector<StackEntry, 8 > DFSInStack;
1423
+ auto StackRestorer = make_scope_exit ([&]() {
1424
+ while (!DFSInStack.empty ())
1425
+ removeEntryFromStack (DFSInStack.back (), Info, DFSInStack, nullptr );
1426
+ });
1427
+ auto AddFact = [&](CmpPredicate Pred, Value *A, Value *B) {
1428
+ Info.addFact (Pred, A, B, 0 , 0 , DFSInStack);
1429
+ };
1430
+
1431
+ if (auto *II = dyn_cast<IntrinsicInst>(A))
1432
+ addNonPoisonIntrinsicInstFact (II, AddFact);
1433
+ if (auto *II = dyn_cast<IntrinsicInst>(B))
1434
+ addNonPoisonIntrinsicInstFact (II, AddFact);
1392
1435
1393
1436
auto R = Info.getConstraintForSolving (Pred, A, B);
1394
1437
if (R.empty () || !R.isValid (Info)){
@@ -1517,22 +1560,6 @@ static bool checkAndReplaceCmp(CmpIntrinsic *I, ConstraintInfo &Info,
1517
1560
return false ;
1518
1561
}
1519
1562
1520
- static void
1521
- removeEntryFromStack (const StackEntry &E, ConstraintInfo &Info,
1522
- Module *ReproducerModule,
1523
- SmallVectorImpl<ReproducerEntry> &ReproducerCondStack,
1524
- SmallVectorImpl<StackEntry> &DFSInStack) {
1525
- Info.popLastConstraint (E.IsSigned );
1526
- // Remove variables in the system that went out of scope.
1527
- auto &Mapping = Info.getValue2Index (E.IsSigned );
1528
- for (Value *V : E.ValuesToRelease )
1529
- Mapping.erase (V);
1530
- Info.popLastNVariables (E.IsSigned , E.ValuesToRelease .size ());
1531
- DFSInStack.pop_back ();
1532
- if (ReproducerModule)
1533
- ReproducerCondStack.pop_back ();
1534
- }
1535
-
1536
1563
// / Check if either the first condition of an AND or OR is implied by the
1537
1564
// / (negated in case of OR) second condition or vice versa.
1538
1565
static bool checkOrAndOpImpliedByOther (
@@ -1554,8 +1581,8 @@ static bool checkOrAndOpImpliedByOther(
1554
1581
// Remove entries again.
1555
1582
while (OldSize < DFSInStack.size ()) {
1556
1583
StackEntry E = DFSInStack.back ();
1557
- removeEntryFromStack (E, Info, ReproducerModule, ReproducerCondStack ,
1558
- DFSInStack );
1584
+ removeEntryFromStack (E, Info, DFSInStack ,
1585
+ ReproducerModule ? &ReproducerCondStack : nullptr );
1559
1586
}
1560
1587
});
1561
1588
bool IsOr = match (JoinOp, m_LogicalOr ());
@@ -1571,6 +1598,14 @@ static bool checkOrAndOpImpliedByOther(
1571
1598
Pred = CmpInst::getInversePredicate (Pred);
1572
1599
// Optimistically add fact from the other compares in the AND/OR.
1573
1600
Info.addFact (Pred, LHS, RHS, CB.NumIn , CB.NumOut , DFSInStack);
1601
+ auto AddFact = [&](CmpPredicate Pred, Value *A, Value *B) {
1602
+ Info.addFact (Pred, A, B, CB.NumIn , CB.NumOut , DFSInStack);
1603
+ };
1604
+
1605
+ if (auto *II = dyn_cast<IntrinsicInst>(LHS))
1606
+ addNonPoisonIntrinsicInstFact (II, AddFact);
1607
+ if (auto *II = dyn_cast<IntrinsicInst>(RHS))
1608
+ addNonPoisonIntrinsicInstFact (II, AddFact);
1574
1609
continue ;
1575
1610
}
1576
1611
if (IsOr ? match (Val, m_LogicalOr (m_Value (LHS), m_Value (RHS)))
@@ -1807,8 +1842,8 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
1807
1842
Info.getValue2Index (E.IsSigned ));
1808
1843
dbgs () << " \n " ;
1809
1844
});
1810
- removeEntryFromStack (E, Info, ReproducerModule. get (), ReproducerCondStack ,
1811
- DFSInStack );
1845
+ removeEntryFromStack (E, Info, DFSInStack ,
1846
+ ReproducerModule ? &ReproducerCondStack : nullptr );
1812
1847
}
1813
1848
1814
1849
// For a block, check if any CmpInsts become known based on the current set
@@ -1879,25 +1914,6 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
1879
1914
};
1880
1915
1881
1916
CmpPredicate Pred;
1882
- if (!CB.isConditionFact ()) {
1883
- Value *X;
1884
- if (match (CB.Inst , m_Intrinsic<Intrinsic::abs >(m_Value (X)))) {
1885
- // If is_int_min_poison is true then we may assume llvm.abs >= 0.
1886
- if (cast<ConstantInt>(CB.Inst ->getOperand (1 ))->isOne ())
1887
- AddFact (CmpInst::ICMP_SGE, CB.Inst ,
1888
- ConstantInt::get (CB.Inst ->getType (), 0 ));
1889
- AddFact (CmpInst::ICMP_SGE, CB.Inst , X);
1890
- continue ;
1891
- }
1892
-
1893
- if (auto *MinMax = dyn_cast<MinMaxIntrinsic>(CB.Inst )) {
1894
- Pred = ICmpInst::getNonStrictPredicate (MinMax->getPredicate ());
1895
- AddFact (Pred, MinMax, MinMax->getLHS ());
1896
- AddFact (Pred, MinMax, MinMax->getRHS ());
1897
- continue ;
1898
- }
1899
- }
1900
-
1901
1917
Value *A = nullptr , *B = nullptr ;
1902
1918
if (CB.isConditionFact ()) {
1903
1919
Pred = CB.Cond .Pred ;
@@ -1922,6 +1938,11 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
1922
1938
assert (Matched && " Must have an assume intrinsic with a icmp operand" );
1923
1939
}
1924
1940
AddFact (Pred, A, B);
1941
+ // Now both A and B is guaranteed not to be poison.
1942
+ if (auto *II = dyn_cast<IntrinsicInst>(A))
1943
+ addNonPoisonIntrinsicInstFact (II, AddFact);
1944
+ if (auto *II = dyn_cast<IntrinsicInst>(B))
1945
+ addNonPoisonIntrinsicInstFact (II, AddFact);
1925
1946
}
1926
1947
1927
1948
if (ReproducerModule && !ReproducerModule->functions ().empty ()) {
0 commit comments