Skip to content

Commit a3b39f5

Browse files
authored
JIT: Improve interference checks for thrown exceptions and enable CSE/hoisting of GVM resolution helpers (#122017)
- Introduce `ExceptionSetFlags::UnknownException`. This special value marks that an operation may throw an exception that we cannot say anything about. Consumers of flags must be specially aware about this exception type. - Make `GenTree::OperExceptions` callable on all trees by changing arbitrary user calls to return the new `UnknownException` type. - Switch `OperMayThrow` to be literally `OperExceptions() != None` - Enhance precision about exceptions thrown by helper calls. Instead of just modelling "may throw" and "may not throw", we model the exact exceptions a helper may throw via `ExceptionSetFlags`. - Add helper call properties for `CORINFO_HELP_VIRTUAL_FUNC_PTR`, `CORINFO_HELP_GVMLOOKUP_FOR_SLOT`, `CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR`. These do not mutate the heap and we use the new mechanism above to indicate that the only exception they can throw is NRE. They are also pure, so add a VN function so VN can model them. This allows us to CSE and hoist these helpers. - Update `SideEffectSet` to track and precisely handle interference for exceptions. We can now reorder two operations if we know they can only throw the exact same exception. - Generalize `OptimizeCallIndirectTargetEvaluation`; manual interference handling is no longer necessary, and we can use it for all calls. Example: ```csharp public static void Test(Base b) { b.Foo<string>(); b.Foo<int>(); b.Foo<string>(); b.Foo<int>(); for (int i = 0; i < 10; i++) b.Foo<double>(); } public abstract class Base { public abstract void Foo<T>(); } public class Derived : Base { public override void Foo<T>() { } } ``` Before: ```asm G_M7145_IG02: mov rcx, rbx mov rsi, 0xD1FFAB1E ; Program+Base mov rdx, rsi mov r8, 0xD1FFAB1E ; token handle call CORINFO_HELP_VIRTUAL_FUNC_PTR mov rcx, rbx call rax mov rcx, rbx mov rdx, rsi mov r8, 0xD1FFAB1E ; token handle call CORINFO_HELP_VIRTUAL_FUNC_PTR mov rcx, rbx call rax mov rcx, rbx mov rdx, rsi mov r8, 0xD1FFAB1E ; token handle call CORINFO_HELP_VIRTUAL_FUNC_PTR mov rcx, rbx call rax mov rcx, rbx mov rdx, rsi mov r8, 0xD1FFAB1E ; token handle call CORINFO_HELP_VIRTUAL_FUNC_PTR mov rcx, rbx call rax mov edi, 10 ;; size=119 bbWeight=1 PerfScore 20.50 G_M7145_IG03: mov rcx, rbx mov rdx, rsi mov r8, 0xD1FFAB1E ; token handle call CORINFO_HELP_VIRTUAL_FUNC_PTR mov rcx, rbx call rax dec edi jne SHORT G_M7145_IG03 ;; size=30 bbWeight=8 PerfScore 50.00 ``` After: ```asm G_M7145_IG02: mov rcx, rbx mov rsi, 0xD1FFAB1E ; Program+Base mov rdx, rsi mov r8, 0xD1FFAB1E ; token handle call CORINFO_HELP_VIRTUAL_FUNC_PTR mov rcx, rbx mov rdi, rax call rdi mov rcx, rbx mov rdx, rsi mov r8, 0xD1FFAB1E ; token handle call CORINFO_HELP_VIRTUAL_FUNC_PTR mov rcx, rbx mov rbp, rax call rbp mov rcx, rbx call rdi mov rcx, rbx call rbp mov rcx, rbx mov rdx, rsi mov r8, 0xD1FFAB1E ; token handle call CORINFO_HELP_VIRTUAL_FUNC_PTR mov rsi, rax mov edi, 10 ;; size=107 bbWeight=1 PerfScore 19.50 G_M7145_IG03: mov rcx, rbx call rsi dec edi jne SHORT G_M7145_IG03 ;; size=9 bbWeight=8 PerfScore 36.00 ```
1 parent bae19aa commit a3b39f5

File tree

12 files changed

+198
-168
lines changed

12 files changed

+198
-168
lines changed

src/coreclr/jit/compiler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5906,6 +5906,9 @@ class Compiler
59065906
// Adds the exception set for the current tree node which has a memory indirection operation
59075907
void fgValueNumberAddExceptionSetForIndirection(GenTree* tree, GenTree* baseAddr);
59085908

5909+
// Create VNP for NullPtrExc for something that null checks a base address
5910+
ValueNumPair fgValueNumberIndirNullCheckExceptions(GenTree* baseAddr);
5911+
59095912
// Adds the exception sets for the current tree node which is performing a division or modulus operation
59105913
void fgValueNumberAddExceptionSetForDivision(GenTree* tree);
59115914

src/coreclr/jit/forwardsub.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -257,16 +257,13 @@ class ForwardSubVisitor final : public GenTreeVisitor<ForwardSubVisitor>
257257
}
258258

