Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.NET 7 exception on Android with EnableLLVM=true #73003

Closed
jonathanpeppers opened this issue Jul 28, 2022 · 15 comments · Fixed by #74301
Closed

.NET 7 exception on Android with EnableLLVM=true #73003

jonathanpeppers opened this issue Jul 28, 2022 · 15 comments · Fixed by #74301

Comments

@jonathanpeppers
Copy link
Member

jonathanpeppers commented Jul 28, 2022

Description

Run with LLVM on an arm64 device, and you can run into:

07-22 09:59:55.062  4374  4374 F mono-rt : [ERROR] FATAL UNHANDLED EXCEPTION: System.PlatformNotSupportedException: Arg_PlatformNotSupported
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.Text.ASCIIUtility.GetIndexOfFirstNonAsciiByte_Intrinsified(Byte* , UIntPtr )
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.Text.Unicode.Utf8Utility.GetPointerToFirstInvalidByte(Byte* , Int32 , Int32& , Int32& )
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.Text.UTF8Encoding.GetCharCount(Byte* , Int32 )
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.String.CreateStringFromEncoding(Byte* , Int32 , Encoding )
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.Text.Encoding.GetString(Byte* , Int32 )
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.String.CreateStringForSByteConstructor(Byte* , Int32 )
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.String.Ctor(SByte* value)
07-22 09:59:55.062  4374  4374 F mono-rt :    at Java.Interop.TypeManager.GetClassName(IntPtr )
07-22 09:59:55.062  4374  4374 F mono-rt :    at Android.Runtime.JNIEnv.RegisterJniNatives(IntPtr , Int32 , IntPtr , IntPtr , Int32 )

Somewhere here:

return (Sse2.IsSupported || (AdvSimd.Arm64.IsSupported && BitConverter.IsLittleEndian))

