Skip to content

Fix CSE isEqual and HashVisitor for escaped values #63791

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 40 additions & 13 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
NonTypeDependentOperandValueRange getNonTypeDependentOperandValues() const;

TransformedOperandValueRange
getOperandValues(std::function<SILValue(SILValue)> transformFn,
getOperandValues(std::function<SILValue(const Operand *)> transformFn,
bool skipTypeDependentOperands) const;

SILValue getOperand(unsigned Num) const {
Expand Down Expand Up @@ -720,8 +720,9 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
/// Returns true if the given instruction is completely identical to RHS,
/// using \p opEqual to compare operands.
///
template <typename OpCmp>
bool isIdenticalTo(const SILInstruction *RHS, OpCmp &&opEqual) const {
bool
isIdenticalTo(const SILInstruction *RHS,
llvm::function_ref<bool(SILValue, SILValue)> opEqual) const {
// Quick check if both instructions have the same kind, number of operands,
// and types. This should filter out most cases.
if (getKind() != RHS->getKind() ||
Expand All @@ -742,6 +743,29 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
return hasIdenticalState(RHS);
}

bool isIdenticalTo(const SILInstruction *RHS,
llvm::function_ref<bool(const Operand *, const Operand *)>
opEqual) const {
// Quick check if both instructions have the same kind, number of operands,
Copy link
Contributor Author

@meg-gupta meg-gupta Feb 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Refactor code common to bool isIdenticalTo(const SILInstruction *RHS, std::function<bool(SILValue, SILValue)> opEqual) const

// and types. This should filter out most cases.
if (getKind() != RHS->getKind() ||
getNumOperands() != RHS->getNumOperands()) {
return false;
}

if (!getResults().hasSameTypes(RHS->getResults()))
return false;

// Check operands.
for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
if (!opEqual(&getOperandRef(i), &RHS->getOperandRef(i)))
return false;

// Check any special state of instructions that are not represented in the
// instructions operands/type.
return hasIdenticalState(RHS);
}

/// Returns true if the instruction may have side effects.
///
/// Instructions that store into memory or change retain counts as well as
Expand Down Expand Up @@ -972,19 +996,20 @@ struct SILInstruction::NonTypeDependentOperandToValue {

struct SILInstruction::OperandToTransformedValue {
const SILInstruction &i;
std::function<SILValue(SILValue)> transformFn;
std::function<SILValue(const Operand *)> transformFn;
bool skipTypeDependentOps;

OperandToTransformedValue(const SILInstruction &i,
std::function<SILValue(SILValue)> transformFn,
bool skipTypeDependentOps)
OperandToTransformedValue(
const SILInstruction &i,
std::function<SILValue(const Operand *)> transformFn,
bool skipTypeDependentOps)
: i(i), transformFn(transformFn),
skipTypeDependentOps(skipTypeDependentOps) {}

Optional<SILValue> operator()(const Operand &use) const {
if (skipTypeDependentOps && i.isTypeDependentOperand(use))
return None;
return transformFn(use.get());
return transformFn(&use);
}
};

Expand All @@ -1005,10 +1030,9 @@ SILInstruction::getNonTypeDependentOperandValues() const
NonTypeDependentOperandToValue(*this));
}

inline auto
SILInstruction::getOperandValues(std::function<SILValue(SILValue)> transformFn,
bool skipTypeDependentOperands) const
-> TransformedOperandValueRange {
inline auto SILInstruction::getOperandValues(
std::function<SILValue(const Operand *)> transformFn,
bool skipTypeDependentOperands) const -> TransformedOperandValueRange {
return TransformedOperandValueRange(
getAllOperands(),
OperandToTransformedValue(*this, transformFn, skipTypeDependentOperands));
Expand Down Expand Up @@ -6539,7 +6563,8 @@ class SelectEnumInstBase

SILValue getOperand() const { return getAllOperands()[0].get(); }
SILValue getEnumOperand() const { return getOperand(); }

const Operand &getEnumOperandRef() const { return getAllOperands()[0]; }

std::pair<EnumElementDecl*, SILValue>
getCase(unsigned i) const {
return std::make_pair(getEnumElementDeclStorage()[i],
Expand Down Expand Up @@ -8717,6 +8742,8 @@ class IndexingInst : public SingleValueInstruction {
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }

const Operand &getBaseOperandRef() const { return getAllOperands()[Base]; }

DEFINE_ABSTRACT_SINGLE_VALUE_INST_BOILERPLATE(IndexingInst)
};

Expand Down
Loading