-
Notifications
You must be signed in to change notification settings - Fork 23
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
Fix undefined behaviour warnings in ir_fold.h #99
Conversation
See php/php-src#17430 I changed the adds, subs, muls to use unsigned arithmetic because on 2-complement systems that's the same as signed arithmetic but without potential UB warnings. This essentially makes the wrapping behaviour defined. I only did this for 32 and 64 bit types because for 8 and 16 bit the operations will do integer promotion, avoiding the issue. There is also `val.i64 < 0 && val.i64 - 1 < 0` that I changed. This is because the second condition would be thrown away by the compiler because `val.i64 < 0` and signed wrapping is undefined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fix looks right. LLVM and HotSpot also use unsigned math at least for add/sub/mul.
IR_FOLD_CONST_I(op1_insn->val.i32 + op2_insn->val.i32); | ||
IR_FOLD_CONST_I(op1_insn->val.u32 + op2_insn->val.u32); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please add a comment: e.g. "Here and below we use unsigned math to prevent undefined signed overflow behavior".
Unfortunately, the fix is incomplete. I see 6 new tests failures on C test suite from MIR project (https://github.com/vnmakarov/mir/tree/master/c-tests). I'll take care. |
The problem is in this rule IR_FOLD(SUB(C_I32, C_I32))
{
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
IR_FOLD_CONST_I(op1_insn->val.u32 - op2_insn->val.u32);
} With |
@nielsdos I reverted this patch. |
No. Actually we need to treat the result of unsigned operation as signed to make the proper sign extension. IR_FOLD(SUB(C_I32, C_I32))
{
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
IR_FOLD_CONST_I((int32_t)(op1_insn->val.u32 - op2_insn->val.u32));
} |
See php/php-src#17430 I changed the adds, subs, muls to use unsigned arithmetic because on 2-complement systems that's the same as signed arithmetic but without potential UB warnings. This essentially makes the wrapping behaviour defined. I only did this for 32 and 64 bit types because for 8 and 16 bit the operations will do integer promotion, avoiding the issue. There is also `val.i64 < 0 && val.i64 - 1 < 0` that I changed. This is because the second condition would be thrown away by the compiler because `val.i64 < 0` and signed wrapping is undefined.
I committed the fixed version 4c3389b |
Thanks for handling this. |
Thanks for catching this. This is definitely my mistake. I'll commit s/u64/u32/. |
See php/php-src#17430
I changed the adds, subs, muls to use unsigned arithmetic because on 2-complement systems that's the same as signed arithmetic but without potential UB warnings. This essentially makes the wrapping behaviour defined. I only did this for 32 and 64 bit types because for 8 and 16 bit the operations will do integer promotion, avoiding the issue.
There is also
val.i64 < 0 && val.i64 - 1 < 0
that I changed. This is because the second condition would be removed by the compiler becauseval.i64 < 0
and signed wrapping is undefined.