Skip to content

Remove unsafe code from System.Linq.MaxMin#127845

Draft
EgorBo wants to merge 3 commits intodotnet:mainfrom
EgorBo:reduce-unsafe-maxmin
Draft

Remove unsafe code from System.Linq.MaxMin#127845
EgorBo wants to merge 3 commits intodotnet:mainfrom
EgorBo:reduce-unsafe-maxmin

Conversation

@EgorBo
Copy link
Copy Markdown
Member

@EgorBo EgorBo commented May 6, 2026

Note

This PR is AI-generated.

No asm diffs

Also, added [Intrinsic] on top of non-generics Vector classes. The generic ones do have it already.
The intrinsic on a type helps inliner when it runs out of budget, as a hint that these apis (like Vector.Create(Span) or Vector.CopyTo(Span)) are important.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 6, 2026 00:04
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-linq
See info in area-owners.md if you want to be subscribed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes explicit Unsafe / MemoryMarshal-based vector loads from System.Linq’s integer min/max implementation, switching to span-based Vector*.Create(ReadOnlySpan<T>) to avoid unsafe code in MaxMin.

Changes:

  • Replaced LoadUnsafe + ref/Unsafe.Add iteration with ReadOnlySpan<T> slicing and Vector128/256/512.Create(ReadOnlySpan<T>).
  • Kept the same “first vector + interior vectors + last vector” aggregation pattern while removing address comparisons.

Comment thread src/libraries/System.Linq/src/System/Linq/MaxMin.cs
@EgorBo
Copy link
Copy Markdown
Member Author

EgorBo commented May 6, 2026

@MihuBot

@EgorBo
Copy link
Copy Markdown
Member Author

EgorBo commented May 6, 2026

Note

AI-generated benchmark. Targets only the MaxMin.cs (Min/Max vector path) changes; the new [Intrinsic] attributes on Vector128/256/512 are out of scope.

@EgorBot -arm -amd

using System;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

BenchmarkSwitcher.FromAssembly(typeof(Bench).Assembly).Run(args);

public class Bench
{
    private int[] _ints = default!;
    private long[] _longs = default!;
    private byte[] _bytes = default!;

    [Params(32, 256, 4096)]
    public int Length { get; set; }

    [GlobalSetup]
    public void Setup()
    {
        var rng = new Random(42);
        _ints = new int[Length];
        _longs = new long[Length];
        _bytes = new byte[Length];
        for (int i = 0; i < Length; i++)
        {
            _ints[i] = rng.Next();
            _longs[i] = ((long)rng.Next() << 32) | (uint)rng.Next();
            _bytes[i] = (byte)rng.Next(256);
        }
    }

    [Benchmark] public int IntMax() => _ints.Max();
    [Benchmark] public int IntMin() => _ints.Min();
    [Benchmark] public long LongMax() => _longs.Max();
    [Benchmark] public byte ByteMax() => _bytes.Max();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants