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

GCC error - missing cast in MVE arm_biquad_cascade_df1_q15 #58

Open
kjbracey opened this issue Oct 19, 2022 · 12 comments
Open

GCC error - missing cast in MVE arm_biquad_cascade_df1_q15 #58

kjbracey opened this issue Oct 19, 2022 · 12 comments
Labels
enhancement New feature or request

Comments

@kjbracey
Copy link

kjbracey commented Oct 19, 2022

We've had a report that GCC doesn't like the MVE version of arm_biquad_cascade_df1_q15. And its complaint seems valid:

bCoeffs2 =
vsetq_lane_s32(vgetq_lane_s32((q31x4_t) bCoeffs0, 3), (q31x4_t) bCoeffs2, 3);
bCoeffs3 =
vsetq_lane_s32(vgetq_lane_s32((q31x4_t) bCoeffs1, 3), (q31x4_t) bCoeffs3, 3);

arm_biquad_cascade_df1_q15.c:106:13: error: incompatible types when assigning to type 'q15x8_t' {aka 'int16x8_t'} from type 'int32x4_t'

I'd say you need an explicit (q15x8_t) cast on the output of vsetq_lane_s32.

What's not clear to me is why armclang accepts it, which it does. Indeed, armclang doesn't seem to require the existing (q31x4_t) casts either, at least within that C file.

Pasting the same function into some other C++ code I had handy made armclang produce the equivalent error, unless you have 3 casts. Is it performing implicit conversion in C mode, maybe? Intentionally? Possible armclang bug?

@christophe0606 christophe0606 added the enhancement New feature or request label Oct 21, 2022
@kjbracey
Copy link
Author

While looking around build systems, I've just noticed that GCC's behaviour here is configurable via -flax-vector-conversions.

@christophe0606
Copy link
Contributor

It is advised to use -flax-vector-conversions because there are some cases where the use of the intrinsic is valid but gcc is nevertheless generating a warning.

But, I'll look at above case because I think it needs the cast.

@kjbracey
Copy link
Author

kjbracey commented Oct 26, 2022

Any thoughts on the C vs C++ difference in armclang (if that's what it is)? I don't see such a thing documented. Can you control it?

There were no other reports from our customer of GCC problems without the -flax-vector-conversions, so it's possible that GCC is better than it used to be.

@christophe0606
Copy link
Contributor

I don't know the differences between C and C++ for handling the intrinsics.

So you confirm that for the arm_biquad_cascade_df1_q15, you get cast warnings in C++ with armclang but none from C ?

Can you share the compilation options you used ? I'll try to reproduce and then check with our compiler team.

@kjbracey
Copy link
Author

kjbracey commented Oct 27, 2022

Yes, I've stripped it down, and confirm that it's a C/C++ difference

Given this source:

#include "arm_mve.h"

int16x8_t test(int32x4_t a)
{
    return a;
}

That's accepted without warnings if it's input as C:

armclang --target=arm-arm-none-eabi -mcpu=cortex-m55 -O2 -S vectest.c

But rejected with the type error (not warning) if it comes in as vectest.cpp. Compiler version 6.18.

Conceptually I see no reason for C to be more lax here, and I've not found this documented as being by design. Sure, C++ is more type strict on a few scalar things, like enums and bools, but C has always been just as strict as C++ on aggregates, which these vectors effectively are.

(GCC 11.3 rejects it as either C or C++, unless you have -flax-vector-conversions.)

@christophe0606
Copy link
Contributor

Compiler team tells me that the C and C++ standards are not managing implicit casts in the same way. But otherwise, for this specific example they can't say more.

@kjbracey
Copy link
Author

Arm C Language Extensions document just says that such implicit conversions are not portable (for C or C++) - and to use vreinterpretq. (It doesn't actually say explicit conversions via casts are portable.)

So the C compiler is free to give the error, and I think it would be far more helpful if it did. Was trying to check whether this has changed since armcc, but don't have a copy to hand.

@kjbracey
Copy link
Author

kjbracey commented Mar 6, 2023

Minor update, as I found some discussion elsewhere - clang and armclang do also have the -flax-vector-conversions flag, slightly extended to support three options: =none, =int, =all.

Documentation for clang says the default is -flax-vector-conversions=int = -flax-vector-conversions, but as we saw above, the default is actually none for C++.

You can get armclang to reject the above code in C by adding -flax-vector-conversions=none or -fno-lax-vector-conversions. I'll be adding that to my own projects. (I've made too many mistakes from its absence!)

Which in turn means that the change in #65 technically needs to also be applied for armclang. If someone has made vectors strict in the global CMake compile flags (or a future clang has tightened up), it needs to be overridden for the CMSIS-DSP target.

@christophe0606
Copy link
Contributor

@kjbracey Thanks for the feedback !

christophe0606 added a commit that referenced this issue Mar 9, 2023
In relation with issue #58

When HELIUM, MVEF or MVEI are used as cmake options, the option
LAXVECTORCONVERSIONS can be set to ON or OFF to enable / disable
lax vector conversions in GCC or ArmClang.

Currently, CMSIS-DSP won't build if lax vector conversions are disabled.
The option is ON by default.
@christophe0606
Copy link
Contributor

@kjbracey I have added a cmake option to enable / disable lax vector conversions when building for Helium with gcc or ArmClang.
By default it is ON since currently some parts of the library won't build without it.

@kjbracey
Copy link
Author

kjbracey commented Mar 9, 2023

You could scale that back a bit, as I assume you don't actually need "=all", as that's not the default for clang (since clang 10), and it's laxer than gcc, which only permits the integer->integer laxness. So you can set clang to "=integer", or just use the same simple flags as gcc.

"=all" is the clang-9-and-earlier default behaviour and what -flax-vector-conversions used to mean for it, but they changed it to match gcc.

https://releases.llvm.org/10.0.0/tools/clang/docs/ReleaseNotes.html

@christophe0606
Copy link
Contributor

@kjbracey You're right. It build without problems with integer. I have just pushed the change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants