AliasClass AliasClass::unionData(rep newBits, AliasClass a, AliasClass b) { assertx(a.m_stag == b.m_stag); switch (a.m_stag) { case STag::None: break; case STag::Frame: case STag::Prop: case STag::ElemI: case STag::ElemS: case STag::MIState: case STag::Ref: assertx(!a.equivData(b)); break; case STag::Stack: { auto const stkA = a.m_stack; auto const stkB = b.m_stack; // Make a stack range big enough to contain both of them. auto const highest = std::max(stkA.offset, stkB.offset); auto const lowest = std::min(lowest_offset(stkA), lowest_offset(stkB)); auto const newStack = AStack { highest, highest - lowest }; auto ret = AliasClass{newBits}; new (&ret.m_stack) AStack(newStack); ret.m_stag = STag::Stack; assertx(ret.checkInvariants()); assertx(a <= ret && b <= ret); return ret; } } return AliasClass{newBits}; }
bool AliasClass::maybeData(AliasClass o) const { assertx(m_stag == o.m_stag); switch (m_stag) { case STag::None: not_reached(); // handled above case STag::Frame: return m_frame.fp == o.m_frame.fp && m_frame.id == o.m_frame.id; case STag::Prop: /* * We can't tell if two objects could be the same from here in general, but * we can rule out simple cases based on type. The props can't be the same * if they are at different offsets, though. * * For now we're ignoring the type information, and only using offset. * TODO(#2939547) TODO(#2884927) */ if (m_prop.offset != o.m_prop.offset) return false; return true; /* * Two arrays can generally be the same even if they aren't the same SSATmp, * because we might have loaded it from more than one place, and we have * linear chains in array modification instructions. */ case STag::ElemI: if (m_elemI.idx != o.m_elemI.idx) return false; return true; case STag::ElemS: if (m_elemS.key != o.m_elemS.key) return false; return true; /* * Stack offsets that have different StkPtr bases are always presumed to * possibly alias. If both are FramePtrs but different, they can't alias. * Stack offsets on the same base pointer may only alias if they have * overlapping ranges. */ case STag::Stack: if (m_stack.base != o.m_stack.base) { return !(m_stack.base->type() <= Type::FramePtr && o.m_stack.base->type() <= Type::FramePtr); } { // True if there's a non-empty intersection of the two stack slot // intervals. auto const lowest_upper = std::min(m_stack.offset, o.m_stack.offset); auto const highest_lower = std::max( lowest_offset(m_stack), lowest_offset(o.m_stack) ); return lowest_upper > highest_lower; } case STag::MIState: return m_mis.offset == o.m_mis.offset; } not_reached(); }
bool AliasClass::maybeData(AliasClass o) const { assertx(m_stag == o.m_stag); switch (m_stag) { case STag::None: not_reached(); // handled outside case STag::Frame: return m_frame.fp == o.m_frame.fp && m_frame.id == o.m_frame.id; case STag::Prop: /* * We can't tell if two objects could be the same from here in general, but * we can rule out simple cases based on type. The props can't be the same * if they are at different offsets, though. * * For now we're ignoring the type information, and only using offset. * TODO(#2939547) TODO(#2884927) */ if (m_prop.offset != o.m_prop.offset) return false; return true; /* * Two arrays can generally be the same even if they aren't the same SSATmp, * because we might have loaded it from more than one place, and we have * linear chains in array modification instructions. */ case STag::ElemI: if (m_elemI.idx != o.m_elemI.idx) return false; return true; case STag::ElemS: if (m_elemS.key != o.m_elemS.key) return false; return true; case STag::Stack: { // True if there's a non-empty intersection of the two stack slot // intervals. auto const lowest_upper = std::min(m_stack.offset, o.m_stack.offset); auto const highest_lower = std::max( lowest_offset(m_stack), lowest_offset(o.m_stack) ); return lowest_upper > highest_lower; } case STag::MIState: return m_mis.offset == o.m_mis.offset; /* * Two boxed cells can generally refer to the same RefData. */ case STag::Ref: return true; } not_reached(); }
bool AliasClass::subclassData(AliasClass o) const { switch (m_stag) { case STag::None: case STag::Frame: case STag::Prop: case STag::ElemI: case STag::ElemS: case STag::MIState: return equivData(o); case STag::Stack: if (m_stack.base != o.m_stack.base) return false; return m_stack.offset <= o.m_stack.offset && lowest_offset(m_stack) >= lowest_offset(o.m_stack); } not_reached(); }
bool AliasClass::subclassData(AliasClass o) const { assertx(m_stag == o.m_stag); switch (m_stag) { case STag::None: case STag::Frame: case STag::Prop: case STag::ElemI: case STag::ElemS: case STag::MIState: case STag::Ref: return equivData(o); case STag::Stack: return m_stack.offset <= o.m_stack.offset && lowest_offset(m_stack) >= lowest_offset(o.m_stack); } not_reached(); }
AliasClass AliasClass::unionData(rep newBits, AliasClass a, AliasClass b) { assertx(a.m_stag == b.m_stag); switch (a.m_stag) { case STag::None: break; case STag::Frame: case STag::Prop: case STag::ElemI: case STag::ElemS: case STag::MIState: case STag::Ref: assertx(!a.equivData(b)); break; case STag::Stack: { auto const stkA = a.m_stack; auto const stkB = b.m_stack; // If two AStack have different bases, we can't union them any better // than AStackAny, since we don't know where they are relative to each // other. We know two AStacks with different FramePtr bases can't alias, // but that doesn't help us represent a union of them. if (stkA.base != stkB.base) return AliasClass{newBits}; // Make a stack range big enough to contain both of them. auto const highest = std::max(stkA.offset, stkB.offset); auto const lowest = std::min(lowest_offset(stkA), lowest_offset(stkB)); auto const newStack = AStack { stkA.base, highest, highest - lowest }; auto ret = AliasClass{newBits}; new (&ret.m_stack) AStack(newStack); ret.m_stag = STag::Stack; assertx(ret.checkInvariants()); assertx(a <= ret && b <= ret); return ret; } } return AliasClass{newBits}; }