|
23 | 23 | #include "llvm/Analysis/ScalarEvolution.h"
|
24 | 24 | #include "llvm/Analysis/ScalarEvolutionExpressions.h"
|
25 | 25 | #include "llvm/Analysis/ValueTracking.h"
|
| 26 | +#include "llvm/IR/CmpPredicate.h" |
26 | 27 | #include "llvm/IR/DataLayout.h"
|
27 | 28 | #include "llvm/IR/Dominators.h"
|
28 | 29 | #include "llvm/IR/Function.h"
|
@@ -1083,6 +1084,44 @@ void State::addInfoForInductions(BasicBlock &BB) {
|
1083 | 1084 | }
|
1084 | 1085 | }
|
1085 | 1086 |
|
| 1087 | +static void addNonPoisonIntrinsicInstFact( |
| 1088 | + IntrinsicInst *II, |
| 1089 | + function_ref<void(CmpPredicate, Value *, Value *)> AddFact) { |
| 1090 | + Intrinsic::ID IID = II->getIntrinsicID(); |
| 1091 | + switch (IID) { |
| 1092 | + case Intrinsic::umin: |
| 1093 | + case Intrinsic::umax: |
| 1094 | + case Intrinsic::smin: |
| 1095 | + case Intrinsic::smax: { |
| 1096 | + ICmpInst::Predicate Pred = |
| 1097 | + ICmpInst::getNonStrictPredicate(MinMaxIntrinsic::getPredicate(IID)); |
| 1098 | + AddFact(Pred, II, II->getArgOperand(0)); |
| 1099 | + AddFact(Pred, II, II->getArgOperand(1)); |
| 1100 | + break; |
| 1101 | + } |
| 1102 | + case Intrinsic::abs: { |
| 1103 | + if (cast<ConstantInt>(II->getArgOperand(1))->isOne()) |
| 1104 | + AddFact(CmpInst::ICMP_SGE, II, ConstantInt::get(II->getType(), 0)); |
| 1105 | + AddFact(CmpInst::ICMP_SGE, II, II->getArgOperand(0)); |
| 1106 | + break; |
| 1107 | + } |
| 1108 | + default: |
| 1109 | + break; |
| 1110 | + } |
| 1111 | +} |
| 1112 | + |
| 1113 | +static void addNonPoisonValueFactRecursive( |
| 1114 | + Value *V, function_ref<void(CmpPredicate, Value *, Value *)> AddFact) { |
| 1115 | + if (auto *II = dyn_cast<IntrinsicInst>(V)) |
| 1116 | + addNonPoisonIntrinsicInstFact(II, AddFact); |
| 1117 | + |
| 1118 | + if (auto *I = dyn_cast<Instruction>(V)) { |
| 1119 | + for (auto &Op : I->operands()) |
| 1120 | + if (impliesPoison(Op, V)) |
| 1121 | + addNonPoisonValueFactRecursive(Op.get(), AddFact); |
| 1122 | + } |
| 1123 | +} |
| 1124 | + |
1086 | 1125 | void State::addInfoFor(BasicBlock &BB) {
|
1087 | 1126 | addInfoForInductions(BB);
|
1088 | 1127 |
|
@@ -1134,6 +1173,18 @@ void State::addInfoFor(BasicBlock &BB) {
|
1134 | 1173 | break;
|
1135 | 1174 | }
|
1136 | 1175 |
|
| 1176 | + if (GuaranteedToExecute) { |
| 1177 | + auto AddFact = [&](CmpPredicate Pred, Value *A, Value *B) { |
| 1178 | + WorkList.emplace_back( |
| 1179 | + FactOrCheck::getConditionFact(DT.getNode(&BB), Pred, A, B)); |
| 1180 | + }; |
| 1181 | + |
| 1182 | + handleGuaranteedWellDefinedOps(&I, [&](const Value *Op) { |
| 1183 | + addNonPoisonValueFactRecursive(const_cast<Value *>(Op), AddFact); |
| 1184 | + return false; |
| 1185 | + }); |
| 1186 | + } |
| 1187 | + |
1137 | 1188 | GuaranteedToExecute &= isGuaranteedToTransferExecutionToSuccessor(&I);
|
1138 | 1189 | }
|
1139 | 1190 |
|
@@ -1374,32 +1425,6 @@ static void generateReproducer(CmpInst *Cond, Module *M,
|
1374 | 1425 | assert(!verifyFunction(*F, &dbgs()));
|
1375 | 1426 | }
|
1376 | 1427 |
|
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 | 1428 | static void
|
1404 | 1429 | removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info,
|
1405 | 1430 | SmallVectorImpl<StackEntry> &DFSInStack,
|
@@ -1428,10 +1453,8 @@ static std::optional<bool> checkCondition(CmpInst::Predicate Pred, Value *A,
|
1428 | 1453 | Info.addFact(Pred, A, B, 0, 0, DFSInStack);
|
1429 | 1454 | };
|
1430 | 1455 |
|
1431 |
| - if (auto *II = dyn_cast<IntrinsicInst>(A)) |
1432 |
| - addNonPoisonIntrinsicInstFact(II, AddFact); |
1433 |
| - if (auto *II = dyn_cast<IntrinsicInst>(B)) |
1434 |
| - addNonPoisonIntrinsicInstFact(II, AddFact); |
| 1456 | + addNonPoisonValueFactRecursive(A, AddFact); |
| 1457 | + addNonPoisonValueFactRecursive(B, AddFact); |
1435 | 1458 |
|
1436 | 1459 | auto R = Info.getConstraintForSolving(Pred, A, B);
|
1437 | 1460 | if (R.empty() || !R.isValid(Info)){
|
@@ -1602,10 +1625,8 @@ static bool checkOrAndOpImpliedByOther(
|
1602 | 1625 | Info.addFact(Pred, A, B, CB.NumIn, CB.NumOut, DFSInStack);
|
1603 | 1626 | };
|
1604 | 1627 |
|
1605 |
| - if (auto *II = dyn_cast<IntrinsicInst>(LHS)) |
1606 |
| - addNonPoisonIntrinsicInstFact(II, AddFact); |
1607 |
| - if (auto *II = dyn_cast<IntrinsicInst>(RHS)) |
1608 |
| - addNonPoisonIntrinsicInstFact(II, AddFact); |
| 1628 | + addNonPoisonValueFactRecursive(LHS, AddFact); |
| 1629 | + addNonPoisonValueFactRecursive(RHS, AddFact); |
1609 | 1630 | continue;
|
1610 | 1631 | }
|
1611 | 1632 | if (IsOr ? match(Val, m_LogicalOr(m_Value(LHS), m_Value(RHS)))
|
@@ -1939,10 +1960,8 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
|
1939 | 1960 | }
|
1940 | 1961 | AddFact(Pred, A, B);
|
1941 | 1962 | // 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); |
| 1963 | + addNonPoisonValueFactRecursive(A, AddFact); |
| 1964 | + addNonPoisonValueFactRecursive(B, AddFact); |
1946 | 1965 | }
|
1947 | 1966 |
|
1948 | 1967 | if (ReproducerModule && !ReproducerModule->functions().empty()) {
|
|
0 commit comments