Skip to content

Commit

Permalink
Arm: Consider the fact that targetReg can be second half during resol…
Browse files Browse the repository at this point in the history
…ution (dotnet#107493)

* Arm: Consider the fact that targetReg can be second half during resolution

* add test case

* Make sure we only handle float registers

* fix test case's public methods
  • Loading branch information
kunalspathak committed Sep 9, 2024
1 parent 18eedbe commit ac4b7c6
Show file tree
Hide file tree
Showing 3 changed files with 307 additions and 4 deletions.
57 changes: 53 additions & 4 deletions src/coreclr/jit/lsra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9789,10 +9789,26 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock,
if (location[targetReg] == REG_NA)
{
#ifdef TARGET_ARM
regNumber sourceReg = (regNumber)source[targetReg];
Interval* interval = sourceIntervals[sourceReg];
// For Arm, check two things:
// 1. If sourceReg relates to DOUBLE interval, then make sure
// the second half of targetReg is not participating in the resolution.
// 2. On the contrary, if targetReg is second half of a DOUBLE interval,
// then make sure the first half is not participating in the resolution.
// Only when both these conditions are met, can we safely assume
// that sourceReg can be moved to targetReg.
regNumber sourceReg = (regNumber)source[targetReg];
Interval* interval = sourceIntervals[sourceReg];
Interval* otherTargetInterval = nullptr;
regNumber otherHalfTargetReg = REG_NA;
if (genIsValidFloatReg(targetReg) && !genIsValidDoubleReg(targetReg))
{
otherHalfTargetReg = REG_PREV(targetReg);
otherTargetInterval = sourceIntervals[otherHalfTargetReg];
}

if (interval->registerType == TYP_DOUBLE)
{
// Condition 1 above.
// For ARM32, make sure that both of the float halves of the double register are available.
assert(genIsValidDoubleReg(targetReg));
regNumber anotherHalfRegNum = REG_NEXT(targetReg);
Expand All @@ -9801,11 +9817,22 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock,
targetRegsReady.AddRegNumInMask(targetReg);
}
}
else if ((otherTargetInterval != nullptr) && (otherTargetInterval->registerType == TYP_DOUBLE))
{
// Condition 2 above.
assert(otherHalfTargetReg != REG_NA);
if (location[otherHalfTargetReg] == REG_NA)
{
targetRegsReady.AddRegNumInMask(targetReg);
}
}
else
#endif // TARGET_ARM
{
targetRegsReady.AddRegNumInMask(targetReg);
}
#else
targetRegsReady.AddRegNumInMask(targetReg);
#endif
}
}

Expand Down Expand Up @@ -10019,6 +10046,13 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock,
{
compiler->codeGen->regSet.rsSetRegsModified(genRegMask(tempReg) DEBUGARG(true));
#ifdef TARGET_ARM
Interval* otherTargetInterval = nullptr;
regNumber otherHalfTargetReg = REG_NA;
if (genIsValidFloatReg(targetReg) && !genIsValidDoubleReg(targetReg))
{
otherHalfTargetReg = REG_PREV(targetReg);
otherTargetInterval = sourceIntervals[otherHalfTargetReg];
}
if (sourceIntervals[fromReg]->registerType == TYP_DOUBLE)
{
assert(genIsValidDoubleReg(targetReg));
Expand All @@ -10027,8 +10061,15 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock,
addResolutionForDouble(block, insertionPoint, sourceIntervals, location, tempReg, targetReg,
resolveType DEBUG_ARG(fromBlock) DEBUG_ARG(toBlock));
}
else if (otherTargetInterval != nullptr)
{
assert(otherHalfTargetReg != REG_NA);
assert(otherTargetInterval->registerType == TYP_DOUBLE);

addResolutionForDouble(block, insertionPoint, sourceIntervals, location, tempReg,
otherHalfTargetReg, resolveType DEBUG_ARG(fromBlock) DEBUG_ARG(toBlock));
}
else
#endif // TARGET_ARM
{
assert(sourceIntervals[targetReg] != nullptr);

Expand All @@ -10037,6 +10078,14 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock,
DEBUG_ARG(resolveTypeName[resolveType]));
location[targetReg] = (regNumberSmall)tempReg;
}
#else
assert(sourceIntervals[targetReg] != nullptr);

