Skip to content

Commit fd11209

Browse files
authored
Use the register of CAST for contained index operator (#74275)
* Rename test files * Fix index scale for cast * Do not contain index if indir is not containable. * Revert "Do not contain index if indir is not containable." This reverts commit e79d17d92ceb0eed5ae1bfd03c2d1d6b171ab17f. * Instead try to contain the LEA * IsSafeToContainMem() check * Do IsSafeToContainMem() only if needed * Add test case * Fix merge error * fix the test case * review comment
1 parent db4a954 commit fd11209

6 files changed

Lines changed: 89 additions & 24 deletions

File tree

src/coreclr/jit/codegenarmarch.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4458,12 +4458,26 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea)
44584458
else
44594459
{
44604460
#ifdef TARGET_ARM64
4461-
// Handle LEA with "contained" BFIZ
4462-
if (index->isContained() && index->OperIs(GT_BFIZ))
4461+
4462+
if (index->isContained())
44634463
{
4464-
assert(scale == 0);
4465-
scale = (DWORD)index->gtGetOp2()->AsIntConCommon()->IconValue();
4466-
index = index->gtGetOp1()->gtGetOp1();
4464+
if (index->OperIs(GT_BFIZ))
4465+
{
4466+
// Handle LEA with "contained" BFIZ
4467+
assert(scale == 0);
4468+
scale = (DWORD)index->gtGetOp2()->AsIntConCommon()->IconValue();
4469+
index = index->gtGetOp1()->gtGetOp1();
4470+
}
4471+
else if (index->OperIs(GT_CAST))
4472+
{
4473+
index = index->AsCast()->gtGetOp1();
4474+
}
4475+
else
4476+
{
4477+
// Only BFIZ/CAST nodes should be present for for contained index on ARM64.
4478+
// If there are more, we need to handle them here.
4479+
unreached();
4480+
}
44674481
}
44684482
#endif
44694483

src/coreclr/jit/lower.cpp

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5362,29 +5362,43 @@ bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, GenTree* par
53625362
}
53635363

53645364
#ifdef TARGET_ARM64
5365-
if ((index != nullptr) && index->OperIs(GT_CAST) && (scale == 1) && (offset == 0) && varTypeIsByte(targetType))
5366-
{
5367-
index->AsCast()->CastOp()->ClearContained(); // Uncontain any memory operands.
5368-
MakeSrcContained(addrMode, index);
5369-
}
53705365

5371-
// Check if we can "contain" LEA(BFIZ) in order to extend 32bit index to 64bit as part of load/store.
5372-
if ((index != nullptr) && index->OperIs(GT_BFIZ) && index->gtGetOp1()->OperIs(GT_CAST) &&
5373-
index->gtGetOp2()->IsCnsIntOrI() && !varTypeIsStruct(targetType))
5366+
if (index != nullptr)
53745367
{
5375-
// BFIZ node is a binary op where op1 is GT_CAST and op2 is GT_CNS_INT
5376-
GenTreeCast* cast = index->gtGetOp1()->AsCast();
5377-
assert(cast->isContained());
5368+
if (index->OperIs(GT_CAST) && (scale == 1) && (offset == 0) && varTypeIsByte(targetType))
5369+
{
5370+
if (IsSafeToContainMem(parent, index))
5371+
{
5372+
// Check containment safety against the parent node - this will ensure that LEA with the contained
5373+
// index will itself always be contained. We do not support uncontained LEAs with contained indices.
5374+
index->AsCast()->CastOp()->ClearContained(); // Uncontain any memory operands.
5375+
MakeSrcContained(addrMode, index);
5376+
}
5377+
}
5378+
else if (index->OperIs(GT_BFIZ) && index->gtGetOp1()->OperIs(GT_CAST) && index->gtGetOp2()->IsCnsIntOrI() &&
5379+
!varTypeIsStruct(targetType))
5380+
{
5381+
// Check if we can "contain" LEA(BFIZ) in order to extend 32bit index to 64bit as part of load/store.
5382+
// BFIZ node is a binary op where op1 is GT_CAST and op2 is GT_CNS_INT
5383+
GenTreeCast* cast = index->gtGetOp1()->AsCast();
5384+
assert(cast->isContained());
53785385

5379-
const unsigned shiftBy = (unsigned)index->gtGetOp2()->AsIntCon()->IconValue();
5386+
const unsigned shiftBy = (unsigned)index->gtGetOp2()->AsIntCon()->IconValue();
53805387

5381-
// 'scale' and 'offset' have to be unset since we're going to use [base + index * SXTW/UXTW scale] form
5382-
// where there is no room for additional offsets/scales on ARM64. 'shiftBy' has to match target's width.
5383-
if (cast->CastOp()->TypeIs(TYP_INT) && cast->TypeIs(TYP_LONG) && (genTypeSize(targetType) == (1U << shiftBy)) &&
5384-
(scale == 1) && (offset == 0))
5385-
{
5386-
// TODO: Make sure that genCreateAddrMode marks such BFIZ candidates as GTF_DONT_CSE for better CQ.
5387-
MakeSrcContained(addrMode, index);
5388+
// 'scale' and 'offset' have to be unset since we're going to use [base + index * SXTW/UXTW scale] form
5389+
// where there is no room for additional offsets/scales on ARM64. 'shiftBy' has to match target's width.
5390+
if (cast->CastOp()->TypeIs(TYP_INT) && cast->TypeIs(TYP_LONG) &&
5391+
(genTypeSize(targetType) == (1U << shiftBy)) && (scale == 1) && (offset == 0))
5392+
{
5393+
if (IsSafeToContainMem(parent, index))
5394+
{
5395+
// Check containment safety against the parent node - this will ensure that LEA with the contained
5396+
// index will itself always be contained. We do not support uncontained LEAs with contained indices.
5397+
5398+
// TODO: Make sure that genCreateAddrMode marks such BFIZ candidates as GTF_DONT_CSE for better CQ.
5399+
MakeSrcContained(addrMode, index);
5400+
}
5401+
}
53885402
}
53895403
}
53905404
#endif
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Runtime.CompilerServices;
5+
6+
unsafe class Runtime_74117
7+
{
8+
public unsafe static int Main(string[] args)
9+
{
10+
byte a = 5;
11+
Problem(ref a, 0);
12+
return 100;
13+
}
14+
15+
[MethodImpl(MethodImplOptions.NoInlining)]
16+
static byte GetByte() => 1;
17+
18+
[MethodImpl(MethodImplOptions.NoInlining)]
19+
private static void Problem(ref byte x, int a)
20+
{
21+
JitUse(&a);
22+
Unsafe.Add(ref x, a) = GetByte();
23+
}
24+
25+
[MethodImpl(MethodImplOptions.NoInlining)]
26+
public static void JitUse<T>(T* arg) where T : unmanaged { }
27+
}

src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.csproj renamed to src/tests/JIT/Regression/JitBlue/Runtime_74117/Runtime_74117.csproj

File renamed without changes.

src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_73821.cs renamed to src/tests/JIT/Regression/JitBlue/Runtime_74373/Runtime_74373.cs

File renamed without changes.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<Optimize>True</Optimize>
5+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
6+
</PropertyGroup>
7+
<ItemGroup>
8+
<Compile Include="$(MSBuildProjectName).cs" />
9+
</ItemGroup>
10+
</Project>

0 commit comments

Comments
 (0)