4343#include " llvm/Support/KnownBits.h"
4444#include " llvm/Transforms/InstCombine/InstCombiner.h"
4545#include < cassert>
46+ #include < optional>
4647#include < utility>
4748
4849#define DEBUG_TYPE " instcombine"
@@ -1401,9 +1402,43 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel,
14011402 return nullptr ;
14021403 }
14031404
1405+ std::optional<bool > CanReplacePointersIfEqualCache[2 ] = {std::nullopt ,
1406+ std::nullopt };
1407+ std::optional<bool > ShareSameUnderlyingObject = std::nullopt ;
1408+ auto CanReplacePointersIfEqual = [&](Value *From, Value *To,
1409+ std::optional<bool > &Cache) -> bool {
1410+ if (Cache.has_value ())
1411+ return *Cache;
1412+
1413+ assert (From->getType () == To->getType () &&
1414+ " values must have matching types" );
1415+ // Not a pointer, just return true.
1416+ if (!From->getType ()->isPointerTy ()) {
1417+ Cache = true ;
1418+ return true ;
1419+ }
1420+
1421+ if (isa<ConstantPointerNull>(To)) {
1422+ Cache = true ;
1423+ return true ;
1424+ }
1425+ if (isa<Constant>(To) &&
1426+ isDereferenceablePointer (To, Type::getInt8Ty (To->getContext ()), DL)) {
1427+ Cache = true ;
1428+ return true ;
1429+ }
1430+
1431+ if (!ShareSameUnderlyingObject.has_value ())
1432+ ShareSameUnderlyingObject = getUnderlyingObjectAggressive (From) ==
1433+ getUnderlyingObjectAggressive (To);
1434+
1435+ Cache = *ShareSameUnderlyingObject;
1436+ return *ShareSameUnderlyingObject;
1437+ };
1438+
14041439 Value *CmpLHS = Cmp.getOperand (0 ), *CmpRHS = Cmp.getOperand (1 );
1405- auto ReplaceOldOpWithNewOp = [&](Value *OldOp,
1406- Value *NewOp ) -> Instruction * {
1440+ auto ReplaceOldOpWithNewOp = [&](Value *OldOp, Value *NewOp,
1441+ uint32_t Direction ) -> Instruction * {
14071442 // In X == Y ? f(X) : Z, try to evaluate f(Y) and replace the operand.
14081443 // Take care to avoid replacing X == Y ? X : Z with X == Y ? Y : Z, as that
14091444 // would lead to an infinite replacement cycle.
@@ -1412,7 +1447,8 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel,
14121447 // in the cmp and in f(Y).
14131448 if (TrueVal == OldOp && (isa<Constant>(OldOp) || !isa<Constant>(NewOp)))
14141449 return nullptr ;
1415- if (!canReplacePointersIfEqual (OldOp, NewOp, DL))
1450+ if (!CanReplacePointersIfEqual (OldOp, NewOp,
1451+ CanReplacePointersIfEqualCache[Direction]))
14161452 return nullptr ;
14171453
14181454 if (Value *V = simplifyWithOpReplaced (TrueVal, OldOp, NewOp, SQ,
@@ -1451,9 +1487,9 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel,
14511487 return nullptr ;
14521488 };
14531489
1454- if (Instruction *R = ReplaceOldOpWithNewOp (CmpLHS, CmpRHS))
1490+ if (Instruction *R = ReplaceOldOpWithNewOp (CmpLHS, CmpRHS, 0 ))
14551491 return R;
1456- if (Instruction *R = ReplaceOldOpWithNewOp (CmpRHS, CmpLHS))
1492+ if (Instruction *R = ReplaceOldOpWithNewOp (CmpRHS, CmpLHS, 1 ))
14571493 return R;
14581494
14591495 auto *FalseInst = dyn_cast<Instruction>(FalseVal);
@@ -1469,11 +1505,13 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel,
14691505 // Example:
14701506 // (X == 42) ? 43 : (X + 1) --> (X == 42) ? (X + 1) : (X + 1) --> X + 1
14711507 SmallVector<Instruction *> DropFlags;
1472- if ((canReplacePointersIfEqual (CmpLHS, CmpRHS, DL) &&
1508+ if ((CanReplacePointersIfEqual (CmpLHS, CmpRHS,
1509+ CanReplacePointersIfEqualCache[0 ]) &&
14731510 simplifyWithOpReplaced (FalseVal, CmpLHS, CmpRHS, SQ,
14741511 /* AllowRefinement */ false ,
14751512 &DropFlags) == TrueVal) ||
1476- (canReplacePointersIfEqual (CmpRHS, CmpLHS, DL) &&
1513+ (CanReplacePointersIfEqual (CmpRHS, CmpLHS,
1514+ CanReplacePointersIfEqualCache[1 ]) &&
14771515 simplifyWithOpReplaced (FalseVal, CmpRHS, CmpLHS, SQ,
14781516 /* AllowRefinement */ false ,
14791517 &DropFlags) == TrueVal)) {
0 commit comments