Re: [PATCH, GCC/ARM] Use bitmap to control cmse_nonsecure_call register clearing
Thanks Kyrill. Committed the attached rebased patch (same patch but without the last hunk because a better fix was done in an earlier commit). Best regards, Thomas On 22/11/17 11:57, Kyrill Tkachov wrote: Hi Thomas, On 15/11/17 17:08, Thomas Preudhomme wrote: Hi, As part of r253256, cmse_nonsecure_entry_clear_before_return has been rewritten to use auto_sbitmap instead of an integer bitfield to control which register needs to be cleared. This commit continue this work in cmse_nonsecure_call_clear_caller_saved. ChangeLog entry is as follows: *** gcc/ChangeLog *** 2017-10-16 Thomas Preud'homme* config/arm/arm.c (cmse_nonsecure_call_clear_caller_saved): Use auto_sbitap instead of integer bitfield to control register needing clearing. Testing: bootstrapped on arm-linux-gnueabihf and no regression in the testsuite. Is this ok for trunk? Ok for trunk. Thanks for this conversion. It's much easier to understand the code without having to think about the bitmasks and shifts. Kyrill Best regards, Thomas diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 106e3edce0d6f2518eb391c436c5213a78d1275b..092cd61d49382101bce9b8c5f04de31965dcdc77 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -17007,10 +17007,11 @@ cmse_nonsecure_call_clear_caller_saved (void) FOR_BB_INSNS (bb, insn) { - uint64_t to_clear_mask, float_mask; + unsigned address_regnum, regno, maxregno = + TARGET_HARD_FLOAT_ABI ? D7_VFP_REGNUM : NUM_ARG_REGS - 1; + auto_sbitmap to_clear_bitmap (maxregno + 1); rtx_insn *seq; rtx pat, call, unspec, reg, cleared_reg, tmp; - unsigned int regno, maxregno; rtx address; CUMULATIVE_ARGS args_so_far_v; cumulative_args_t args_so_far; @@ -17041,18 +17042,21 @@ cmse_nonsecure_call_clear_caller_saved (void) continue; /* Determine the caller-saved registers we need to clear. */ - to_clear_mask = (1LL << (NUM_ARG_REGS)) - 1; - maxregno = NUM_ARG_REGS - 1; + bitmap_clear (to_clear_bitmap); + bitmap_set_range (to_clear_bitmap, R0_REGNUM, NUM_ARG_REGS); + /* Only look at the caller-saved floating point registers in case of -mfloat-abi=hard. For -mfloat-abi=softfp we will be using the lazy store and loads which clear both caller- and callee-saved registers. */ if (TARGET_HARD_FLOAT_ABI) { - float_mask = (1LL << (D7_VFP_REGNUM + 1)) - 1; - float_mask &= ~((1LL << FIRST_VFP_REGNUM) - 1); - to_clear_mask |= float_mask; - maxregno = D7_VFP_REGNUM; + auto_sbitmap float_bitmap (maxregno + 1); + + bitmap_clear (float_bitmap); + bitmap_set_range (float_bitmap, FIRST_VFP_REGNUM, +D7_VFP_REGNUM - FIRST_VFP_REGNUM + 1); + bitmap_ior (to_clear_bitmap, to_clear_bitmap, float_bitmap); } /* Make sure the register used to hold the function address is not @@ -17060,7 +17064,9 @@ cmse_nonsecure_call_clear_caller_saved (void) address = RTVEC_ELT (XVEC (unspec, 0), 0); gcc_assert (MEM_P (address)); gcc_assert (REG_P (XEXP (address, 0))); - to_clear_mask &= ~(1LL << REGNO (XEXP (address, 0))); + address_regnum = REGNO (XEXP (address, 0)); + if (address_regnum < R0_REGNUM + NUM_ARG_REGS) + bitmap_clear_bit (to_clear_bitmap, address_regnum); /* Set basic block of call insn so that df rescan is performed on insns inserted here. */ @@ -17081,6 +17087,7 @@ cmse_nonsecure_call_clear_caller_saved (void) FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter) { rtx arg_rtx; + uint64_t to_clear_args_mask; machine_mode arg_mode = TYPE_MODE (arg_type); if (VOID_TYPE_P (arg_type)) @@ -17093,10 +17100,18 @@ cmse_nonsecure_call_clear_caller_saved (void) arg_rtx = arm_function_arg (args_so_far, arg_mode, arg_type, true); gcc_assert (REG_P (arg_rtx)); - to_clear_mask - &= ~compute_not_to_clear_mask (arg_type, arg_rtx, - REGNO (arg_rtx), - padding_bits_to_clear_ptr); + to_clear_args_mask + = compute_not_to_clear_mask (arg_type, arg_rtx, + REGNO (arg_rtx), + padding_bits_to_clear_ptr); + if (to_clear_args_mask) + { + for (regno = R0_REGNUM; regno <= maxregno; regno++) + { + if (to_clear_args_mask & (1ULL << regno)) + bitmap_clear_bit (to_clear_bitmap, regno); + } + } first_param = false; } @@ -17155,7 +17170,7 @@ cmse_nonsecure_call_clear_caller_saved (void) call. */ for (regno = R0_REGNUM; regno <= maxregno; regno++) { - if (!(to_clear_mask & (1LL << regno))) + if (!bitmap_bit_p (to_clear_bitmap, regno)) continue; /* If regno is an even vfp register and its successor is also to @@ -17164,7 +17179,7 @@ cmse_nonsecure_call_clear_caller_saved (void) { if (TARGET_VFP_DOUBLE && VFP_REGNO_OK_FOR_DOUBLE (regno) - && to_clear_mask & (1LL << (regno +
Re: [PATCH, GCC/ARM] Use bitmap to control cmse_nonsecure_call register clearing
Hi Thomas, On 15/11/17 17:08, Thomas Preudhomme wrote: Hi, As part of r253256, cmse_nonsecure_entry_clear_before_return has been rewritten to use auto_sbitmap instead of an integer bitfield to control which register needs to be cleared. This commit continue this work in cmse_nonsecure_call_clear_caller_saved. ChangeLog entry is as follows: *** gcc/ChangeLog *** 2017-10-16 Thomas Preud'homme* config/arm/arm.c (cmse_nonsecure_call_clear_caller_saved): Use auto_sbitap instead of integer bitfield to control register needing clearing. Testing: bootstrapped on arm-linux-gnueabihf and no regression in the testsuite. Is this ok for trunk? Ok for trunk. Thanks for this conversion. It's much easier to understand the code without having to think about the bitmasks and shifts. Kyrill Best regards, Thomas
[PATCH, GCC/ARM] Use bitmap to control cmse_nonsecure_call register clearing
Hi, As part of r253256, cmse_nonsecure_entry_clear_before_return has been rewritten to use auto_sbitmap instead of an integer bitfield to control which register needs to be cleared. This commit continue this work in cmse_nonsecure_call_clear_caller_saved. ChangeLog entry is as follows: *** gcc/ChangeLog *** 2017-10-16 Thomas Preud'homme* config/arm/arm.c (cmse_nonsecure_call_clear_caller_saved): Use auto_sbitap instead of integer bitfield to control register needing clearing. Testing: bootstrapped on arm-linux-gnueabihf and no regression in the testsuite. Is this ok for trunk? Best regards, Thomas diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 9919f54242d9317125a104f9777d76a85de80e9b..7384b96fea0179334a6010b099df68c8e2a0fc32 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -16990,10 +16990,11 @@ cmse_nonsecure_call_clear_caller_saved (void) FOR_BB_INSNS (bb, insn) { - uint64_t to_clear_mask, float_mask; + unsigned address_regnum, regno, maxregno = + TARGET_HARD_FLOAT_ABI ? D7_VFP_REGNUM : NUM_ARG_REGS - 1; + auto_sbitmap to_clear_bitmap (maxregno + 1); rtx_insn *seq; rtx pat, call, unspec, reg, cleared_reg, tmp; - unsigned int regno, maxregno; rtx address; CUMULATIVE_ARGS args_so_far_v; cumulative_args_t args_so_far; @@ -17024,18 +17025,21 @@ cmse_nonsecure_call_clear_caller_saved (void) continue; /* Determine the caller-saved registers we need to clear. */ - to_clear_mask = (1LL << (NUM_ARG_REGS)) - 1; - maxregno = NUM_ARG_REGS - 1; + bitmap_clear (to_clear_bitmap); + bitmap_set_range (to_clear_bitmap, R0_REGNUM, NUM_ARG_REGS); + /* Only look at the caller-saved floating point registers in case of -mfloat-abi=hard. For -mfloat-abi=softfp we will be using the lazy store and loads which clear both caller- and callee-saved registers. */ if (TARGET_HARD_FLOAT_ABI) { - float_mask = (1LL << (D7_VFP_REGNUM + 1)) - 1; - float_mask &= ~((1LL << FIRST_VFP_REGNUM) - 1); - to_clear_mask |= float_mask; - maxregno = D7_VFP_REGNUM; + auto_sbitmap float_bitmap (maxregno + 1); + + bitmap_clear (float_bitmap); + bitmap_set_range (float_bitmap, FIRST_VFP_REGNUM, +D7_VFP_REGNUM - FIRST_VFP_REGNUM + 1); + bitmap_ior (to_clear_bitmap, to_clear_bitmap, float_bitmap); } /* Make sure the register used to hold the function address is not @@ -17043,7 +17047,9 @@ cmse_nonsecure_call_clear_caller_saved (void) address = RTVEC_ELT (XVEC (unspec, 0), 0); gcc_assert (MEM_P (address)); gcc_assert (REG_P (XEXP (address, 0))); - to_clear_mask &= ~(1LL << REGNO (XEXP (address, 0))); + address_regnum = REGNO (XEXP (address, 0)); + if (address_regnum < R0_REGNUM + NUM_ARG_REGS) + bitmap_clear_bit (to_clear_bitmap, address_regnum); /* Set basic block of call insn so that df rescan is performed on insns inserted here. */ @@ -17064,6 +17070,7 @@ cmse_nonsecure_call_clear_caller_saved (void) FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter) { rtx arg_rtx; + uint64_t to_clear_args_mask; machine_mode arg_mode = TYPE_MODE (arg_type); if (VOID_TYPE_P (arg_type)) @@ -17076,10 +17083,18 @@ cmse_nonsecure_call_clear_caller_saved (void) arg_rtx = arm_function_arg (args_so_far, arg_mode, arg_type, true); gcc_assert (REG_P (arg_rtx)); - to_clear_mask - &= ~compute_not_to_clear_mask (arg_type, arg_rtx, - REGNO (arg_rtx), - padding_bits_to_clear_ptr); + to_clear_args_mask + = compute_not_to_clear_mask (arg_type, arg_rtx, + REGNO (arg_rtx), + padding_bits_to_clear_ptr); + if (to_clear_args_mask) + { + for (regno = R0_REGNUM; regno <= maxregno; regno++) + { + if (to_clear_args_mask & (1ULL << regno)) + bitmap_clear_bit (to_clear_bitmap, regno); + } + } first_param = false; } @@ -17138,7 +17153,7 @@ cmse_nonsecure_call_clear_caller_saved (void) call. */ for (regno = R0_REGNUM; regno <= maxregno; regno++) { - if (!(to_clear_mask & (1LL << regno))) + if (!bitmap_bit_p (to_clear_bitmap, regno)) continue; /* If regno is an even vfp register and its successor is also to @@ -17147,7 +17162,7 @@ cmse_nonsecure_call_clear_caller_saved (void) { if (TARGET_VFP_DOUBLE && VFP_REGNO_OK_FOR_DOUBLE (regno) - && to_clear_mask & (1LL << (regno + 1))) + && bitmap_bit_p (to_clear_bitmap, (regno + 1))) emit_move_insn (gen_rtx_REG (DFmode, regno++), CONST0_RTX (DFmode)); else @@ -17161,7 +17176,6 @@ cmse_nonsecure_call_clear_caller_saved (void) seq = get_insns (); end_sequence (); emit_insn_before (seq, insn); - } } } @@ -25188,7 +25202,7 @@ cmse_nonsecure_entry_clear_before_return (void) if