Skip to content
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
28 changes: 15 additions & 13 deletions src/coreclr/jit/codegenarmarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4278,31 +4278,33 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea)
else
{
#ifdef TARGET_ARM64

if (index->isContained())
{
// Only BFIZ/CAST nodes should be present for contained index on ARM64.
GenTreeCast* cast;
if (index->OperIs(GT_BFIZ))
{
// Handle LEA with "contained" BFIZ
assert(scale == 0);
scale = (DWORD)index->gtGetOp2()->AsIntConCommon()->IconValue();
index = index->gtGetOp1()->gtGetOp1();
}
else if (index->OperIs(GT_CAST))
{
index = index->AsCast()->gtGetOp1();
cast = index->gtGetOp1()->AsCast();
}
else
{
// Only BFIZ/CAST nodes should be present for for contained index on ARM64.
// If there are more, we need to handle them here.
unreached();
cast = index->AsCast();
}

// The 32-bit index has to be sign/zero-extended as part of the add.
assert(genActualTypeIsInt(cast->CastOp()) && (scale <= 4));
emit->emitIns_R_R_R_I(INS_add, size, lea->GetRegNum(), memBase->GetRegNum(),
cast->CastOp()->GetRegNum(), scale,
cast->IsUnsigned() ? INS_OPTS_UXTW : INS_OPTS_SXTW);
Comment thread
EgorBo marked this conversation as resolved.
}
else
#endif

// Then compute target reg from [base + index*scale]
genScaledAdd(size, lea->GetRegNum(), memBase->GetRegNum(), index->GetRegNum(), scale);
{
// Then compute target reg from [base + index*scale]
genScaledAdd(size, lea->GetRegNum(), memBase->GetRegNum(), index->GetRegNum(), scale);
}
}
}
else if (lea->HasBase())
Expand Down
12 changes: 10 additions & 2 deletions src/coreclr/jit/rangecheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,12 @@ Range RangeCheck::GetRangeFromAssertionsWorker(
#endif
}

if (varTypeIsFloating(vnType))
{
// Integer ranges don't describe floating point values (e.g. int->float casts may round).
return Limit(Limit::keUnknown);
}

//
// First, let's see if we can tighten the range based on VN information.
//
Expand Down Expand Up @@ -2144,9 +2150,11 @@ bool RangeCheck::DoesVarDefOverflow(BasicBlock* block, GenTreeLclVarCommon* lcl,

// But only if the range from the assertion is more strict than the global
// range computed; otherwise we might still have used the def's value to
// tighten the range of the global range.
// tighten the range of the global range. A dependent limit doesn't qualify:
// Widen resolves it later assuming the defs don't overflow.
Range merged = RangeOps::Merge(range, assertionRange, false);
if (merged.LowerLimit().Equals(range.LowerLimit()) && merged.UpperLimit().Equals(range.UpperLimit()))
if (!range.LowerLimit().IsDependent() && !range.UpperLimit().IsDependent() &&
merged.LowerLimit().Equals(range.LowerLimit()) && merged.UpperLimit().Equals(range.UpperLimit()))
{
return false;
}
Expand Down
8 changes: 6 additions & 2 deletions src/coreclr/jit/rangecheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -442,9 +442,13 @@ struct RangeOps
// For RSZ by N >= 1, result is in [0, UINT_MAX >> N] regardless of r1's signedness.
// When r1 isn't proven non-negative, the bound above is unsound (negative r1 reinterprets
// as large unsigned), so override with the type-based bound.
if (logical && (r2.LowerLimit().GetConstant() >= 1) &&
!(r1.LowerLimit().IsConstant() && (r1.LowerLimit().GetConstant() >= 0)))
if (logical && !(r1.LowerLimit().IsConstant() && (r1.LowerLimit().GetConstant() >= 0)))
{
if (r2.LowerLimit().GetConstant() == 0)
{
// A shift by 0 may preserve a negative r1, so nothing is known.
return Limit(Limit::keUnknown);
}
Comment thread
EgorBo marked this conversation as resolved.
result.lLimit = Limit(Limit::keConstant, 0);
result.uLimit = Limit(Limit::keConstant, (int)(UINT32_MAX >> r2.LowerLimit().GetConstant()));
}
Expand Down
33 changes: 33 additions & 0 deletions src/tests/JIT/Regression_ro_2/Runtime_134451.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// 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 Xunit;

public class Runtime_134451
{
[Fact]
public static void TestEntryPoint()
{
Assert.Throws<IndexOutOfRangeException>(() => Test(new int[101], true));
}

// "x" wraps around, so "j += x" is not monotonic and "j" becomes negative.
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
private static int Test(int[] a, bool flag)
{
int j = 0, x = int.MaxValue - 10, sum = 0;
if (a.Length != 101)
return 0;
while (j < 101)
{
if (flag)
sum += a[j];
x++;
if (x >= int.MinValue + 1 && x <= 10)
j += x;
}
return sum;
}
}
52 changes: 52 additions & 0 deletions src/tests/JIT/Regression_ro_2/Runtime_134452.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// 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 Xunit;

public class Runtime_134452
{
[Fact]
[SkipOnMono("CoreCLR JIT regression test")]
public static void TestEntryPoint()
{
Assert.Equal(1, IntToFloatRounding(16777219));
Assert.Equal(1, DoubleToUIntSaturation(-5));
Assert.Throws<IndexOutOfRangeException>(() => IndexThroughFloat(new byte[16777220], 16777219));
}

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
private static int IntToFloatRounding(int x)
{
if (x >= 0 && x <= 16777219)
{
// (float)16777219 rounds to 16777220
int y = (int)(float)x;
if (y > 16777219)
return 1;
}
return 0;
}

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
private static int DoubleToUIntSaturation(int x)
{
if (x < 0)
{
// Saturates to 0
uint u = (uint)(double)x;
if (u == 0)
return 1;
}
return 0;
}

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
private static int IndexThroughFloat(byte[] arr, int x)
{
if (arr.Length == 16777220 && x >= 0 && x <= 16777219)
return arr[(int)(float)x];
return -1;
}
}
31 changes: 31 additions & 0 deletions src/tests/JIT/Regression_ro_2/Runtime_134455.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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 Xunit;

public class Runtime_134455
{
[Fact]
public static void TestEntryPoint()
{
Assert.Throws<IndexOutOfRangeException>(() => Test(-1, 1));
Assert.Equal(0, Test(-1, 0));
Assert.Equal(0, Test(50, 0));
}

// "x >>> (y & 3)" is a large positive value for negative "x".
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
private static int Test(int x, int y)
{
int[] a = new int[51];
if (x <= 50)
{
int v = x >>> (y & 3);
if (v >= 0)
return a[v];
}
return 0;
}
}
Loading