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

sys: util: add a sign_extend function #68828

Merged
merged 2 commits into from Feb 26, 2024

Conversation

fabiobaltieri
Copy link
Member

Pretty much the same as https://elixir.bootlin.com/linux/latest/source/include/linux/bitops.h#L186, figured I would not use the 32 suffix since it works fine for smaller types as well but let me know what you think.


Add a sign_extend function, same as the Linux sign_extend32 one. This is useful for sign extending values smaller than 32 bits.

@cfriedt
Copy link
Member

cfriedt commented Feb 10, 2024

@fabiobaltieri - would it be ok to request a few unit tests for this function?

@fabiobaltieri
Copy link
Member Author

fabiobaltieri commented Feb 10, 2024

@fabiobaltieri - would it be ok to request a few unit tests for this function?

Yeah good point, I'll add some tomorrow, back to draft for now.

@fabiobaltieri fabiobaltieri marked this pull request as draft February 10, 2024 01:20
andyross
andyross previously approved these changes Feb 10, 2024
Copy link
Contributor

@andyross andyross left a comment

Choose a reason for hiding this comment

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

Seems very reasonable. FWIW, worth noting that various architectures do this in various ways as a single-instruction primitive (or less, x86 can fold it into a load) instead of a double shift. Are we confident existing compilers optimize that correctly or should we worry about having an override in the toolchain layer? I guess one assumes that if this is how linux does this then gcc and clang are known to get it right?

* @param value The value to sign expand.
* @param index 0 based bit index to sign bit (0 to 31)
*/
static inline int32_t sign_extend(int32_t value, int index)
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be worth considering redefining as a macro with some __typeof__() magic to work with arbitrary input word sizes. Because you just know that someone is going to ask for a sign_extend_64().

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah I tried something like

#define SIGN_EXTEND(value, index) \
       (__typeof__(value))(value << (NUM_BITS(value) - 1 - index)) >> (NUM_BITS(value) - 1 - index)

But then realized that I need the signed version of the type, not the same type, for that to work. :-) If you have any idea... meanwhile I've added a 64 bit variants to anticipate that, Linux has it so why not.

@fabiobaltieri
Copy link
Member Author

  • Added a 64 bit variant and some unit tests

Are we confident existing compilers optimize that correctly or should we worry about having an override in the toolchain layer? I guess one assumes that if this is how linux does this then gcc and clang are known to get it right?

Wow good question, I'd be shocked if there's a chance to optimize it further and it's not done in Linux, my code looks something like this on ARM:

575             return (int32_t)(value << shift) >> shift;
   0x000000c8 <+128>:   sbfx    r4, r4, #0, #12

So it looks like it's doing the right thing.

@fabiobaltieri
Copy link
Member Author

Funny I found my bug in my driver while trying to figure why that optimization was only showing up once while I was expecting it to be there twice, thanks @andyross. :-)

cfriedt
cfriedt previously approved these changes Feb 10, 2024
Copy link
Member

@cfriedt cfriedt left a comment

Choose a reason for hiding this comment

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

LGTM. If there happens to be another rev for some reason, it would be best to split it into one code commit and one test commit.

asemjonovs
asemjonovs previously approved these changes Feb 12, 2024
@fabiobaltieri fabiobaltieri added this to the v3.7.0 milestone Feb 13, 2024
@peter-mitsis
Copy link
Collaborator

Two questions ...

  1. Is it worthwhile adding an assert check to verify the range of the index parameter? Recall that shifting by more bits than the type allows leads to undefined behavior. For example, on x86 value >> 34 is equivalent to value >> 2 if value is 32 bits wide. However, on ARM, IIRC, the same expression would evaluate to 0.
  2. Should the index parameter be an unsigned type? It does not make much sense to have a negative bit index.

@fabiobaltieri
Copy link
Member Author

@peter-mitsis sure, can't think of any reason against either, added few asserts, switched index to uint8_t

@cfriedt
Copy link
Member

cfriedt commented Feb 13, 2024

@fabiobaltieri - if you are re-spinning anyway, would it be possible to separate the implementation in the 1st commit, and the test in a 2nd commit?

@fabiobaltieri
Copy link
Member Author

@fabiobaltieri - if you are re-spinning anyway, would it be possible to separate the implementation in the 1st commit, and the test in a 2nd commit?

Yes sorry forgot, split.

About the assert, turns out those are unhappy with some tests, I dropped it again for now will look into it later

andyross
andyross previously approved these changes Feb 13, 2024
Add a sign_extend and sign_extend_64 functions, same as the Linux
sign_extend32 and sign_extend64 one. This is useful for sign extending
values smaller than 32 bits.

Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
Add tests for the sign extend functions.

Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
@fabiobaltieri
Copy link
Member Author

nvm fixed the assert issue and reintroduced again, test split on its own pr

@fabiobaltieri fabiobaltieri merged commit 9e1eec9 into zephyrproject-rtos:main Feb 26, 2024
18 checks passed
@fabiobaltieri fabiobaltieri deleted the sign-extend branch February 26, 2024 11:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Base OS Base OS Library (lib/os) area: Testsuite Testsuite
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants