@@ -1082,8 +1082,14 @@ bool ActivityAnalyzer::isConstantValue(TypeResults &TR, Value *Val) {
1082
1082
if (!arg->hasByValAttr ()) {
1083
1083
bool res = isConstantValue (TR, TmpOrig);
1084
1084
if (res) {
1085
+ if (EnzymePrintActivity)
1086
+ llvm::errs () << " arg const from orig val=" << *Val
1087
+ << " orig=" << *TmpOrig << " \n " ;
1085
1088
InsertConstantValue (TR, Val);
1086
1089
} else {
1090
+ if (EnzymePrintActivity)
1091
+ llvm::errs () << " arg active from orig val=" << *Val
1092
+ << " orig=" << *TmpOrig << " \n " ;
1087
1093
ActiveValues.insert (Val);
1088
1094
}
1089
1095
return res;
@@ -1096,7 +1102,29 @@ bool ActivityAnalyzer::isConstantValue(TypeResults &TR, Value *Val) {
1096
1102
1097
1103
// If our origin is a load of a known inactive (say inactive argument), we
1098
1104
// are also inactive
1099
- if (auto LI = dyn_cast<LoadInst>(TmpOrig)) {
1105
+ if (auto PN = dyn_cast<PHINode>(TmpOrig)) {
1106
+ // Not taking fast path incase phi is recursive.
1107
+ Value *active = nullptr ;
1108
+ for (auto &V : PN->incoming_values ()) {
1109
+ if (!UpHypothesis->isConstantValue (TR, V.get ())) {
1110
+ active = V.get ();
1111
+ break ;
1112
+ }
1113
+ }
1114
+ if (!active) {
1115
+ InsertConstantValue (TR, Val);
1116
+ if (TmpOrig != Val) {
1117
+ InsertConstantValue (TR, TmpOrig);
1118
+ }
1119
+ insertConstantsFrom (TR, *UpHypothesis);
1120
+ return true ;
1121
+ } else {
1122
+ ReEvaluateValueIfInactiveValue[active].insert (Val);
1123
+ if (TmpOrig != Val) {
1124
+ ReEvaluateValueIfInactiveValue[active].insert (TmpOrig);
1125
+ }
1126
+ }
1127
+ } else if (auto LI = dyn_cast<LoadInst>(TmpOrig)) {
1100
1128
1101
1129
if (directions == UP) {
1102
1130
if (isConstantValue (TR, LI->getPointerOperand ())) {
@@ -1277,24 +1305,31 @@ bool ActivityAnalyzer::isConstantValue(TypeResults &TR, Value *Val) {
1277
1305
// A pointer value is active if two things hold:
1278
1306
// an potentially active value is stored into the memory
1279
1307
// memory loaded from the value is used in an active way
1308
+ bool potentiallyActiveStore = false ;
1280
1309
bool potentialStore = false ;
1281
1310
bool potentiallyActiveLoad = false ;
1282
1311
1283
- if (isa<Instruction>(Val) || isa<Argument>(Val)) {
1284
- // These are handled by iterating through all
1285
- } else {
1286
- llvm::errs () << " unknown pointer value type: " << *Val << " \n " ;
1287
- assert (0 && " unknown pointer value type" );
1288
- llvm_unreachable (" unknown pointer value type" );
1289
- }
1290
-
1291
1312
// Assume the value (not instruction) is itself active
1292
1313
// In spite of that can we show that there are either no active stores
1293
1314
// or no active loads
1294
1315
std::shared_ptr<ActivityAnalyzer> Hypothesis =
1295
1316
std::shared_ptr<ActivityAnalyzer>(
1296
1317
new ActivityAnalyzer (*this , directions));
1297
1318
Hypothesis->ActiveValues .insert (Val);
1319
+ if (auto VI = dyn_cast<Instruction>(Val)) {
1320
+ for (auto V : DeducingPointers) {
1321
+ UpHypothesis->InsertConstantValue (TR, V);
1322
+ }
1323
+ if (UpHypothesis->isInstructionInactiveFromOrigin (TR, VI)) {
1324
+ Hypothesis->DeducingPointers .insert (Val);
1325
+ if (EnzymePrintActivity)
1326
+ llvm::errs () << " constant instruction hypothesis: " << *VI << " \n " ;
1327
+ } else {
1328
+ if (EnzymePrintActivity)
1329
+ llvm::errs () << " cannot show constant instruction hypothesis: "
1330
+ << *VI << " \n " ;
1331
+ }
1332
+ }
1298
1333
1299
1334
auto checkActivity = [&](Instruction *I) {
1300
1335
if (notForAnalysis.count (I->getParent ()))
@@ -1469,7 +1504,7 @@ bool ActivityAnalyzer::isConstantValue(TypeResults &TR, Value *Val) {
1469
1504
llvm::errs ()
1470
1505
<< " potential active store via pointer in load: " << *I
1471
1506
<< " of " << *Val << " \n " ;
1472
- potentialStore = true ;
1507
+ potentiallyActiveStore = true ;
1473
1508
}
1474
1509
}
1475
1510
} else if (auto MTI = dyn_cast<MemTransferInst>(I)) {
@@ -1480,7 +1515,7 @@ bool ActivityAnalyzer::isConstantValue(TypeResults &TR, Value *Val) {
1480
1515
llvm::errs ()
1481
1516
<< " potential active store via pointer in memcpy: " << *I
1482
1517
<< " of " << *Val << " \n " ;
1483
- potentialStore = true ;
1518
+ potentiallyActiveStore = true ;
1484
1519
}
1485
1520
}
1486
1521
} else {
@@ -1492,27 +1527,41 @@ bool ActivityAnalyzer::isConstantValue(TypeResults &TR, Value *Val) {
1492
1527
// A load that has as result an active pointer is not an active
1493
1528
// instruction, but does have an active value
1494
1529
if (!Hypothesis->isConstantInstruction (TR, I) ||
1495
- ! Hypothesis->isConstantValue (TR, I)) {
1530
+ (I != Val && ! Hypothesis->isConstantValue (TR, I) )) {
1496
1531
potentiallyActiveLoad = true ;
1497
1532
// If this a potential pointer of pointer AND
1533
+ // double** Val;
1534
+ //
1498
1535
if (TR.query (Val)[{-1 , -1 }].isPossiblePointer ()) {
1499
- // If this instruction either can store into the inner pointer,
1500
- // or could return an active loaded pointer(thus into a
1501
- // potential pointer of pointer
1502
- if (I->mayWriteToMemory () ||
1503
- (!Hypothesis->isConstantValue (TR, I) &&
1536
+ // If this instruction either:
1537
+ // 1) can actively store into the inner pointer, even
1538
+ // if it doesn't store into the outer pointer. Actively
1539
+ // storing into the outer pointer is handled by the isMod
1540
+ // case.
1541
+ // I(double** readonly Val, double activeX) {
1542
+ // double* V0 = Val[0]
1543
+ // V0 = activeX;
1544
+ // }
1545
+ // 2) may return an active pointer loaded from Val
1546
+ // double* I = *Val;
1547
+ // I[0] = active;
1548
+ //
1549
+ if ((I->mayWriteToMemory () &&
1550
+ !Hypothesis->isConstantInstruction (TR, I)) ||
1551
+ (!Hypothesis->DeducingPointers .count (I) &&
1552
+ !Hypothesis->isConstantValue (TR, I) &&
1504
1553
TR.query (I)[{-1 }].isPossiblePointer ())) {
1505
1554
if (EnzymePrintActivity)
1506
1555
llvm::errs () << " potential active store via pointer in "
1507
1556
" unknown inst: "
1508
1557
<< *I << " of " << *Val << " \n " ;
1509
- potentialStore = true ;
1558
+ potentiallyActiveStore = true ;
1510
1559
}
1511
1560
}
1512
1561
}
1513
1562
}
1514
1563
}
1515
- if (! potentialStore && isModSet (AARes)) {
1564
+ if ((!potentiallyActiveStore || ! potentialStore) && isModSet (AARes)) {
1516
1565
if (EnzymePrintActivity)
1517
1566
llvm::errs () << " potential active store: " << *I << " Val=" << *Val
1518
1567
<< " \n " ;
@@ -1522,39 +1571,80 @@ bool ActivityAnalyzer::isConstantValue(TypeResults &TR, Value *Val) {
1522
1571
llvm::errs () << " -- store potential activity: " << (int )cop
1523
1572
<< " - " << *SI << " of "
1524
1573
<< " Val=" << *Val << " \n " ;
1525
- potentialStore |= cop;
1574
+ potentialStore = true ;
1575
+ if (cop)
1576
+ potentiallyActiveStore = true ;
1526
1577
} else if (auto MTI = dyn_cast<MemTransferInst>(I)) {
1527
- potentialStore |=
1528
- !Hypothesis->isConstantValue (TR, MTI->getArgOperand (1 ));
1578
+ bool cop = !Hypothesis->isConstantValue (TR, MTI->getArgOperand (1 ));
1579
+ potentialStore = true ;
1580
+ if (cop)
1581
+ potentiallyActiveStore = true ;
1529
1582
} else {
1530
1583
// Otherwise fallback and check if the instruction is active
1531
1584
// TODO: note that this can be optimized (especially for function
1532
1585
// calls)
1533
- potentialStore |= !Hypothesis->isConstantInstruction (TR, I);
1586
+ auto cop = !Hypothesis->isConstantInstruction (TR, I);
1587
+ if (EnzymePrintActivity)
1588
+ llvm::errs () << " -- unknown store potential activity: " << (int )cop
1589
+ << " - " << *I << " of "
1590
+ << " Val=" << *Val << " \n " ;
1591
+ potentialStore = true ;
1592
+ if (cop)
1593
+ potentiallyActiveStore = true ;
1534
1594
}
1535
1595
}
1536
- if (potentialStore && potentiallyActiveLoad)
1596
+ if (potentiallyActiveStore && potentiallyActiveLoad)
1537
1597
return true ;
1538
1598
return false ;
1539
1599
};
1540
1600
1541
1601
// Search through all the instructions in this function
1542
- // for potential loads / stores of this value
1543
- for (BasicBlock &BB : *TR.getFunction ()) {
1544
- if (notForAnalysis.count (&BB))
1545
- continue ;
1546
- for (Instruction &I : BB) {
1547
- if (checkActivity (&I))
1548
- goto activeLoadAndStore;
1602
+ // for potential loads / stores of this value.
1603
+ //
1604
+ // We can choose to only look at potential follower instructions
1605
+ // if the value is created by the instruction (alloca, noalias)
1606
+ // since no potentially active store to the same location can occur
1607
+ // prior to its creation. Otherwise, check all instructions in the
1608
+ // function as a store to an aliasing location may have occured
1609
+ // prior to the instruction generating the value.
1610
+
1611
+ if (auto VI = dyn_cast<AllocaInst>(Val)) {
1612
+ allFollowersOf (VI, checkActivity);
1613
+ } else if (auto VI = dyn_cast<CallInst>(Val)) {
1614
+ if (VI->hasRetAttr (Attribute::NoAlias))
1615
+ allFollowersOf (VI, checkActivity);
1616
+ else {
1617
+ for (BasicBlock &BB : *TR.getFunction ()) {
1618
+ if (notForAnalysis.count (&BB))
1619
+ continue ;
1620
+ for (Instruction &I : BB) {
1621
+ if (checkActivity (&I))
1622
+ goto activeLoadAndStore;
1623
+ }
1624
+ }
1549
1625
}
1626
+ } else if (isa<Argument>(Val) || isa<Instruction>(Val)) {
1627
+ for (BasicBlock &BB : *TR.getFunction ()) {
1628
+ if (notForAnalysis.count (&BB))
1629
+ continue ;
1630
+ for (Instruction &I : BB) {
1631
+ if (checkActivity (&I))
1632
+ goto activeLoadAndStore;
1633
+ }
1634
+ }
1635
+ } else {
1636
+ llvm::errs () << " unknown pointer value type: " << *Val << " \n " ;
1637
+ assert (0 && " unknown pointer value type" );
1638
+ llvm_unreachable (" unknown pointer value type" );
1550
1639
}
1551
1640
1552
1641
activeLoadAndStore:;
1553
1642
if (EnzymePrintActivity)
1554
1643
llvm::errs () << " </MEMSEARCH" << (int )directions << " >" << *Val
1555
1644
<< " potentiallyActiveLoad=" << potentiallyActiveLoad
1645
+ << " potentiallyActiveStore=" << potentiallyActiveStore
1556
1646
<< " potentialStore=" << potentialStore << " \n " ;
1557
- if (potentiallyActiveLoad && potentialStore ) {
1647
+ if (potentiallyActiveLoad && potentiallyActiveStore ) {
1558
1648
insertAllFrom (TR, *Hypothesis, Val);
1559
1649
// TODO have insertall dependence on this
1560
1650
if (TmpOrig != Val)
@@ -1579,7 +1669,11 @@ bool ActivityAnalyzer::isConstantValue(TypeResults &TR, Value *Val) {
1579
1669
1580
1670
assert (UpHypothesis);
1581
1671
// UpHypothesis.ConstantValues.insert(val);
1582
- UpHypothesis->insertConstantsFrom (TR, *Hypothesis);
1672
+ if (DeducingPointers.size () == 0 )
1673
+ UpHypothesis->insertConstantsFrom (TR, *Hypothesis);
1674
+ for (auto V : DeducingPointers) {
1675
+ UpHypothesis->InsertConstantValue (TR, V);
1676
+ }
1583
1677
assert (directions & UP);
1584
1678
bool ActiveUp = !isa<Argument>(Val) &&
1585
1679
!UpHypothesis->isInstructionInactiveFromOrigin (TR, Val);
@@ -1671,7 +1765,8 @@ bool ActivityAnalyzer::isConstantValue(TypeResults &TR, Value *Val) {
1671
1765
} else {
1672
1766
InsertConstantValue (TR, Val);
1673
1767
insertConstantsFrom (TR, *Hypothesis);
1674
- insertConstantsFrom (TR, *UpHypothesis);
1768
+ if (DeducingPointers.size () == 0 )
1769
+ insertConstantsFrom (TR, *UpHypothesis);
1675
1770
insertConstantsFrom (TR, *DownHypothesis);
1676
1771
return true ;
1677
1772
}
0 commit comments