Skip to content

Vector2.One is not always <1, 1> in some case (silent bad codegen) #54466

@ryancheung

Description

@ryancheung

Reduced repro - Windows x64, repros at commit 9c0bf21 :

  1. Compile with optimizations on:
using System;
using System.Numerics;
using System.Runtime.CompilerServices;

t(1, 1, 1, 1, Vector2.One, Vector2.One, Vector2.One, Vector2.One);

[MethodImplAttribute(MethodImplOptions.NoInlining)]
static void t(int a1, int a2, int a3, int a4, Vector2 x1, Vector2 x2, Vector2 x3, Vector2 x4)
{
   if (x1 != Vector2.One) Console.WriteLine("FAIL");
}
  1. Run (with COMPlus_TieredCompilation=0)

Actual result:

  • Checked build: Assertion failed 'isFloatReg(dstReg) && isFloatReg(srcReg)' in '$:$(System.String[])' during 'Generate code'
  • Release build: FAIL

Expected result: passes without asserts or errors


I have some code:

        public static void DrawSpriteFrame(this CommandBuffer commandBuffer, SpriteFrame spriteFrame, Vector2 position, Color color, float layerDepth = 0f)
        {
            DrawSpriteFrame(commandBuffer, spriteFrame, position, null, color, Vector2.One, 0f, SpriteEffects.None, layerDepth);
        }

        public static void DrawSpriteFrame(this CommandBuffer commandBuffer, SpriteFrame spriteFrame, Vector2 position, Rectangle areaRewrite, Color color, float layerDepth = 0f)
        {
            DrawSpriteFrame(commandBuffer, spriteFrame, position, areaRewrite, color, Vector2.One, 0f, SpriteEffects.None, layerDepth);
        }

        public static void DrawSpriteFrame(this CommandBuffer commandBuffer, SpriteFrame spriteFrame, Vector2 position, Size sizeRewrite, Color color, float layerDepth = 0f)
        {
            var areaRewrite = new Rectangle(0, 0, sizeRewrite.Width, sizeRewrite.Height);
            DrawSpriteFrame(commandBuffer, spriteFrame, position, areaRewrite, color, Vector2.One, 0f, SpriteEffects.None, layerDepth);
        }

        public static void DrawSpriteFrame(this CommandBuffer commandBuffer, SpriteFrame spriteFrame, Vector2 position, Rectangle? areaRewrite, Color color, Vector2 scale, float rotation = 0f, SpriteEffects spriteEffects = SpriteEffects.None, float layerDepth = 0f)
        {
            if (scale != Vector2.One)
            {
                Console.WriteLine("Scale is: {0}", scale);
                return;
            }
            ...
        }

The Vector2.One passed to method calls is not actually equal to Vector2.One in NativeAOT sometimes. It returns <6.28E-43, 5.27E-43> instead. But everything is fine is CoreCLR. And I'm sure the value of the scale parameter is always <1, 1> in all code logic.

The workaround I found: Change the method call parameter Vector2.One to new Vector2(1, 1).

Which looks like:

        public static void DrawSpriteFrame(this CommandBuffer commandBuffer, SpriteFrame spriteFrame, Vector2 position, Color color, float layerDepth = 0f)
        {
            DrawSpriteFrame(commandBuffer, spriteFrame, position, null, color, new Vector2(1f, 1f), 0f, SpriteEffects.None, layerDepth);
        }

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIbug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions