diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 6bf852a49fb38..2905e4ad1691f 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -5074,8 +5074,43 @@ GenTree* Lowering::LowerHWIntrinsicGetElement(GenTreeHWIntrinsic* node) uint32_t newScale; int32_t newOffset; - GenTreeIndir* indir = op1->AsIndir(); - GenTree* addr = indir->Addr(); + // Normally we'd evaluate op1 (indir), then op2 (element index). + // We like to be able to reorder these to fold op2 into the indir. + + GenTreeIndir* indir = op1->AsIndir(); + GenTree* addr = indir->Addr(); + bool const canMoveTheIndirLater = IsInvariantInRange(indir, node); + + // If we can't move the indir, force evaluation of its side effects. + // + if (!canMoveTheIndirLater) + { + // Force evaluation of the address, if it is complex + // + if (!(addr->IsInvariant() || addr->OperIsLocal())) + { + addr->ClearContained(); + LIR::Use addrUse(BlockRange(), &indir->Addr(), indir); + addrUse.ReplaceWithLclVar(comp); + addr = indir->Addr(); + } + + // If the indir can fault, do a null check. + // + if (indir->OperMayThrow(comp)) + { + GenTree* addrClone = comp->gtCloneExpr(addr); + GenTree* nullcheck = comp->gtNewNullCheck(addrClone, comp->compCurBB); + BlockRange().InsertBefore(indir, addrClone, nullcheck); + LowerNode(nullcheck); + + indir->gtFlags |= GTF_IND_NONFAULTING; + } + + // We should now be able to move the indir + // + indir->gtFlags &= ~GTF_EXCEPT; + } if (addr->OperIsAddrMode()) { diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_89565/Runtime_89565.cs b/src/tests/JIT/Regression/JitBlue/Runtime_89565/Runtime_89565.cs new file mode 100644 index 0000000000000..77c558e881215 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_89565/Runtime_89565.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using Xunit; + +public class Runtime_89565 +{ + [Fact] + public static unsafe int Test() + { + int result = 0; + try + { + Foo(null); + } + catch (NullReferenceException) + { + result += 50; + } + catch + { + + } + + try + { + Bar(null, 0); + } + catch (DivideByZeroException) + { + result += 50; + } + catch + { + + } + + return result; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static unsafe float Foo(Vector256* v) + { + return (*v)[8]; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static unsafe float Bar(Vector256* v, int x) + { + return (*v)[8/x]; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_89565/Runtime_89565.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_89565/Runtime_89565.csproj new file mode 100644 index 0000000000000..efc38a9429de5 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_89565/Runtime_89565.csproj @@ -0,0 +1,8 @@ + + + true + + + + +