* Fix old printing issues.
* add a repro test that doesn't require crossgen2.
* Check that all `ADDR` sources are marked as DONT_CSE.
* Fix text(no size) diffs found by SPMI.
* Add a question/comment.
* Update src/coreclr/src/jit/compiler.hpp
Co-Authored-By: Eugene Rozenfeld <erozen@microsoft.com>
* Delete an optimization that was not proved to be correct.
* Delete useless code.
* Revert "Fix text(no size) diffs found by SPMI."
This reverts commit
cd24383210b9ed22f7ea3640005217021f9fbd63.
// IND(ADDR(IND(x)) == IND(x)
if (op1->gtOper == GT_ADDR)
{
- if (op1->AsOp()->gtOp1->gtOper == GT_IND && (op1->AsOp()->gtOp1->gtFlags & GTF_IND_ARR_INDEX) == 0)
+ GenTreeUnOp* addr = op1->AsUnOp();
+ GenTree* indir = addr->gtGetOp1();
+ if (indir->OperIs(GT_IND) && ((indir->gtFlags & GTF_IND_ARR_INDEX) == 0))
{
- op1 = op1->AsOp()->gtOp1->AsOp()->gtOp1;
+ op1 = indir->AsIndir()->Addr();
}
}
}
{
return op1->AsOp()->gtOp1;
}
+ else
+ {
+ // Addr source can't be CSE-ed.
+ op1->SetDoNotCSE();
+ }
}
}
return;
}
break;
+ case GT_ADDR:
+ assert(!op1->CanCSE());
default:
break;
printf(" %s", eeGetFieldName(tree->AsField()->gtFldHnd), 0);
}
+ gtDispCommonEndLine(tree);
+
if (tree->AsField()->gtFldObj && !topOnly)
{
gtDispVN(tree);
ClearRegOptional();
}
+ bool CanCSE() const
+ {
+ return ((gtFlags & GTF_DONT_CSE) == 0);
+ }
+
+ void SetDoNotCSE()
+ {
+ gtFlags |= GTF_DONT_CSE;
+ }
+
+ void ClearDoNotCSE()
+ {
+ gtFlags &= ~GTF_DONT_CSE;
+ }
+
bool IsReverseOp() const
{
return (gtFlags & GTF_REVERSE_OPS) ? true : false;
tree->ChangeOper(GT_IND);
GenTreeIndir* const indir = tree->AsIndir();
indir->Addr() = indexAddr;
+ bool canCSE = indir->CanCSE();
indir->gtFlags = GTF_IND_ARR_INDEX | (indexAddr->gtFlags & GTF_ALL_EFFECT);
+ if (!canCSE)
+ {
+ indir->SetDoNotCSE();
+ }
#ifdef DEBUG
indexAddr->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED;
return tree;
}
-
- /* op1 of a GT_ADDR is an l-value. Only r-values can be CSEed */
- op1->gtFlags |= GTF_DONT_CSE;
break;
case GT_COLON:
tree->SetOper(GT_LCL_VAR);
tree->AsLclVarCommon()->SetLclNum(fieldLclIndex);
tree->gtType = fieldType;
- tree->gtFlags &= GTF_NODE_MASK;
- tree->gtFlags &= ~GTF_GLOB_REF;
+ tree->gtFlags &= GTF_NODE_MASK; // Note: that clears all flags except `GTF_COLON_COND`.
if (parent->gtOper == GT_ASG)
{
if (verbose)
{
printf("\nFound contiguous assignments from a SIMD vector to memory.\n");
- printf("From " FMT_BB ", stmt", block->bbNum);
+ printf("From " FMT_BB ", stmt ", block->bbNum);
printStmtID(stmt);
printf(" to stmt");
printStmtID(lastStmt);
#ifdef DEBUG
if (verbose)
{
- printf("\n" FMT_BB " stmt", block->bbNum);
+ printf("\n" FMT_BB " stmt ", block->bbNum);
printStmtID(stmt);
printf("(before)\n");
gtDispStmt(stmt);
}
#endif
+ assert(!simdStructNode->CanCSE());
+ simdStructNode->ClearDoNotCSE();
+
tree = gtNewAssignNode(dstNode, simdStructNode);
stmt->SetRootNode(tree);
size_t elemTypSize = (elemTyp == TYP_STRUCT) ? elemStructSize : genTypeSize(elemTyp);
size_t indTypeSize = genTypeSize(indType);
- if ((indType == TYP_REF) && (varTypeIsStruct(elemTyp)))
- {
- // indType is TYP_REF and elemTyp is TYP_STRUCT
- //
- // We have a pointer to a static that is a Boxed Struct
- //
- return elem;
- }
- else if (indTypeSize > elemTypSize)
+ if (indTypeSize > elemTypSize)
{
// Reading beyong the end of 'elem'
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// The test showed CSE issues with struct return retyping.
+
+using System;
+using System.Runtime.CompilerServices;
+
+struct RefWrapper
+{
+ public Object a; // a ref field
+}
+
+class TestStructs
+{
+ static RefWrapper[] arr;
+
+ public static RefWrapper GetElement() // 8 byte size return will be retyped as a ref.
+ {
+ return arr[0];
+ }
+
+ public static int Main()
+ {
+ RefWrapper a = new RefWrapper();
+ arr = new RefWrapper[1];
+ arr[0] = a;
+
+ RefWrapper e = GetElement(); // force struct retyping to ref.
+ arr[0] = e; // a struct typed copy.
+ return 100;
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <DebugType>None</DebugType>
+ <Optimize>True</Optimize>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="$(MSBuildProjectName).cs" />
+ </ItemGroup>
+</Project>