addResolution(block, insertionPoint, sourceIntervals[targetReg], tempReg,
targetReg DEBUG_ARG(fromBlock) DEBUG_ARG(toBlock)
DEBUG_ARG(resolveTypeName[resolveType]));
location[targetReg] = (regNumberSmall)tempReg;
#endif // TARGET_ARM
targetRegsReady |= targetRegMask;
}
}
Expand Down
246 changes: 246 additions & 0 deletions src/tests/JIT/Regression/JitBlue/Runtime_105619/Runtime_105619.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// Generated by Fuzzlyn v2.1 on 2024-07-28 15:37:46
// Run on Arm Linux
// Seed: 8024459297219020330
// Reduced from 3285.8 KiB to 12.2 KiB in 01:46:03
// Hits JIT assert in Release:
// Assertion failed 'varDsc->IsAlwaysAliveInMemory() || ((regSet.GetMaskVars() & regMask) == 0)' in 'Program:Main(Fuzzlyn.ExecutionServer.IRuntime)' during 'Generate code' (IL size 7170; hash 0xade6b36b; FullOpts)
//
// File: /__w/1/s/src/coreclr/jit/codegencommon.cpp Line: 664
//
using System;
using System.Runtime.CompilerServices;
using Xunit;

public interface I1
{
}

public struct S0
{
public double F0;
public sbyte F1;
public ulong F2;
public int F3;
public ulong F4;
public ulong F6;
public int F7;
public long F8;
public S0(double f0, ulong f2, ulong f4, float f5, ulong f6, int f7, long f8) : this()
{
}
}

public struct S1
{
public int F0;
public S0 F2;
public S0 F3;
public S0 F4;
public S1(int f0, double f1, S0 f2, S0 f3, S0 f4) : this()
{
}
}

public struct S2 : I1
{
public S1 F2;
public ushort F4;
public S1 F6;
public S1 F7;
public S2(sbyte f0, ulong f1, S1 f2, ushort f4, byte f5, S1 f6, S1 f7) : this()
{
}
}

public class C0
{
public S1 F1;
public C0(S1 f1)
{
}
}

public struct S3 : I1
{
public S3(short f0) : this()
{
}
}

public struct S4 : I1
{
public S3 F0;
public S2 F1;
public S4(S3 f0, S2 f1, float f2, S0 f3, int f5) : this()
{
}
}

public struct S5
{
public C0 F0;
public S5(C0 f0, S1 f3) : this()
{
}
}

public class C1
{
public bool F1;
}

