Message ID | 28e77f12-9596-e398-8957-98c711ed637a@foss.arm.com |
---|---|
State | New |
Headers | show |
Series | [GCC/ARM] Use bitmap to control cmse_nonsecure_call register clearing | expand |
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 <thomas.preudhomme@arm.com> > > * 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
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 <thomas.preudhomme@arm.com> >> >> * 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 + 1))) + && bitmap_bit_p (to_clear_bitmap, (regno + 1))) emit_move_insn (gen_rtx_REG (DFmode, regno++), CONST0_RTX (DFmode)); else @@ -17178,7 +17193,6 @@ cmse_nonsecure_call_clear_caller_saved (void) seq = get_insns (); end_sequence (); emit_insn_before (seq, insn); - } } }
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 (padding_bits_to_clear != 0) { rtx reg_rtx; - auto_sbitmap to_clear_arg_regs_bitmap (R0_REGNUM + NUM_ARG_REGS); + auto_sbitmap to_clear_arg_regs_bitmap (maxregno + 1); /* Padding bits to clear is not 0 so we know we are dealing with returning a composite type, which only uses r0. Let's make sure that