Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

New fix for #26417 - Don't allow the hoisting of GT_CLS_VARs that were assigned a constant value. #26952

Merged
merged 4 commits into from
Oct 6, 2019

Conversation

briansull
Copy link

@briansull briansull commented Sep 30, 2019

Fixes #26417 - JIT compiler bug: Incorrect caching of loop variable
Contributes to issue #7147 - JIT: Loop hoisting re-ordering exceptions
Added the Test case for Issue 26417

@briansull
Copy link
Author

@mikedn PTAL
@erozenfeld

@BruceForstall
Copy link
Member

cc @dotnet/jit-contrib

src/jit/optimizer.cpp Outdated Show resolved Hide resolved
@BruceForstall
Copy link
Member

I think it's advisable to trigger outerloop and outerloop stress jobs on this change, when you consider it ready.

@briansull
Copy link
Author

This change isn't particularly dangerous; as it is a chnage that pessimizes a somewhat uncommon optimization, (the hoisting invariant expressions out of loops). So there isn't a worry about introducing incorrectness.

@briansull
Copy link
Author

@erozenfeld PTAL

src/jit/optimizer.cpp Outdated Show resolved Hide resolved
//
if (m_beforeSideEffect)
{
// Is the value of the whole tree loop invariant?
if (!treeIsInvariant)
Copy link
Member

Choose a reason for hiding this comment

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

I think the right check here is if (!treeIsHoistable). If the tree is invariant and can throw but we don't hoist it, we need to set m_beforeSideEffect to false.

Copy link
Author

@briansull briansull Oct 3, 2019

Choose a reason for hiding this comment

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

Unfortunately we have trees that switch back and forth from having treeIsHoistable as true to false and back to true.
Only the switch to treeIsInvariant is permanent.

One such tree that is important to be able to hoist is an invariant array read inside a loop:

Because ARR_BOUNDS_CHECK is a void, (it doesn't produce a value) it isn't a CSE candidate,
and anything that isn't a CSE candidate has treeIsHoistable set to false.
It's parent node is a GT_COMMA which produces a ushort value and can be hoistable.

               [000054] ---XG+------                 +--*  COMMA     ushort
               [000047] ---X-+------                 |  +--*  ARR_BOUNDS_CHECK_Rng void  
               [000009] -----+------                 |  |  +--*  LCL_VAR   int    V02 loc0         
               [000046] ---X-+------                 |  |  \--*  ARR_LENGTH int   
               [000008] -----+------                 |  |     \--*  LCL_VAR   ref    V01 arg1         
               [000010] a--XG+------                 |  \--*  IND       ushort
               [000053] -----+------                 |     \--*  ADD       byref 
               [000044] -----+------                 |        +--*  LCL_VAR   ref    V01 arg1         
               [000052] -----+------                 |        \--*  ADD       long  
               [000050] -----+------                 |           +--*  LSH       long  
               [000048] -----+------                 |           |  +--*  CAST      long <- int
               [000045] i----+------                 |           |  |  \--*  LCL_VAR   int    V02 loc0         
               [000049] -----+-N----                 |           |  \--*  CNS_INT   long   1
               [000051] -----+------                 |           \--*  CNS_INT   long   12 Fseq[#FirstElem]

Copy link
Member

Choose a reason for hiding this comment

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

We may still have a hole here if we encounter a tree that's invariant and can throw an exception but we never hoist it (directly or as part of a parent). I tried to construct an example but ran into another bug where we do an incorrect exception reordering even without a loop: https://github.com/dotnet/coreclr/issues/27027.
I'm ok with this fix as it makes us "more correct" than before but we'll need to revisit this code.

@briansull
Copy link
Author

/azp run coreclr-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Contributes to issue  #7147 - JIT: Loop hoisting re-ordering exceptions
Added the Test case for Issue 26417
Updated comments
Rebased
@briansull
Copy link
Author

/azp run coreclr-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@briansull
Copy link
Author

/azp run coreclr-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@briansull
Copy link
Author

/azp run coreclr-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@briansull
Copy link
Author

/azp run coreclr-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@briansull briansull merged commit da6edcd into dotnet:master Oct 6, 2019
SrivastavaAnubhav pushed a commit to SrivastavaAnubhav/coreclr that referenced this pull request Oct 7, 2019
…e assigned a constant value. (dotnet#26952)

* Fix issue #26417 = Incorrect caching of loop variable
Contributes to issue  #7147 - JIT: Loop hoisting re-ordering exceptions
Added the Test case for Issue 26417
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

JIT compiler bug: Incorrect caching of loop variable
4 participants