public class Program
{
public static IRuntime s_rt;
public static S2 s_13;
public static S1 s_18;
public static bool[] s_22;
public static C0 s_24;
public static ushort[, ] s_31;
public static S1 s_35;
public static bool s_37;
public static S5[] s_44;
public static S4 s_54;
public static S1 s_58;
public static C1[, ] s_59;
public static S4 s_60;
public static S2 s_88;
public static S2[] s_90;

[Fact]
public static void TestEntryPoint()
{
try
{
CollectibleALC alc = new CollectibleALC();
System.Reflection.Assembly asm = alc.LoadFromAssemblyPath(System.Reflection.Assembly.GetExecutingAssembly().Location);
System.Reflection.MethodInfo mi = asm.GetType(typeof(Program).FullName).GetMethod(nameof(MainInner));
System.Type runtimeTy = asm.GetType(typeof(Runtime).FullName);
mi.Invoke(null, new object[] { System.Activator.CreateInstance(runtimeTy) });
} catch {}
}

// Allow reflection lookup on public method
#pragma warning disable xUnit1013
public static void MainInner(IRuntime rt)
{
S0 vr8 = default(S0);
if (s_59[0, 0].F1)
{
bool[] vr9 = new bool[]
{
true
};
s_88 = new S2(s_54.F1.F2.F4.F1, s_24.F1.F2.F4--, new S1(s_35.F2.F3, 0, new S0(-2, 0, 0, 0, 11218621709493063492UL, 450420498, 0), s_60.F1.F7.F2, new S0(0, 0, 0, 0, 0, 1, 0)), s_13.F4--, (byte)s_31[0, 0], new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), s_54.F1.F2);
vr9[0] = vr9[0];
}

s_rt.WriteLine("c_6973", vr8.F2);
s_rt.WriteLine("c_6975", vr8.F4);
s_rt.WriteLine("c_6978", vr8.F7);
I1[] vr10 = new I1[]
{
new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, -3.4028235E+38F, 0, 0, 0), new S0(0, 0, 0, 1, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 0, 0, new S1(1, 0, new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(0, 0, new S0(0, 0, 16728947367172946933UL, 0, 0, 0, 0), new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))),
new S3(0),
new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 1, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 2102657202, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 16794536930986757818UL, 0, 0, 0, 0, 0), new S0(0, 0, 11911619636908597430UL, 0, 0, 0, 0))),
new S3(0),
new S2(0, 0, new S1(-2147483647, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 1, 0, new S1(0, -2, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(1, 0, 0, 0, 0, 0, 0)), new S1(1, 1, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0))),
new S2(0, 0, new S1(0, -1, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 0, 0, new S1(-1, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, -3.4028235E+38F, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))),
new S4(new S3(0), new S2(1, 0, new S1(0, 1, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0)), 1, 0, new S1(1, 0, new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 1, 0), new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))), 0, new S0(0, 0, 0, 0, 0, 0, 0), 0)
};
var vr11 = new S3(0);
var vr12 = s_44[0].F0.F1.F3.F0;
M75(vr11, vr12);
if (s_22[0])
{
S3 vr13 = new S3(0);
try
{
var vr14 = s_54.F0;
var vr15 = s_18.F4.F0;
S3 vr23 = vr14;
}
finally
{
var vr16 = new S3(0);
var vr17 = s_58.F4.F0--;
M75(vr16, vr17);
if (s_37)
{
for (int vr18 = 0; vr18 < 2; vr18++)
{
var vr19 = new S3(0);
vr10[0] = new S4(new S3(0), new S2(1, 5461410436353764379UL, new S1(0, 0, new S0(0, 18446744073709551614UL, 0, 0, 17533718527758593297UL, 0, 0), new S0(0, 8592301711847430801UL, 0, 0, 0, 0, 0), new S0(-1, 7862269010569978854UL, 0, 0, 0, 0, 0)), 0, 0, new S1(0, 0, new S0(0, 3156588052453432602UL, 0, 0, 0, 810788132, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(1, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 15070356010362475091UL, 0, 0))), 0, new S0(0, 0, 0, 0, 0, 0, 0), 0);
vr10 = new I1[]
{
new S2(1, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, -3.4028235E+38F, 0, -1, 0), new S0(0, 7703692348755595801UL, 0, 0, 0, 0, 0)), 0, 0, new S1(1, 1.7976931348623157E+308, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0)), new S1(0, -1, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 3991586019811875011UL, 0, 0, 0, -2147483648, 0))),
new S4(new S3(-1), new S2(0, 9890997199408041578UL, new S1(0, 0, new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 0, -7424873608279851173L), new S0(0, 0, 9698347484967702837UL, 0, 0, 0, 0)), 0, 0, new S1(0, 0, new S0(1, 0, 0, 0, 0, 0, 8154649548600176800L), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, -9223372036854775808L)), new S1(0, 0, new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 778004003835070330UL, 0, 0, 0, 0, 0), new S0(0, 0, 8658698987098108904UL, 0, 0, 0, 0))), 0, new S0(0, 0, 0, 0, 0, 0, 0), 956596481),
new S4(new S3(0), new S2(0, 453734974695362841UL, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, -8941433507005588199L)), 0, 1, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 10794758865549560580UL, 0, 7077610171127139841UL, 1, 0), new S0(1, 0, 0, 0, 0, 0, 0))), 0, new S0(1, 0, 0, 0, 17621340021635995622UL, 0, 0), 1),
new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(0, 0, new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))),
new S2(0, 6130557987521252430UL, new S1(0, -2, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0), new S0(1, 12555188232274105334UL, 0, 0, 0, 0, 0)), 1, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(0, 0, new S0(0, 1828388993980413842UL, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 5800380996067047058UL, 0, 0))),
new S3(1)
};
s_rt.WriteLine("c_7152", vr18);
}