259259
m_accumulatedFlags |= (node->gtFlags & GTF_GLOB_EFFECT);
260-
if ((node->gtFlags & GTF_CALL) != 0)
260+
if ((node->gtFlags & GTF_EXCEPT) != 0)
261261
{
262-
m_accumulatedExceptions = ExceptionSetFlags::All;
263-
}
264-
else if ((node->gtFlags & GTF_EXCEPT) != 0)
265-
{
266-
// We can never reorder in the face of different exception types,
267-
// so stop calling 'OperExceptions' once we've seen more than one
268-
// different exception type.
269-
if (genCountBits(static_cast<uint32_t>(m_accumulatedExceptions)) <= 1)
262+
// We can never reorder in the face of different or unknown
263+
// exception types, so stop calling 'OperExceptions' once we've
264+
// seen more than one different exception type.
265+
if ((genCountBits(static_cast<uint32_t>(m_accumulatedExceptions)) <= 1) &&
266+
((m_accumulatedExceptions & ExceptionSetFlags::UnknownException) == ExceptionSetFlags::None))
270267
{
271268
m_accumulatedExceptions |= node->OperExceptions(m_compiler);
272269
}
@@ -694,9 +691,10 @@ bool Compiler::fgForwardSubStatement(Statement* stmt)
694691
if ((fsv.GetFlags() & GTF_EXCEPT) != 0)
695692
{
696693
assert(fsv.GetExceptions() != ExceptionSetFlags::None);
697-
if (genCountBits(static_cast<uint32_t>(fsv.GetExceptions())) > 1)
694+
if ((genCountBits(static_cast<uint32_t>(fsv.GetExceptions())) > 1) ||
695+
(((fsv.GetExceptions() & ExceptionSetFlags::UnknownException) != ExceptionSetFlags::None)))
698696
{
699-
JITDUMP(" cannot reorder different thrown exceptions\n");
697+
JITDUMP(" cannot reorder different/unknown thrown exceptions\n");
700698
return false;
701699
}
702700

src/coreclr/jit/gentree.cpp

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7183,8 +7183,9 @@ bool GenTree::OperIsImplicitIndir() const
71837183
// A bit set of exceptions this tree may throw.
71847184
//
71857185
// Remarks:
7186-
// Should not be used on calls given that we can say nothing precise about
7187-
// those.
7186+
// The ExceptionSetFlags::UnknownException must generally be handled
7187+
// specially by the consumer; when it is present it means we can say nothing
7188+
// precise about the thrown exceptions.
71887189
//
71897190
ExceptionSetFlags GenTree::OperExceptions(Compiler* comp)
71907191
{
@@ -7236,9 +7237,14 @@ ExceptionSetFlags GenTree::OperExceptions(Compiler* comp)
72367237
return ExceptionSetFlags::None;
72377238

72387239
case GT_CALL:
7239-
assert(!"Unexpected GT_CALL in OperExceptions");
7240-
return ExceptionSetFlags::All;
7240+
CorInfoHelpFunc helper;
7241+
helper = comp->eeGetHelperNum(this->AsCall()->gtCallMethHnd);
7242+
if (helper == CORINFO_HELP_UNDEF)
7243+
{
7244+
return ExceptionSetFlags::UnknownException;
7245+
}
72417246

7247+
return Compiler::s_helperCallProperties.ThrownExceptions(helper);
72427248
case GT_LOCKADD:
72437249
case GT_XAND:
72447250
case GT_XORR:
@@ -7286,7 +7292,10 @@ ExceptionSetFlags GenTree::OperExceptions(Compiler* comp)
72867292
#ifdef FEATURE_HW_INTRINSICS
72877293
case GT_HWINTRINSIC:
72887294
{
7289-
assert((gtFlags & GTF_HW_USER_CALL) == 0);
7295+
if ((gtFlags & GTF_HW_USER_CALL) != 0)
7296+
{
7297+
return ExceptionSetFlags::UnknownException;
7298+
}
72907299

72917300
GenTreeHWIntrinsic* hwIntrinsicNode = this->AsHWIntrinsic();
72927301

@@ -7332,32 +7341,6 @@ ExceptionSetFlags GenTree::OperExceptions(Compiler* comp)
73327341
//
73337342
bool GenTree::OperMayThrow(Compiler* comp)
73347343
{
7335-
if (OperIs(GT_CALL))
7336-
{
7337-
CorInfoHelpFunc helper;
7338-
helper = comp->eeGetHelperNum(this->AsCall()->gtCallMethHnd);
7339-
return ((helper == CORINFO_HELP_UNDEF) || !comp->s_helperCallProperties.NoThrow(helper));
7340-
}
7341-
#ifdef FEATURE_HW_INTRINSICS
7342-
else if (OperIsHWIntrinsic())
7343-
{
7344-
if ((gtFlags & GTF_HW_USER_CALL) != 0)
7345-
{
7346-
return true;
7347-
}
7348-
7349-
#ifdef TARGET_XARCH
7350-
NamedIntrinsic intrinsicId = this->AsHWIntrinsic()->GetHWIntrinsicId();
7351-
if (intrinsicId == NI_Vector128_op_Division || intrinsicId == NI_Vector256_op_Division ||
7352-
intrinsicId == NI_Vector512_op_Division)
7353-
{
7354-
assert(varTypeIsInt(AsHWIntrinsic()->GetSimdBaseType()));
7355-
return true;
7356-
}
7357-
#endif // TARGET_XARCH
7358-
}
7359-
#endif // FEATURE_HW_INTRINSICS
7360-
73617344
return OperExceptions(comp) != ExceptionSetFlags::None;
73627345
}
73637346

@@ -7513,12 +7496,13 @@ bool GenTree::OperSupportsOrderingSideEffect() const
75137496
// excluding its children.
75147497
//
75157498
// Arguments:
7516-
// comp - Compiler instance
7499+
// comp - Compiler instance
7500+
// preciseExceptions - [out] Precise exceptions this node may throw
75177501
//
75187502
// Return Value:
75197503
// The effect flags.
75207504
//
7521-
GenTreeFlags GenTree::OperEffects(Compiler* comp)
7505+
GenTreeFlags GenTree::OperEffects(Compiler* comp, ExceptionSetFlags* preciseExceptions)
75227506
{
75237507
GenTreeFlags flags = gtFlags & GTF_ALL_EFFECT;
75247508

@@ -7532,9 +7516,17 @@ GenTreeFlags GenTree::OperEffects(Compiler* comp)
75327516
flags &= ~GTF_CALL;
75337517
}
75347518

7535-
if (((flags & GTF_EXCEPT) != 0) && !OperMayThrow(comp))
7519+
if ((flags & GTF_EXCEPT) != 0)
75367520
{
7537-
flags &= ~GTF_EXCEPT;
7521+
*preciseExceptions = OperExceptions(comp);
7522+
if (*preciseExceptions == ExceptionSetFlags::None)
7523+
{
7524+
flags &= ~GTF_EXCEPT;
7525+
}
7526+
}
7527+
else
7528+
{
7529+
*preciseExceptions = ExceptionSetFlags::None;
75387530
}
75397531

75407532
if (((flags & GTF_GLOB_REF) != 0) && !OperRequiresGlobRefFlag(comp))
@@ -17908,11 +17900,6 @@ ExceptionSetFlags Compiler::gtCollectExceptions(GenTree* tree)
1790817900
}
1790917901
};
1791017902

17911-
// We only expect the caller to ask for precise exceptions for cases where
17912-
// it may help with disambiguating between exceptions. If the tree contains
17913-
// a call it can always throw arbitrary exceptions.
17914-
assert((tree->gtFlags & GTF_CALL) == 0);
17915-
1791617903
ExceptionsWalker walker(this);
1791717904
walker.WalkTree(&tree, nullptr);
1791817905
assert(((tree->gtFlags & GTF_EXCEPT) == 0) || (walker.GetFlags() != ExceptionSetFlags::None));

src/coreclr/jit/gentree.h

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -116,20 +116,6 @@ enum gtCallTypes : BYTE
116116
CT_COUNT // fake entry (must be last)
117117
};
118118

119-
enum class ExceptionSetFlags : uint32_t
120-
{
121-
None = 0x0,
122-
OverflowException = 0x1,
123-
DivideByZeroException = 0x2,
124-
ArithmeticException = 0x4,
125-
NullReferenceException = 0x8,
126-
IndexOutOfRangeException = 0x10,
127-
StackOverflowException = 0x20,
128-
129-
All = OverflowException | DivideByZeroException | ArithmeticException | NullReferenceException |
130-
IndexOutOfRangeException | StackOverflowException,
131-
};
132-
133119
inline constexpr ExceptionSetFlags operator~(ExceptionSetFlags a)
134120
{
135121
return (ExceptionSetFlags)(~(uint32_t)a);
@@ -1939,7 +1925,12 @@ struct GenTree
19391925

19401926
bool OperSupportsOrderingSideEffect() const;
19411927

1942-
GenTreeFlags OperEffects(Compiler* comp);
1928+
GenTreeFlags OperEffects(Compiler* comp, ExceptionSetFlags* preciseExceptions);
1929+
GenTreeFlags OperEffects(Compiler* comp)
1930+
{
1931+
ExceptionSetFlags preciseExceptions;
1932+
return OperEffects(comp, &preciseExceptions);
1933+
}
19431934

19441935
unsigned GetScaleIndexMul();
19451936
unsigned GetScaleIndexShf();

src/coreclr/jit/lower.cpp

Lines changed: 6 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6306,15 +6306,12 @@ void Lowering::OptimizeCallIndirectTargetEvaluation(GenTreeCall* call)
63066306
{
63076307
assert((call->gtCallType == CT_INDIRECT) && (call->gtCallAddr != nullptr));
63086308

6309-
if (!call->gtCallAddr->IsHelperCall(comp, CORINFO_HELP_VIRTUAL_FUNC_PTR) &&
6310-
!call->gtCallAddr->IsHelperCall(comp, CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR) &&
6311-
!call->gtCallAddr->IsHelperCall(comp, CORINFO_HELP_GVMLOOKUP_FOR_SLOT) &&
6312-
!call->gtCallAddr->IsHelperCall(comp, CORINFO_HELP_READYTORUN_GENERIC_HANDLE))
6309+
if (!call->gtCallAddr->IsCall())
63136310
{
63146311
return;
63156312
}
63166313

6317-
JITDUMP("Target is a GVM; seeing if we can move arguments ahead of resolution\n");
6314+
JITDUMP("Indirect call target is itself a call; trying to reorder its evaluation with arguments\n");
63186315

63196316
m_scratchSideEffects.Clear();
63206317

@@ -6357,9 +6354,9 @@ void Lowering::OptimizeCallIndirectTargetEvaluation(GenTreeCall* call)
63576354

63586355
if (cur == call->gtCallAddr)
63596356
{
6360-
// Start moving this range. Do not add its side effects as we will
6361-
// check the NRE manually for precision.
6357+
// Start moving this range.
63626358
movingRange = LIR::ReadOnlyRange(cur, cur);
6359+
m_scratchSideEffects.AddNode(comp, cur);
63636360
continue;
63646361
}
63656362

@@ -6374,41 +6371,12 @@ void Lowering::OptimizeCallIndirectTargetEvaluation(GenTreeCall* call)
63746371
{
63756372
// This node is in the dataflow. See if we can move it ahead of the
63766373
// range we are moving.
6377-
bool interferes = false;
63786374
if (m_scratchSideEffects.InterferesWith(comp, cur, /* strict */ true))
6379-
{
6380-
JITDUMP(" Stopping at [%06u]; it interferes with the current range we are moving\n",
6381-
Compiler::dspTreeID(cur));
6382-
interferes = true;
6383-
}
6384-
6385-
if (!interferes)
6386-
{
6387-
// No problem so far. However the side effect set does not
6388-
// include the GVM call itself, which can throw NRE. Check the
6389-
// NRE now for precision.
6390-
GenTreeFlags flags = cur->OperEffects(comp);
6391-
if ((flags & GTF_PERSISTENT_SIDE_EFFECTS) != 0)
6392-
{
6393-
JITDUMP(" Stopping at [%06u]; it has persistent side effects\n", Compiler::dspTreeID(cur));
6394-
interferes = true;
6395-
}
6396-
else if ((flags & GTF_EXCEPT) != 0)
6397-
{
6398-
ExceptionSetFlags preciseExceptions = cur->OperExceptions(comp);
6399-
if (preciseExceptions != ExceptionSetFlags::NullReferenceException)
6400-
{
6401-
JITDUMP(" Stopping at [%06u]; it throws an exception that is not NRE\n",
6402-
Compiler::dspTreeID(cur));
6403-
interferes = true;
6404-
}
6405-
}
6406-
}
6407-
6408-
if (interferes)
64096375
{
64106376
// Stop moving the range, but keep going through the rest
64116377
// of the nodes to unmark them
6378+
JITDUMP(" Stopping at [%06u]; it interferes with the current range we are moving\n",
6379+
Compiler::dspTreeID(cur));
64126380
movingRange = LIR::ReadOnlyRange();
64136381
}
64146382
else

src/coreclr/jit/morph.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -911,8 +911,10 @@ void CallArgs::ArgsComplete(Compiler* comp, GenTreeCall* call)
911911
exceptionFlags = comp->gtCollectExceptions(argx);
912912
}
913913

914-
bool exactlyOne = isPow2(static_cast<unsigned>(exceptionFlags));
915-
bool throwsSameAsPrev = exactlyOne && (exceptionFlags == prevExceptionFlags);
914+
bool exactlyOneKnown =
915+
isPow2(static_cast<unsigned>(exceptionFlags)) &&
916+
((exceptionFlags & ExceptionSetFlags::UnknownException) == ExceptionSetFlags::None);
917+
bool throwsSameAsPrev = exactlyOneKnown && (exceptionFlags == prevExceptionFlags);
916918
if (!throwsSameAsPrev)
917919
{
918920
JITDUMP("Exception set for arg [%06u] interferes with previous tree [%06u]; must evaluate previous "
@@ -5664,10 +5666,11 @@ GenTree* Compiler::getVirtMethodPointerTree(GenTree* thisPtr,
56645666
CORINFO_RESOLVED_TOKEN* pResolvedToken,
56655667
CORINFO_CALL_INFO* pCallInfo)
56665668
{
5667-
GenTree* exactTypeDesc = getTokenHandleTree(pResolvedToken, true);
56685669
GenTree* exactMethodDesc = getTokenHandleTree(pResolvedToken, false);
5670+
GenTree* exactTypeDesc = getTokenHandleTree(pResolvedToken, true);
56695671

5670-
return gtNewHelperCallNode(CORINFO_HELP_VIRTUAL_FUNC_PTR, TYP_I_IMPL, thisPtr, exactTypeDesc, exactMethodDesc);
5672+
return gtNewVirtualFunctionLookupHelperCallNode(CORINFO_HELP_VIRTUAL_FUNC_PTR, TYP_I_IMPL, thisPtr, exactMethodDesc,
5673+
exactTypeDesc);
56715674
}
56725675

56735676
//------------------------------------------------------------------------

src/coreclr/jit/sideeffects.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,10 @@ SideEffectSet::SideEffectSet(Compiler* compiler, GenTree* node)
489489
//
490490
void SideEffectSet::AddNode(Compiler* compiler, GenTree* node)
491491
{
492-
m_sideEffectFlags |= node->OperEffects(compiler);
492+
ExceptionSetFlags preciseExceptions;
493+
GenTreeFlags operEffects = node->OperEffects(compiler, &preciseExceptions);
494+
m_sideEffectFlags |= operEffects;
495+
m_preciseExceptions |= preciseExceptions;
493496
m_aliasSet.AddNode(compiler, node);
494497
}
495498

@@ -507,12 +510,14 @@ void SideEffectSet::AddNode(Compiler* compiler, GenTree* node)
507510
// - One set's reads and writes interfere with the other set's reads and writes
508511
//
509512
// Arguments:
510-
// otherSideEffectFlags - The side effect flags for the other side effect set.
513+
// otherSideEffectFlags - The side effect flags for the other side effect set.
514+
// otherPreciseExceptions - The precise exceptions for the other side effect set.
511515
// otherAliasInfo - The alias information for the other side effect set.
512516
// strict - True if the analysis should be strict as described above.
513517
//
514518
template <typename TOtherAliasInfo>
515519
bool SideEffectSet::InterferesWith(unsigned otherSideEffectFlags,
520+
ExceptionSetFlags otherPreciseExceptions,
516521
const TOtherAliasInfo& otherAliasInfo,
517522
bool strict) const
518523
{
@@ -535,10 +540,15 @@ bool SideEffectSet::InterferesWith(unsigned otherSideEffectFlags,
535540
return true;
536541
}
537542

538-
// If both sets produce an exception, the sets interfere.
543+
// If both sets produce non-reorderable exceptions the sets interfere
539544
if (thisProducesException && otherProducesException)
540545
{
541-
return true;
546+
if ((((m_preciseExceptions | otherPreciseExceptions) & ExceptionSetFlags::UnknownException) !=
547+
ExceptionSetFlags::None) ||
548+
(genCountBits((uint32_t)m_preciseExceptions) > 1) || (m_preciseExceptions != otherPreciseExceptions))
549+
{
550+
return true;
551+
}
542552
}
543553
}
544554

@@ -575,7 +585,7 @@ bool SideEffectSet::InterferesWith(unsigned otherSideEffectFlags,
575585
//
576586
bool SideEffectSet::InterferesWith(const SideEffectSet& other, bool strict) const
577587
{
578-
return InterferesWith(other.m_sideEffectFlags, other.m_aliasSet, strict);
588+
return InterferesWith(other.m_sideEffectFlags, other.m_preciseExceptions, other.m_aliasSet, strict);
579589
}
580590

581591
//------------------------------------------------------------------------
@@ -593,7 +603,9 @@ bool SideEffectSet::InterferesWith(const SideEffectSet& other, bool strict) cons
593603
//
594604
bool SideEffectSet::InterferesWith(Compiler* compiler, GenTree* node, bool strict) const
595605
{
596-
return InterferesWith(node->OperEffects(compiler), AliasSet::NodeInfo(compiler, node), strict);
606+
ExceptionSetFlags preciseExceptions;
607+
GenTreeFlags operEffects = node->OperEffects(compiler, &preciseExceptions);
608+
return InterferesWith(operEffects, preciseExceptions, AliasSet::NodeInfo(compiler, node), strict);
597609
}
598610

599611
//------------------------------------------------------------------------
@@ -782,6 +794,7 @@ bool SideEffectSet::IsLirRangeInvariantInRange(
782794
//
783795
void SideEffectSet::Clear()
784796
{
785-
m_sideEffectFlags = 0;
797+
m_sideEffectFlags = 0;
798+
m_preciseExceptions = ExceptionSetFlags::None;
786799
m_aliasSet.Clear();
787800
}

src/coreclr/jit/sideeffects.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,15 @@ class AliasSet final
168168
//
169169
class SideEffectSet final
170170
{
171-
unsigned m_sideEffectFlags; // A mask of GTF_* flags that represents exceptional and barrier side effects.
172-
AliasSet m_aliasSet; // An AliasSet that represents read and write side effects.
171+
unsigned m_sideEffectFlags; // A mask of GTF_* flags that represents exceptional and barrier side effects.
172+
ExceptionSetFlags m_preciseExceptions; // Set representing exceptions that may be thrown
173+
AliasSet m_aliasSet; // An AliasSet that represents read and write side effects.
173174

174175
template <typename TOtherAliasInfo>
175-
bool InterferesWith(unsigned otherSideEffectFlags, const TOtherAliasInfo& otherAliasInfo, bool strict) const;
176+
bool InterferesWith(unsigned otherSideEffectFlags,
177+
ExceptionSetFlags otherPreciseExceptions,
178+
const TOtherAliasInfo& otherAliasInfo,
179+
bool strict) const;
176180

177181
public:
178182
SideEffectSet();

0 commit comments

Comments
 (0)