{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/coreclr/issues/18605","repository_url":"https://api.github.com/repos/dotnet/coreclr","labels_url":"https://api.github.com/repos/dotnet/coreclr/issues/18605/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/coreclr/issues/18605/comments","events_url":"https://api.github.com/repos/dotnet/coreclr/issues/18605/events","html_url":"https://github.com/dotnet/coreclr/pull/18605","id":334790740,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk2NjcwMzc3","number":18605,"title":"Optimize SSE/SSE2 Set[All]Vector128","user":{"login":"fiigii","id":1263030,"node_id":"MDQ6VXNlcjEyNjMwMzA=","avatar_url":"https://avatars1.githubusercontent.com/u/1263030?v=4","gravatar_id":"","url":"https://api.github.com/users/fiigii","html_url":"https://github.com/fiigii","followers_url":"https://api.github.com/users/fiigii/followers","following_url":"https://api.github.com/users/fiigii/following{/other_user}","gists_url":"https://api.github.com/users/fiigii/gists{/gist_id}","starred_url":"https://api.github.com/users/fiigii/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fiigii/subscriptions","organizations_url":"https://api.github.com/users/fiigii/orgs","repos_url":"https://api.github.com/users/fiigii/repos","events_url":"https://api.github.com/users/fiigii/events{/privacy}","received_events_url":"https://api.github.com/users/fiigii/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-06-22T08:29:00Z","updated_at":"2018-06-22T13:30:25Z","closed_at":null,"author_association":"COLLABORATOR","pull_request":{"url":"https://api.github.com/repos/dotnet/coreclr/pulls/18605","html_url":"https://github.com/dotnet/coreclr/pull/18605","diff_url":"https://github.com/dotnet/coreclr/pull/18605.diff","patch_url":"https://github.com/dotnet/coreclr/pull/18605.patch"},"body":"This PR moves the implementation of SSE/SSE2 `SetVector128` and `SetAllVector128` from managed code to JIT inside.\r\n1. leveraging new instructions to get smaller code size on new CPUs. This optimization cannot be achieved by managed code because the large function body will block inlining.\r\n2. eliminate the unnecessary \"zero-upper-vector\" code of `SetScalarVector128`.\r\n\r\nMost of the `SetAllVector128` intrinsics get obvious performance improvment.\r\n\r\n| `SetAllVector128<byte>` | AVX2 | SSE4.1 | SSE2 |\r\n|------------|---------|----------|--------------|\r\n| Baseline  | 4.9s | 4.93s | 4.93s |\r\n| Optimized | 2.61s | 2.44s | 4.86s |\r\n| Performance gain | 46.7% | 50.5% | 1.4% |\r\n\r\n| `SetAllVector128<short>` | AVX2 | SSE4.1 | SSE2 |\r\n|----------------------------|-------|---------|------|\r\n| Baseline  | 3.61s | 3.61s | 3.61s |\r\n| Optimized | 2.41s | 3.61s | 3.6s |\r\n| Performance gain | 33% | 0% | 0.2% |\r\n\r\n| `SetAllVector128<int>` | AVX2 | SSE4.1 | SSE2 |\r\n|----------------------------|-------|---------|------|\r\n| Baseline  | 2.47s | 2.41s | 2.41s |\r\n| Optimized | 2.41s | 2.42s | 2.41s|\r\n| Performance gain | 2.4% | 0.04% | 0% |\r\n\r\n| `SetAllVector128<long>` | AVX2 | SSE4.1 | SSE2 |\r\n|----------------------------|-------|---------|------|\r\n| Baseline  | 2.44s | 2.42s | 2.42s |\r\n| Optimized | 2.41s | 2.41s | 2.4s |\r\n| Performance gain | 1.2% | 0.4% | 0.8% |\r\n\r\n| `SetAllVector128<float>` | AVX2 | SSE4.1 | SSE2 |\r\n|----------------------------|-------|---------|------|\r\n| Baseline  | 2.42s | 2.42s | 2.42s |\r\n| Optimized | 1.22s | 1.5s | 1.5s |\r\n| Performance gain | 49.6% | 38% | 38% |\r\n\r\n| `SetAllVector128<double>` | AVX2 | SSE4.1 | SSE2 |\r\n|----------------------------|-------|---------|------|\r\n| Baseline  | 2.43s | 2.46s | 2.46s |\r\n| Optimized | 1.2s | 1.22s | 1.52s |\r\n| Performance gain | 50.6% | 50.4% | 38.2% |\r\n\r\n\r\n`SetVector128` gets significant improvement on `float` and `double`. But the new implementation of `SetVector128<byte/sbyte>` makes performance regression (~5%).\r\n\r\n| `SetVector128<byte>` | AVX2 | SSE4.1 | SSE2 |\r\n|----------------------------|-------|---------|------|\r\n| Baseline  | 35.58s | 35.26s | 35.26s |\r\n| Optimized | 37.47 | 37.52 | 37.4s |\r\n| Performance gain | -5.3% |  -6.4% | -6.1% |\r\n\r\n| `SetVector128<short>` | AVX2 | SSE4.1 | SSE2 |\r\n|----------------------------|-------|---------|------|\r\n| Baseline  | 18.2s  | 18.3s | 18.3s  |\r\n| Optimized | 18.18s | 18.19s | 18.18s |\r\n| Performance gain | 0.1% | 0.6% | 0.7% | \r\n\r\n| `SetVector128<int>` | AVX2 | SSE4.1 | SSE2 |\r\n|----------------------------|-------|---------|------|\r\n| Baseline  | 8.46s | 8.56s | 8.56s |\r\n| Optimized | 8.51s | 8.48s | 8.46s |\r\n| Performance gain | -0.6% | 0.9% | 1% |\r\n\r\n| `SetVector128<long>` | AVX2 | SSE4.1 | SSE2 |\r\n|----------------------------|-------|---------|------|\r\n| Baseline  | 3.67s | 3.64s | 3.64s |\r\n| Optimized | 3.62s | 3.62s | 3.60s |\r\n| Performance gain | 1.4% | 0.5% | 1% |\r\n\r\n| `SetVector128<float>` | AVX2 | SSE4.1 | SSE2 |\r\n|----------------------------|-------|---------|------|\r\n| Baseline  | 8.52s | 8.54s | 8.58s |\r\n| Optimized | 3.67s | 3.66s | 3.62s |\r\n| Performance gain | 56.9% | 57.1% | 58% |\r\n\r\n| `SetVector128<double>` | AVX2 | SSE4.1 | SSE2 |\r\n|----------------------------|-------|---------|------|\r\n| Baseline  | 3.92s | 3.66s | 3.66s |\r\n| Optimized | 2.44s | 2.42s | 2.43s |\r\n| Performance gain | 37.8% | 33.9% | 33.6% |\r\n"},"comment":{"url":"https://api.github.com/repos/dotnet/coreclr/issues/comments/399442846","html_url":"https://github.com/dotnet/coreclr/pull/18605#issuecomment-399442846","issue_url":"https://api.github.com/repos/dotnet/coreclr/issues/18605","id":399442846,"node_id":"MDEyOklzc3VlQ29tbWVudDM5OTQ0Mjg0Ng==","user":{"login":"tannergooding","id":10487869,"node_id":"MDQ6VXNlcjEwNDg3ODY5","avatar_url":"https://avatars3.githubusercontent.com/u/10487869?v=4","gravatar_id":"","url":"https://api.github.com/users/tannergooding","html_url":"https://github.com/tannergooding","followers_url":"https://api.github.com/users/tannergooding/followers","following_url":"https://api.github.com/users/tannergooding/following{/other_user}","gists_url":"https://api.github.com/users/tannergooding/gists{/gist_id}","starred_url":"https://api.github.com/users/tannergooding/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tannergooding/subscriptions","organizations_url":"https://api.github.com/users/tannergooding/orgs","repos_url":"https://api.github.com/users/tannergooding/repos","events_url":"https://api.github.com/users/tannergooding/events{/privacy}","received_events_url":"https://api.github.com/users/tannergooding/received_events","type":"User","site_admin":false},"created_at":"2018-06-22T13:30:25Z","updated_at":"2018-06-22T13:30:25Z","author_association":"MEMBER","body":"I'm happy to see the perf gains, but as I called out on https://github.com/dotnet/coreclr/issues/18436, I don't think moving the implementations back into the JIT is the correct answer here.\r\n\r\nThis is a perfect example of \"inefficient codegen\" and it should be fixable by ensuring:\r\n* We have the correct APIs exposed\r\n* We are emitting good assembly for the exposed APIs\r\n\r\n> This optimization cannot be achieved by managed code because the large function body will block inlining\r\n\r\nMarking the method with `AggressiveInlining` should resolve this.\r\n\r\n> eliminate the unnecessary \"zero-upper-vector\" code of SetScalarVector128.\r\n\r\nWe should be able to make the JIT smart enough to skip this in various circumstances. This is a good opportunity for a peephole optimization, but it could also just start with a simple heuristic of `SetScalarVector128` being directly consumed by another HWIntrinsic API that only reads the lower bits (for example `Sse.MoveScalar` takes `upper` and `value`. If `SetScalarVector128` is passed to `value`, we don't need to zero the upper bits)."}}
{"actor":{"display_login":"tannergooding"}}