So I think AdvSimd.Arm64.IsSupported is true, but because GetIndexOfFirstNonAsciiByte_Intrinsified() is not in the AOT profile (it's running under JIT), we get the above exception. It's possible that the above code should also work under JIT.

/cc @fanyang-mono

Reproduction Steps

  1. dotnet new android
  2. dotnet build -t:Run -c Release -p:EnableLLVM=true to run on an arm64 device (in my case a Pixel 5)

Expected behavior

You can use Profiled AOT + LLVM together on Android.

Actual behavior

We get an exception when trying to use Profiled AOT + LLVM together on Android.

Regression?

I don't hit this same exception in .NET 6, but maybe it's just luck?

Known Workarounds

You can turn off profiled AOT, such as -p:AndroidEnableProfiledAot=false or don't use LLVM.

Configuration

.NET 7.0.100-rc.1.22374.1

Other information

No response

@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Jul 28, 2022
@jonathanpeppers
Copy link
Member Author

We also tried passing -O=-simd to the AOT compiler, but ran into a different issue.

But that might be solved by: #72982

@jonathanpeppers jonathanpeppers changed the title .NET 7 crash on Android with EnableLLVM=true .NET 7 exception on Android with EnableLLVM=true Jul 28, 2022
@ghost
Copy link

ghost commented Jul 28, 2022

Tagging subscribers to 'arch-android': @steveisok, @akoeplinger
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

Run with LLVM on an arm64 device, and you can run into:

07-22 09:59:55.062  4374  4374 F mono-rt : [ERROR] FATAL UNHANDLED EXCEPTION: System.PlatformNotSupportedException: Arg_PlatformNotSupported
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.Text.ASCIIUtility.GetIndexOfFirstNonAsciiByte_Intrinsified(Byte* , UIntPtr )
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.Text.Unicode.Utf8Utility.GetPointerToFirstInvalidByte(Byte* , Int32 , Int32& , Int32& )
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.Text.UTF8Encoding.GetCharCount(Byte* , Int32 )
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.String.CreateStringFromEncoding(Byte* , Int32 , Encoding )
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.Text.Encoding.GetString(Byte* , Int32 )
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.String.CreateStringForSByteConstructor(Byte* , Int32 )
07-22 09:59:55.062  4374  4374 F mono-rt :    at System.String.Ctor(SByte* value)
07-22 09:59:55.062  4374  4374 F mono-rt :    at Java.Interop.TypeManager.GetClassName(IntPtr )
07-22 09:59:55.062  4374  4374 F mono-rt :    at Android.Runtime.JNIEnv.RegisterJniNatives(IntPtr , Int32 , IntPtr , IntPtr , Int32 )

Somewhere here:

return (Sse2.IsSupported || (AdvSimd.Arm64.IsSupported && BitConverter.IsLittleEndian))

So I think AdvSimd.Arm64.IsSupported is true, but because GetIndexOfFirstNonAsciiByte_Intrinsified() is not in the AOT profile (it's running under JIT), we get the above exception. It's possible that the above code should also work under JIT.

/cc @fanyang-mono

Reproduction Steps

  1. dotnet new android
  2. dotnet build -t:Run -c Release -p:EnableLLVM=true to run on an arm64 device (in my case a Pixel 5)

Expected behavior

You can use Profiled AOT + LLVM together on Android.

Actual behavior

We get an exception when trying to use Profiled AOT + LLVM together on Android.

Regression?

I don't hit this same exception in .NET 6, but maybe it's just luck?

Known Workarounds

You can turn off profiled AOT, such as -p:AndroidEnableProfiledAot=false or don't use LLVM.

Configuration

.NET 7.0.100-rc.1.22374.1

Other information

No response

Author: jonathanpeppers
Assignees: -
Labels:

os-android, untriaged, area-Codegen-AOT-mono

Milestone: -

@steveisok steveisok removed the untriaged New issue has not been triaged by the area owner label Jul 28, 2022
@steveisok steveisok added this to the 7.0.0 milestone Jul 28, 2022
@steveisok
Copy link
Member

@vargaz Will #72982 solve this?

@vargaz
Copy link
Contributor

vargaz commented Jul 28, 2022

Hopefully.

@steveisok
Copy link
Member

@jonathanpeppers Any chance you can help us validate?

@jonathanpeppers
Copy link
Member Author

I triggered Maestro just now, but I don't see the change there yet: dotnet/android#7217

Maybe we can try it tomorrow.

@fanyang-mono
Copy link
Member

This could be a dup of #60792

jonathanpeppers added a commit to dotnet/android that referenced this issue Aug 3, 2022
`dotnet new android` apps would crash on startup when built with
`-c Release -p:EnableLLVM=true`:

    07-20 08:55:44.642  2983  2983 F monodroid-assembly: Internal p/invoke symbol 'java-interop @ java_interop_jvm_list' (hash: 0x58c48fc8b89cb484) not found in compile-time map.
    ...
    07-20 08:55:44.834  3004  3004 F DEBUG   : signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
    07-20 08:55:44.834  3004  3004 F DEBUG   : Abort message: 'Internal p/invoke symbol 'java-interop @ java_interop_jvm_list' (hash: 0x58c48fc8b89cb484) not found in compile-time map.'

`java_interop_jvm_list` should *never* be called on Android, it is the
result of `new AndroidRuntime()` having not been called yet?

The problem being that the static `Android.App.Application.cctor` was
somehow running *before* `JNIEnv.Initialize()` was complete? And this
only happens with LLVM?

Reviewing the code:

    [UnmanagedCallersOnly]
    internal static unsafe void Initialize (JnienvInitializeArgs* args)
    {
        //...
        SynchronizationContext.SetSynchronizationContext (Android.App.Application.SynchronizationContext);
    }

We do indeed access `Android.App.Application`...

To fix this, we can move this to a new method decorated with
`MethodImplOptions.NoInlining`. Apps built with LLVM now launch for
me.

However, we can't really enable the LLVM `Mono.Android-Tests` quite
yet. Read on!

~~ Known Issues ~~

* dotnet/runtime#73003

Using Profiled AOT and LLVM at the same time can hit:

    [ERROR] FATAL UNHANDLED EXCEPTION: System.PlatformNotSupportedException: Arg_PlatformNotSupported
    at System.Text.ASCIIUtility.GetIndexOfFirstNonAsciiByte_Intrinsified(Byte* , UIntPtr )
    at System.Text.Unicode.Utf8Utility.GetPointerToFirstInvalidByte(Byte* , Int32 , Int32& , Int32& )
    at System.Text.UTF8Encoding.GetCharCount(Byte* , Int32 )
    at System.String.CreateStringFromEncoding(Byte* , Int32 , Encoding )
    at System.Text.Encoding.GetString(Byte* , Int32 )
    at System.String.CreateStringForSByteConstructor(Byte* , Int32 )
    at System.String.Ctor(SByte* value)
    at Java.Interop.TypeManager.GetClassName(IntPtr )
    at Android.Runtime.JNIEnv.RegisterJniNatives(IntPtr , Int32 , IntPtr , IntPtr , Int32 )

For now we can set `AndroidEnableProfiledAot=false` for the LLVM tests.

* dotnet/runtime#73304

Some Java.Interop unit tests fail with:

    System.InvalidOperationException : InvalidOperation_EnumEnded
    at System.ArrayEnumerator.get_Current()
    at Cadenza.Collections.Tests.CollectionContract`1[[System.Int16, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].DisposeCollection(IEnumerable c)
    at Cadenza.Collections.Tests.CollectionContract`1[[System.Int16, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].CopyTo()
    at System.Reflection.MethodInvoker.InterpretedInvoke(Object , Span`1 , BindingFlags )

* https://github.com/xamarin/java.interop/blob/a3de91efdaec04b3927b755a07018e8d26cfdc71/tests/Java.Interop-Tests/Cadenza.Collections/CollectionContract.cs#L205-L221
* https://github.com/xamarin/java.interop/blob/a3de91efdaec04b3927b755a07018e8d26cfdc71/tests/Java.Interop-Tests/Cadenza.Collections/CollectionContract.cs#L85-L86

The `InetAccess` category causes the `Mono.Android-Tests` suite to crash with:

    08-02 21:26:57.581  5154  5173 I NUnit   : System.NetTests.ProxyTest : 646.269 ms
    08-02 21:26:57.593  5154  5173 I droid.NET_Test: Explicit concurrent copying GC freed 20(95KB) AllocSpace objects, 0(0B) LOS objects, 59% free, 1054KB/2590KB, paused 1.469ms total 7.180ms
    08-02 21:26:57.594  5154  5173 I NUnit   : SslTest
    08-02 21:26:57.594  5154  5173 I NUnit   : HttpsShouldWork 
    08-02 21:26:57.858  5154  5181 D NetworkSecurityConfig: No Network Security Config specified, using platform default
    08-02 21:26:58.585  5154  5164 I droid.NET_Test: Background young concurrent copying GC freed 39658(2920KB) AllocSpace objects, 0(0B) LOS objects, 22% free, 1999KB/2590KB, paused 69.607ms total 194.902ms
    08-02 21:26:58.922  5154  5164 I droid.NET_Test: Background concurrent copying GC freed 12412(836KB) AllocSpace objects, 0(0B) LOS objects, 46% free, 6987KB/12MB, paused 2.127ms total 327.448ms
    08-02 21:26:58.953  5154  5181 I monodroid-timing: [1/0] LZ4 decompression time for <assembly_store>; elapsed: 0:0::75000
    08-02 21:26:58.954  5154  5181 W linker  : Warning: "/data/app/Mono.Android.NET_Tests-QcXozuJGB3EpfK6bvDvvMQ==/split_config.x86_64.apk!/lib/x86_64/libaot-System.Formats.Asn1.dll.so" has no DT_SONAME (will use libaot-System.Formats.Asn1.dll.so instead) and will not work when the app moves to API level 23 or later (https://android.googlesource.com/platform/bionic/+/master/missing-soname-enforced-for-api-level-23) (allowing for now because this app's target API level is still 21)
    08-02 21:26:59.037  5154  5181 I monodroid-timing: [1/0] LZ4 decompression time for <assembly_store>; elapsed: 0:0::129000
    08-02 21:26:59.038  5154  5181 W linker  : Warning: "/data/app/Mono.Android.NET_Tests-QcXozuJGB3EpfK6bvDvvMQ==/split_config.x86_64.apk!/lib/x86_64/libaot-System.Runtime.Numerics.dll.so" has no DT_SONAME (will use libaot-System.Runtime.Numerics.dll.so instead) and will not work when the app moves to API level 23 or later (https://android.googlesource.com/platform/bionic/+/master/missing-soname-enforced-for-api-level-23) (allowing for now because this app's target API level is still 21)
    08-02 21:26:56.680  5154  5154 W Instrumentation: type=1400 audit(0.0:432): avc: denied { search } for name="run" dev="vdc" ino=32774 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:varrun_file:s0 tclass=dir permissive=0 app=Mono.Android.NET_Tests
    08-02 21:26:56.770  5154  5154 W Instrumentation: type=1400 audit(0.0:433): avc: denied { ioctl } for path="socket:[49468]" dev="sockfs" ino=49468 ioctlcmd=0x8946 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:r:untrusted_app_25:s0:c512,c768 tclass=udp_socket permissive=0 app=Mono.Android.NET_Tests
    08-02 21:26:56.780  5154  5154 W Instrumentation: type=1400 audit(0.0:434): avc: denied { ioctl } for path="socket:[49468]" dev="sockfs" ino=49468 ioctlcmd=0x8946 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:r:untrusted_app_25:s0:c512,c768 tclass=udp_socket permissive=0 app=Mono.Android.NET_Tests
    08-02 21:27:00.029  1540  1540 I Zygote  : Process 5154 exited due to signal 11 (Segmentation fault)

Not really any useful info here...

Disabled this category for now. We can file an issue for this one,
assuming it is different than the other issues.
jonathanpeppers added a commit to dotnet/android that referenced this issue Aug 5, 2022
`dotnet new android` apps would crash on startup when built with
`-c Release -p:EnableLLVM=true`:

    07-20 08:55:44.642  2983  2983 F monodroid-assembly: Internal p/invoke symbol 'java-interop @ java_interop_jvm_list' (hash: 0x58c48fc8b89cb484) not found in compile-time map.
    ...
    07-20 08:55:44.834  3004  3004 F DEBUG   : signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
    07-20 08:55:44.834  3004  3004 F DEBUG   : Abort message: 'Internal p/invoke symbol 'java-interop @ java_interop_jvm_list' (hash: 0x58c48fc8b89cb484) not found in compile-time map.'

`java_interop_jvm_list` should *never* be called on Android, it is the
result of `new AndroidRuntime()` having not been called yet?

The problem being that the static `Android.App.Application.cctor` was
somehow running *before* `JNIEnv.Initialize()` was complete? And this
only happens with LLVM?

Reviewing the code:

    [UnmanagedCallersOnly]
    internal static unsafe void Initialize (JnienvInitializeArgs* args)
    {
        //...
        SynchronizationContext.SetSynchronizationContext (Android.App.Application.SynchronizationContext);
    }

We do indeed access `Android.App.Application`...

To fix this, we can move this to a new method decorated with
`MethodImplOptions.NoInlining`. Apps built with LLVM now launch for
me.

However, we can't really enable the LLVM `Mono.Android-Tests` quite
yet. Read on!

~~ Known Issues ~~

* dotnet/runtime#73003

Using Profiled AOT and LLVM at the same time can hit:

    [ERROR] FATAL UNHANDLED EXCEPTION: System.PlatformNotSupportedException: Arg_PlatformNotSupported
    at System.Text.ASCIIUtility.GetIndexOfFirstNonAsciiByte_Intrinsified(Byte* , UIntPtr )
    at System.Text.Unicode.Utf8Utility.GetPointerToFirstInvalidByte(Byte* , Int32 , Int32& , Int32& )
    at System.Text.UTF8Encoding.GetCharCount(Byte* , Int32 )
    at System.String.CreateStringFromEncoding(Byte* , Int32 , Encoding )
    at System.Text.Encoding.GetString(Byte* , Int32 )
    at System.String.CreateStringForSByteConstructor(Byte* , Int32 )
    at System.String.Ctor(SByte* value)
    at Java.Interop.TypeManager.GetClassName(IntPtr )
    at Android.Runtime.JNIEnv.RegisterJniNatives(IntPtr , Int32 , IntPtr , IntPtr , Int32 )

For now we can set `AndroidEnableProfiledAot=false` for the LLVM tests.

* dotnet/runtime#73304

Some Java.Interop unit tests fail with:

    System.InvalidOperationException : InvalidOperation_EnumEnded
    at System.ArrayEnumerator.get_Current()
    at Cadenza.Collections.Tests.CollectionContract`1[[System.Int16, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].DisposeCollection(IEnumerable c)
    at Cadenza.Collections.Tests.CollectionContract`1[[System.Int16, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].CopyTo()
    at System.Reflection.MethodInvoker.InterpretedInvoke(Object , Span`1 , BindingFlags )

* https://github.com/xamarin/java.interop/blob/a3de91efdaec04b3927b755a07018e8d26cfdc71/tests/Java.Interop-Tests/Cadenza.Collections/CollectionContract.cs#L205-L221
* https://github.com/xamarin/java.interop/blob/a3de91efdaec04b3927b755a07018e8d26cfdc71/tests/Java.Interop-Tests/Cadenza.Collections/CollectionContract.cs#L85-L86

The `InetAccess` category causes the `Mono.Android-Tests` suite to crash with:

    08-02 21:26:57.581  5154  5173 I NUnit   : System.NetTests.ProxyTest : 646.269 ms
    08-02 21:26:57.593  5154  5173 I droid.NET_Test: Explicit concurrent copying GC freed 20(95KB) AllocSpace objects, 0(0B) LOS objects, 59% free, 1054KB/2590KB, paused 1.469ms total 7.180ms
    08-02 21:26:57.594  5154  5173 I NUnit   : SslTest
    08-02 21:26:57.594  5154  5173 I NUnit   : HttpsShouldWork 
    08-02 21:26:57.858  5154  5181 D NetworkSecurityConfig: No Network Security Config specified, using platform default
    08-02 21:26:58.585  5154  5164 I droid.NET_Test: Background young concurrent copying GC freed 39658(2920KB) AllocSpace objects, 0(0B) LOS objects, 22% free, 1999KB/2590KB, paused 69.607ms total 194.902ms
    08-02 21:26:58.922  5154  5164 I droid.NET_Test: Background concurrent copying GC freed 12412(836KB) AllocSpace objects, 0(0B) LOS objects, 46% free, 6987KB/12MB, paused 2.127ms total 327.448ms
    08-02 21:26:58.953  5154  5181 I monodroid-timing: [1/0] LZ4 decompression time for <assembly_store>; elapsed: 0:0::75000
    08-02 21:26:58.954  5154  5181 W linker  : Warning: "/data/app/Mono.Android.NET_Tests-QcXozuJGB3EpfK6bvDvvMQ==/split_config.x86_64.apk!/lib/x86_64/libaot-System.Formats.Asn1.dll.so" has no DT_SONAME (will use libaot-System.Formats.Asn1.dll.so instead) and will not work when the app moves to API level 23 or later (https://android.googlesource.com/platform/bionic/+/master/missing-soname-enforced-for-api-level-23) (allowing for now because this app's target API level is still 21)
    08-02 21:26:59.037  5154  5181 I monodroid-timing: [1/0] LZ4 decompression time for <assembly_store>; elapsed: 0:0::129000
    08-02 21:26:59.038  5154  5181 W linker  : Warning: "/data/app/Mono.Android.NET_Tests-QcXozuJGB3EpfK6bvDvvMQ==/split_config.x86_64.apk!/lib/x86_64/libaot-System.Runtime.Numerics.dll.so" has no DT_SONAME (will use libaot-System.Runtime.Numerics.dll.so instead) and will not work when the app moves to API level 23 or later (https://android.googlesource.com/platform/bionic/+/master/missing-soname-enforced-for-api-level-23) (allowing for now because this app's target API level is still 21)
    08-02 21:26:56.680  5154  5154 W Instrumentation: type=1400 audit(0.0:432): avc: denied { search } for name="run" dev="vdc" ino=32774 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:varrun_file:s0 tclass=dir permissive=0 app=Mono.Android.NET_Tests
    08-02 21:26:56.770  5154  5154 W Instrumentation: type=1400 audit(0.0:433): avc: denied { ioctl } for path="socket:[49468]" dev="sockfs" ino=49468 ioctlcmd=0x8946 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:r:untrusted_app_25:s0:c512,c768 tclass=udp_socket permissive=0 app=Mono.Android.NET_Tests
    08-02 21:26:56.780  5154  5154 W Instrumentation: type=1400 audit(0.0:434): avc: denied { ioctl } for path="socket:[49468]" dev="sockfs" ino=49468 ioctlcmd=0x8946 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:r:untrusted_app_25:s0:c512,c768 tclass=udp_socket permissive=0 app=Mono.Android.NET_Tests
    08-02 21:27:00.029  1540  1540 I Zygote  : Process 5154 exited due to signal 11 (Segmentation fault)

Not really any useful info here...

Disabled this category for now. We can file an issue for this one,
assuming it is different than the other issues.
@lambdageek lambdageek self-assigned this Aug 17, 2022
@lambdageek
Copy link
Member

this is a nasty problem.

so the issue is.

  1. Android uses profiled AOT pretty much by default now - for fast startup
  2. There are functions that don't get AOTed (they're not early enough or they weren't used in the profile that Android uses)
  3. when you turn on LLVM, the method that makes the decision "should we support intrinsics" gets inlined into something that is part of the AOT profile, so AdvSimd.IsSupported is hardcoded to "true"
    public static unsafe nuint GetIndexOfFirstNonAsciiByte(byte* pBuffer, nuint bufferLength)
  4. But at runtime the actual method that does the work is JITed, so when it checks AdvSimd.IsSupported it gets false

I believe the fix is that when we check for "jit_supported" instead of just checking "are we using LLVM", we need to check "and we don't have the JIT as a fallback". in other words, we have to be in FullAOT or HybridAOT mode.

// Hardware intrinsics are LLVM-only.
if (!COMPILE_LLVM (cfg) && !intrin_group->jit_supported)
goto support_probe_complete;

In other words: profiled AOT cannot benefit from the arm64 intrinsics work we've done for LLVM.

@akoeplinger
Copy link
Member

not a fix for the underlying issue but could we somehow force the intrinsics APIs to be included in the profile so that we still get the LLVM intrinsics handling by default?

@lambdageek
Copy link
Member

not a fix for the underlying issue but could we somehow force the intrinsics APIs to be included in the profile so that we still get the LLVM intrinsics handling by default?

I'm not sure I understand the suggestion.

The issue is: the code that decides if we should use an optimized version of an algorithm sees different IsSupported values than the code that implements the specialized version of the algorithm.

The code that decides is compiled with LLVM AOT and therefore IsSupported is true. The code that implements the algorithm is JITed and locally sees IsSupported as false.

@lambdageek
Copy link
Member

Basically the "fallback" execution engines need to return IsSupported == true if any accelerted execution engine returns IsSupported == true. Otherwise code is unsafe.

@fanyang-mono
Copy link
Member

The reason why Android is seeing this is because Android uses this setup: LLVM AOT with non-LLVM JIT fallback. Currently, AdvSimd.IsSupported only returns true, when LLVM is enabled, no matter it is AOT or JIT.

@akoeplinger
Copy link
Member

The issue is: the code that decides if we should use an optimized version of an algorithm sees different IsSupported values than the code that implements the specialized version of the algorithm.

My suggestion was to make sure we always LLVM AOT the implementation, regardless of whether it is used by the profile, so that no fallback to the JIT occurs.

@lambdageek
Copy link
Member

The issue is: the code that decides if we should use an optimized version of an algorithm sees different IsSupported values than the code that implements the specialized version of the algorithm.

My suggestion was to make sure we always LLVM AOT the implementation, regardless of whether it is used by the profile, so that no fallback to the JIT occurs.

That's hard for a number of reasons:

  1. We don't know what "the implementation" is. In this case it's called after the IsSupported check, but in general the decision about which algorithm to use could be far removed from the place where the intrinsics get used.
  2. The implementation method could use something that we don't know how to AOT like exception filters.

If we had some attribute [ForceAOT(AdvSimd.IsSupported)] then maybe we could address (1), and then (2) could be an error and we could educate users to only use the supported constructs or refactor their code

@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Aug 20, 2022
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Aug 23, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Sep 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants