@@ -1298,6 +1298,34 @@ case BuiltinValueKind::id:
1298
1298
return foldFPToIntConversion (BI, Builtin, ResultsInError);
1299
1299
}
1300
1300
1301
+ case BuiltinValueKind::IntToPtr: {
1302
+ if (auto *op = dyn_cast<BuiltinInst>(BI->getOperand (0 ))) {
1303
+ if (auto kind = op->getBuiltinKind ()) {
1304
+ // If we have a single int_to_ptr user and all of the types line up, we
1305
+ // can simplify this instruction.
1306
+ if (*kind == BuiltinValueKind::PtrToInt &&
1307
+ op->getOperand (0 )->getType () == BI->getResult (0 )->getType ()) {
1308
+ return op->getOperand (0 );
1309
+ }
1310
+ }
1311
+ }
1312
+ break ;
1313
+ }
1314
+
1315
+ case BuiltinValueKind::PtrToInt: {
1316
+ if (auto *op = dyn_cast<BuiltinInst>(BI->getOperand (0 ))) {
1317
+ if (auto kind = op->getBuiltinKind ()) {
1318
+ // If we have a single int_to_ptr user and all of the types line up, we
1319
+ // can simplify this instruction.
1320
+ if (*kind == BuiltinValueKind::IntToPtr &&
1321
+ op->getOperand (0 )->getType () == BI->getResult (0 )->getType ()) {
1322
+ return op->getOperand (0 );
1323
+ }
1324
+ }
1325
+ }
1326
+ break ;
1327
+ }
1328
+
1301
1329
case BuiltinValueKind::AssumeNonNegative: {
1302
1330
auto *V = dyn_cast<IntegerLiteralInst>(Args[0 ]);
1303
1331
if (!V)
@@ -1418,7 +1446,8 @@ static bool isApplyOfStringConcat(SILInstruction &I) {
1418
1446
}
1419
1447
1420
1448
static bool isFoldable (SILInstruction *I) {
1421
- return isa<IntegerLiteralInst>(I) || isa<FloatLiteralInst>(I);
1449
+ return isa<IntegerLiteralInst>(I) || isa<FloatLiteralInst>(I) ||
1450
+ isa<StringLiteralInst>(I);
1422
1451
}
1423
1452
1424
1453
bool ConstantFolder::constantFoldStringConcatenation (ApplyInst *AI) {
@@ -1550,6 +1579,29 @@ void ConstantFolder::initializeWorklist(SILFunction &F) {
1550
1579
}
1551
1580
}
1552
1581
1582
+ // / Returns true if \p i is an instruction that has a stateless inverse. We want
1583
+ // / to visit such instructions to eliminate such round-trip unnecessary
1584
+ // / operations.
1585
+ // /
1586
+ // / As an example, consider casts, inttoptr, ptrtoint and friends.
1587
+ static bool isReadNoneAndInvertible (SILInstruction *i) {
1588
+ if (auto *bi = dyn_cast<BuiltinInst>(i)) {
1589
+ // Look for ptrtoint and inttoptr for now.
1590
+ if (auto kind = bi->getBuiltinKind ()) {
1591
+ switch (*kind) {
1592
+ default :
1593
+ return false ;
1594
+ case BuiltinValueKind::PtrToInt:
1595
+ case BuiltinValueKind::IntToPtr:
1596
+ return true ;
1597
+ }
1598
+ }
1599
+ }
1600
+
1601
+ // Be conservative and return false if we do not have any information.
1602
+ return false ;
1603
+ }
1604
+
1553
1605
SILAnalysis::InvalidationKind
1554
1606
ConstantFolder::processWorkList () {
1555
1607
LLVM_DEBUG (llvm::dbgs () << " *** ConstPropagation processing: \n " );
@@ -1721,6 +1773,17 @@ ConstantFolder::processWorkList() {
1721
1773
if (isa<CondFailInst>(User))
1722
1774
FoldedUsers.insert (User);
1723
1775
1776
+ // See if we have an instruction that is read none and has a stateless
1777
+ // inverse. If we do, add it to the worklist so we can check its users
1778
+ // for the inverse operation and see if we can perform constant folding
1779
+ // on the inverse operation. This can eliminate annoying "round trip"s.
1780
+ //
1781
+ // NOTE: We are assuming on purpose that our inverse will be read none,
1782
+ // since otherwise we wouldn't be able to constant fold it this way.
1783
+ if (isReadNoneAndInvertible (User)) {
1784
+ WorkList.insert (User);
1785
+ }
1786
+
1724
1787
// Initialize ResultsInError as a None optional.
1725
1788
//
1726
1789
// We are essentially using this optional to represent 3 states: true,
0 commit comments