Its me
Its me

Reputation: 49

Strict aliasing error for fp16 to fp32 conversion

I have a function for fp16 to fp32 conversion

static float fp16_to_fp32(const short in){
    signed int t1, t2, t3;
    float out = 0;

    t1 = (in & 0x7fff) << 13 + 0x38000000;
    t2 = (in & 0x8000) << 16;
    t3 = in & 0x7c00;
    
    t1 = (t3==0 ? 0 : t1);
    t1 |= t2;

    *((unsigned int*)&out) = t1;
    
    return out;
}

error: dereferencing typed-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing] in ((unsigned int)&out) = t1;

How can I solve this? (can't change type of argument in )

Upvotes: 0

Views: 200

Answers (3)

Lundin
Lundin

Reputation: 214780

You can use type punning through union to dodge strict aliasing:

union type_punner
{
  unsigned int i;
  float f;
} out = {.i = t1};
return out.f;

This assuming int and float are the same size, so it isn't very portable code.

You could also compile with -fno-strict-aliasing.

Upvotes: 1

MikeCAT
MikeCAT

Reputation: 75062

You can use memcpy() for copying data.

Also note that + operator has higher precedence than << operator, so the line t1 = (in & 0x7fff) << 13 + 0x38000000; won't work as expected.

#include <string.h> /* for memcpy() */

static float fp16_to_fp32(const short in){
    signed int t1, t2, t3;
    float out = 0;

    t1 = ((in & 0x7fff) << 13) + 0x38000000; /* add parenthesis */
    t2 = (in & 0x8000) << 16;
    t3 = in & 0x7c00;
    
    t1 = (t3==0 ? 0 : t1);
    t1 |= t2;

    memcpy(&out, &t1, sizeof(out)); /* use memcpy() for copying */
    
    return out;
}

Upvotes: 4

syzztem
syzztem

Reputation: 92

Try declaring out as a float pointer then return *out

Upvotes: 0

Related Questions