S0 vr20 = new S0(0, 0, 0, 0, 0, 0, 0);
C0 vr21 = new C0(new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)));
s_rt.WriteLine("c_7159", vr20.F6);
s_rt.WriteLine("c_7164", vr21.F1.F0);
s_rt.WriteLine("c_7168", vr21.F1.F2.F2);
s_rt.WriteLine("c_7170", vr21.F1.F2.F4);
s_rt.WriteLine("c_7173", vr21.F1.F2.F7);
s_rt.WriteLine("c_7176", vr21.F1.F3.F1);
s_rt.WriteLine("c_7177", vr21.F1.F3.F2);
s_rt.WriteLine("c_7181", vr21.F1.F3.F6);
s_rt.WriteLine("c_7185", vr21.F1.F4.F1);
s_rt.WriteLine("c_7191", vr21.F1.F4.F7);
s_rt.WriteLine("c_7192", vr21.F1.F4.F8);
}

s_54.F1.F2.F0 = s_90[0].F6.F0++;
}

var vr22 = new S5(new C0(new S1(0, 0, new S0(-2, 0, 0, 0, 0, 0, 0), new S0(1, 0, 0, 0, 0, -1, 0), new S0(0, 0, 0, 0, 0, 0, 0))), new S1(0, 0, new S0(-1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)));
}

vr10 = new I1[]
{
new S4(new S3(-18643), new S2(0, 0, new S1(1, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 11398096482162480173UL, 0, 0, 0, 9223372036854775806L), new S0(0, 0, 0, 0, 0, 2134113955, 0)), 0, 0, new S1(0, 0, new S0(0, 0, 15971873843035984033UL, 0, 5979847448536525346UL, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(1, 0, 0, 0, 11276959574309188693UL, 0, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 0, 0))), 0, new S0(0, 0, 0, 0, 0, 0, 0), 0),
new S3(1),
new S3(0),
new S4(new S3(0), new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 1, 0)), 1, 0, new S1(0, 0, new S0(0, 0, 0, 0, 11829847737932804605UL, 0, 0), new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(0, -2, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 9919258226402299883UL, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))), 0, new S0(0, 0, 0, 0, 0, 1, 0), 0),
new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(-1, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 1, 0), new S0(0, 0, 0, 0, 0, 0, 0))),
new S4(new S3(0), new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 0, 0, new S1(0, 1, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, -1, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(1, 0, 0, 0, 0, 0, 0))), 0, new S0(0, 0, 0, 0, 0, 1, 0), 0),
new S4(new S3(0), new S2(0, 0, new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), 0, 0, new S1(0, 0, new S0(1, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0)), new S1(0, 0, new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0), new S0(0, 0, 0, 0, 0, 0, 0))), 0, new S0(1, 0, 0, 0, 0, 0, 0), 0),
new S3(0),
new S3(0),
new S3(0)
};
}
#pragma warning restore xUnit1013

private static void M75(S3 argThis, double arg1)
{
}
}

public interface IRuntime
{
void WriteLine<T>(string site, T value);
}

public class Runtime : IRuntime
{
public void WriteLine<T>(string site, T value) => System.Console.WriteLine(value);
}

public class CollectibleALC : System.Runtime.Loader.AssemblyLoadContext
{
public CollectibleALC() : base(true)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>

0 comments on commit ac4b7c6

Please sign in to comment.