Miscompiled c++ class with packed attribute on ARM with -Os optimizations http://gcc.gnu.org/PR45070 https://bugs.gentoo.org/331641 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -3036,7 +3036,7 @@ tree-switch-conversion.o : tree-switch-conversion.c $(CONFIG_H) $(SYSTEM_H) \ $(TREE_H) $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) $(TREE_INLINE_H) \ $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(GIMPLE_H) \ $(TREE_PASS_H) $(FLAGS_H) $(EXPR_H) $(BASIC_BLOCK_H) output.h \ - $(GGC_H) $(OBSTACK_H) $(PARAMS_H) $(CPPLIB_H) $(PARAMS_H) + $(GGC_H) $(OBSTACK_H) $(PARAMS_H) $(CPPLIB_H) $(PARAMS_H) langhooks.h tree-complex.o : tree-complex.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \ $(TM_H) $(RTL_H) $(REAL_H) $(FLAGS_H) $(TREE_FLOW_H) $(GIMPLE_H) \ tree-iterator.h $(TREE_PASS_H) tree-ssa-propagate.h $(DIAGNOSTIC_H) --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -13705,7 +13705,8 @@ arm_output_epilogue (rtx sibling) && !crtl->tail_call_emit) { unsigned long mask; - mask = (1 << (arm_size_return_regs() / 4)) - 1; + /* Preserve return values, of any size. */ + mask = (1 << ((arm_size_return_regs() + 3) / 4)) - 1; mask ^= 0xf; mask &= ~saved_regs_mask; reg = 0; --- a/gcc/config/arm/linux-atomic.c +++ b/gcc/config/arm/linux-atomic.c @@ -56,7 +56,7 @@ typedef void (__kernel_dmb_t) (void); \ do { \ tmp = *ptr; \ - failure = __kernel_cmpxchg (tmp, PFX_OP tmp INF_OP val, ptr); \ + failure = __kernel_cmpxchg (tmp, PFX_OP (tmp INF_OP val), ptr); \ } while (failure != 0); \ \ return tmp; \ @@ -88,8 +88,8 @@ FETCH_AND_OP_WORD (nand, ~, &) \ do { \ oldval = *wordptr; \ - newval = ((PFX_OP ((oldval & mask) >> shift) \ - INF_OP (unsigned int) val) << shift) & mask; \ + newval = ((PFX_OP (((oldval & mask) >> shift) \ + INF_OP (unsigned int) val)) << shift) & mask; \ newval |= oldval & ~mask; \ failure = __kernel_cmpxchg (oldval, newval, wordptr); \ } while (failure != 0); \ @@ -97,19 +97,19 @@ FETCH_AND_OP_WORD (nand, ~, &) return (RETURN & mask) >> shift; \ } -SUBWORD_SYNC_OP (add, , +, short, 2, oldval) -SUBWORD_SYNC_OP (sub, , -, short, 2, oldval) -SUBWORD_SYNC_OP (or, , |, short, 2, oldval) -SUBWORD_SYNC_OP (and, , &, short, 2, oldval) -SUBWORD_SYNC_OP (xor, , ^, short, 2, oldval) -SUBWORD_SYNC_OP (nand, ~, &, short, 2, oldval) +SUBWORD_SYNC_OP (add, , +, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (sub, , -, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (or, , |, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (and, , &, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (xor, , ^, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, oldval) -SUBWORD_SYNC_OP (add, , +, char, 1, oldval) -SUBWORD_SYNC_OP (sub, , -, char, 1, oldval) -SUBWORD_SYNC_OP (or, , |, char, 1, oldval) -SUBWORD_SYNC_OP (and, , &, char, 1, oldval) -SUBWORD_SYNC_OP (xor, , ^, char, 1, oldval) -SUBWORD_SYNC_OP (nand, ~, &, char, 1, oldval) +SUBWORD_SYNC_OP (add, , +, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (sub, , -, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (or, , |, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (and, , &, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (xor, , ^, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (nand, ~, &, unsigned char, 1, oldval) #define OP_AND_FETCH_WORD(OP, PFX_OP, INF_OP) \ int HIDDEN \ @@ -119,10 +119,10 @@ SUBWORD_SYNC_OP (nand, ~, &, char, 1, oldval) \ do { \ tmp = *ptr; \ - failure = __kernel_cmpxchg (tmp, PFX_OP tmp INF_OP val, ptr); \ + failure = __kernel_cmpxchg (tmp, PFX_OP (tmp INF_OP val), ptr); \ } while (failure != 0); \ \ - return PFX_OP tmp INF_OP val; \ + return PFX_OP (tmp INF_OP val); \ } OP_AND_FETCH_WORD (add, , +) @@ -132,19 +132,19 @@ OP_AND_FETCH_WORD (and, , &) OP_AND_FETCH_WORD (xor, , ^) OP_AND_FETCH_WORD (nand, ~, &) -SUBWORD_SYNC_OP (add, , +, short, 2, newval) -SUBWORD_SYNC_OP (sub, , -, short, 2, newval) -SUBWORD_SYNC_OP (or, , |, short, 2, newval) -SUBWORD_SYNC_OP (and, , &, short, 2, newval) -SUBWORD_SYNC_OP (xor, , ^, short, 2, newval) -SUBWORD_SYNC_OP (nand, ~, &, short, 2, newval) +SUBWORD_SYNC_OP (add, , +, unsigned short, 2, newval) +SUBWORD_SYNC_OP (sub, , -, unsigned short, 2, newval) +SUBWORD_SYNC_OP (or, , |, unsigned short, 2, newval) +SUBWORD_SYNC_OP (and, , &, unsigned short, 2, newval) +SUBWORD_SYNC_OP (xor, , ^, unsigned short, 2, newval) +SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, newval) -SUBWORD_SYNC_OP (add, , +, char, 1, newval) -SUBWORD_SYNC_OP (sub, , -, char, 1, newval) -SUBWORD_SYNC_OP (or, , |, char, 1, newval) -SUBWORD_SYNC_OP (and, , &, char, 1, newval) -SUBWORD_SYNC_OP (xor, , ^, char, 1, newval) -SUBWORD_SYNC_OP (nand, ~, &, char, 1, newval) +SUBWORD_SYNC_OP (add, , +, unsigned char, 1, newval) +SUBWORD_SYNC_OP (sub, , -, unsigned char, 1, newval) +SUBWORD_SYNC_OP (or, , |, unsigned char, 1, newval) +SUBWORD_SYNC_OP (and, , &, unsigned char, 1, newval) +SUBWORD_SYNC_OP (xor, , ^, unsigned char, 1, newval) +SUBWORD_SYNC_OP (nand, ~, &, unsigned char, 1, newval) int HIDDEN __sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval) @@ -194,8 +194,8 @@ __sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval) } \ } -SUBWORD_VAL_CAS (short, 2) -SUBWORD_VAL_CAS (char, 1) +SUBWORD_VAL_CAS (unsigned short, 2) +SUBWORD_VAL_CAS (unsigned char, 1) typedef unsigned char bool; @@ -216,8 +216,8 @@ __sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval) return (oldval == actual_oldval); \ } -SUBWORD_BOOL_CAS (short, 2) -SUBWORD_BOOL_CAS (char, 1) +SUBWORD_BOOL_CAS (unsigned short, 2) +SUBWORD_BOOL_CAS (unsigned char, 1) void HIDDEN __sync_synchronize (void) @@ -259,8 +259,8 @@ __sync_lock_test_and_set_4 (int *ptr, int val) return (oldval & mask) >> shift; \ } -SUBWORD_TEST_AND_SET (short, 2) -SUBWORD_TEST_AND_SET (char, 1) +SUBWORD_TEST_AND_SET (unsigned short, 2) +SUBWORD_TEST_AND_SET (unsigned char, 1) #define SYNC_LOCK_RELEASE(TYPE, WIDTH) \ void HIDDEN \ --- a/gcc/tree-switch-conversion.c +++ b/gcc/tree-switch-conversion.c @@ -96,6 +96,7 @@ eight) times the number of the actual switch branches. */ #include "diagnostic.h" #include "tree-dump.h" #include "timevar.h" +#include "langhooks.h" /* The main structure of the pass. */ struct switch_conv_info @@ -693,9 +694,11 @@ gen_inbound_check (gimple swtch) /* Make sure we do not generate arithmetics in a subrange. */ if (TREE_TYPE (TREE_TYPE (info.index_expr))) - utype = unsigned_type_for (TREE_TYPE (TREE_TYPE (info.index_expr))); + utype = lang_hooks.types.type_for_mode + (TYPE_MODE (TREE_TYPE (TREE_TYPE (info.index_expr))), 1); else - utype = unsigned_type_for (TREE_TYPE (info.index_expr)); + utype = lang_hooks.types.type_for_mode + (TYPE_MODE (TREE_TYPE (info.index_expr)), 1); /* (end of) block 0 */ gsi = gsi_for_stmt (info.arr_ref_first);