On 16/07/12 14:45, Ulrich Weigand wrote:
> Hello,
> 
> when testing an out-of-tree patch I ran into a latent bug.
> The symptom is error messages along the lines of
> /tmp/cc6q0E3x.s:38: Error: co-processor offset out of range
> caused by an out-of-range reference to a literal pool constant.
> This happens only with -O0.
> 
> This turns out to caused by insn_and_split patterns in sync.md
> used to represent atomic instructions.  Those will (must) always
> be split (usually into some form of compare-and-swap loop).  If
> optimization is on, this split happens shortly after reload,
> before literal pool placement is finalized.
> 
> However, when building with -O0, this split is done very late;
> in fact it happens *after* the machine-dependent reorg pass
> where literal pools are handled.  This means that this pass
> sees the atomic patterns as single insns, and unfortunately,
> since they have no length attribute, they are handled as if
> they had a default length of 4 bytes.
> 
> But since those patterns in the end will expand to at least
> 5-9 actual machine instructions, this default drastically
> underestimates the code size, causing the out of range
> references.
> 
> The patch below adds length attributes giving conservative
> estimates of the final resulting code sizes.  (They could
> probably be made more specific, but since this is relevant
> only for -O0, that's probably not worth the effort.)
> 
> This fixes the problems I was seeing.
> 
> Tested on arm-linux-gnueabi with no regressions.
> 
> OK for mainline?
> 

Hmm, I wonder if we should just unconditionally call split_all_insns()
at the start of md_reorg when -O0.  This would address your problem, but
have the added benefit that the length calculations would be more
accurate.  We're going to have to split the insns anyway during output,
so why not get it over and done with...

R.

> Bye,
> Ulrich
> 
> 
> ChangeLog:
> 
>       * config/arm/sync.md (cas_length): New mode attribute.
>       (atomic_op_length, atomic_nand_length): Likewise.
>       ("atomic_compare_and_swap<mode>_1"): Add length attribute.
>       ("atomic_exchange<mode>"): Likewise.
>       ("atomic_<sync_optab><mode>"): Likewise.
>       ("atomic_nand<mode>"): Likewise.
>       ("atomic_fetch_<sync_optab><mode>"): Likewise.
>       ("atomic_fetch_nand<mode>"): Likewise.
>       ("atomic_<sync_optab>_fetch<mode>"): Likewise.
>       ("atomic_nand_fetch<mode>"): Likewise.
> 
> Index: gcc/config/arm/sync.md
> ===================================================================
> *** gcc/config/arm/sync.md    (revision 189459)
> --- gcc/config/arm/sync.md    (working copy)
> ***************
> *** 127,138 ****
>     {
>       arm_split_compare_and_swap (operands);
>       DONE;
> !   })
>   
>   (define_mode_attr cas_cmp_operand
>     [(SI "arm_add_operand") (DI "cmpdi_operand")])
>   (define_mode_attr cas_cmp_str
>     [(SI "rIL") (DI "rDi")])
>   
>   (define_insn_and_split "atomic_compare_and_swap<mode>_1"
>     [(set (reg:CC_Z CC_REGNUM)                                        ;; bool 
> out
> --- 127,141 ----
>     {
>       arm_split_compare_and_swap (operands);
>       DONE;
> !   }
> !   [(set_attr "length" "32")])
>   
>   (define_mode_attr cas_cmp_operand
>     [(SI "arm_add_operand") (DI "cmpdi_operand")])
>   (define_mode_attr cas_cmp_str
>     [(SI "rIL") (DI "rDi")])
> + (define_mode_attr cas_length
> +   [(SI "32") (DI "44")])
>   
>   (define_insn_and_split "atomic_compare_and_swap<mode>_1"
>     [(set (reg:CC_Z CC_REGNUM)                                        ;; bool 
> out
> ***************
> *** 155,161 ****
>     {
>       arm_split_compare_and_swap (operands);
>       DONE;
> !   })
>   
>   (define_insn_and_split "atomic_exchange<mode>"
>     [(set (match_operand:QHSD 0 "s_register_operand" "=&r")   ;; output
> --- 158,165 ----
>     {
>       arm_split_compare_and_swap (operands);
>       DONE;
> !   }
> !   [(set_attr "length" "<cas_length>")])
>   
>   (define_insn_and_split "atomic_exchange<mode>"
>     [(set (match_operand:QHSD 0 "s_register_operand" "=&r")   ;; output
> ***************
> *** 175,181 ****
>       arm_split_atomic_op (SET, operands[0], NULL, operands[1],
>                        operands[2], operands[3], operands[4]);
>       DONE;
> !   })
>   
>   (define_mode_attr atomic_op_operand
>     [(QI "reg_or_int_operand")
> --- 179,186 ----
>       arm_split_atomic_op (SET, operands[0], NULL, operands[1],
>                        operands[2], operands[3], operands[4]);
>       DONE;
> !   }
> !   [(set_attr "length" "20")])
>   
>   (define_mode_attr atomic_op_operand
>     [(QI "reg_or_int_operand")
> ***************
> *** 186,191 ****
> --- 191,199 ----
>   (define_mode_attr atomic_op_str
>     [(QI "rn") (HI "rn") (SI "rn") (DI "r")])
>   
> + (define_mode_attr atomic_op_length
> +   [(QI "24") (HI "24") (SI "24") (DI "28")])
> + 
>   (define_insn_and_split "atomic_<sync_optab><mode>"
>     [(set (match_operand:QHSD 0 "mem_noofs_operand" "+Ua")
>       (unspec_volatile:QHSD
> ***************
> *** 204,210 ****
>       arm_split_atomic_op (<CODE>, NULL, operands[3], operands[0],
>                        operands[1], operands[2], operands[4]);
>       DONE;
> !   })
>   
>   (define_insn_and_split "atomic_nand<mode>"
>     [(set (match_operand:QHSD 0 "mem_noofs_operand" "+Ua")
> --- 212,222 ----
>       arm_split_atomic_op (<CODE>, NULL, operands[3], operands[0],
>                        operands[1], operands[2], operands[4]);
>       DONE;
> !   }
> !   [(set_attr "length" "<atomic_op_length>")])
> ! 
> ! (define_mode_attr atomic_nand_length
> !   [(QI "28") (HI "28") (SI "28") (DI "32")])
>   
>   (define_insn_and_split "atomic_nand<mode>"
>     [(set (match_operand:QHSD 0 "mem_noofs_operand" "+Ua")
> ***************
> *** 225,231 ****
>       arm_split_atomic_op (NOT, NULL, operands[3], operands[0],
>                        operands[1], operands[2], operands[4]);
>       DONE;
> !   })
>   
>   (define_insn_and_split "atomic_fetch_<sync_optab><mode>"
>     [(set (match_operand:QHSD 0 "s_register_operand" "=&r")
> --- 237,244 ----
>       arm_split_atomic_op (NOT, NULL, operands[3], operands[0],
>                        operands[1], operands[2], operands[4]);
>       DONE;
> !   }
> !   [(set_attr "length" "<atomic_nand_length>")])
>   
>   (define_insn_and_split "atomic_fetch_<sync_optab><mode>"
>     [(set (match_operand:QHSD 0 "s_register_operand" "=&r")
> ***************
> *** 247,253 ****
>       arm_split_atomic_op (<CODE>, operands[0], operands[4], operands[1],
>                        operands[2], operands[3], operands[5]);
>       DONE;
> !   })
>   
>   (define_insn_and_split "atomic_fetch_nand<mode>"
>     [(set (match_operand:QHSD 0 "s_register_operand" "=&r")
> --- 260,267 ----
>       arm_split_atomic_op (<CODE>, operands[0], operands[4], operands[1],
>                        operands[2], operands[3], operands[5]);
>       DONE;
> !   }
> !   [(set_attr "length" "<atomic_op_length>")])
>   
>   (define_insn_and_split "atomic_fetch_nand<mode>"
>     [(set (match_operand:QHSD 0 "s_register_operand" "=&r")
> ***************
> *** 270,276 ****
>       arm_split_atomic_op (NOT, operands[0], operands[4], operands[1],
>                        operands[2], operands[3], operands[5]);
>       DONE;
> !   })
>   
>   (define_insn_and_split "atomic_<sync_optab>_fetch<mode>"
>     [(set (match_operand:QHSD 0 "s_register_operand" "=&r")
> --- 284,291 ----
>       arm_split_atomic_op (NOT, operands[0], operands[4], operands[1],
>                        operands[2], operands[3], operands[5]);
>       DONE;
> !   }
> !   [(set_attr "length" "<atomic_nand_length>")])
>   
>   (define_insn_and_split "atomic_<sync_optab>_fetch<mode>"
>     [(set (match_operand:QHSD 0 "s_register_operand" "=&r")
> ***************
> *** 292,298 ****
>       arm_split_atomic_op (<CODE>, NULL, operands[0], operands[1],
>                        operands[2], operands[3], operands[4]);
>       DONE;
> !   })
>   
>   (define_insn_and_split "atomic_nand_fetch<mode>"
>     [(set (match_operand:QHSD 0 "s_register_operand" "=&r")
> --- 307,314 ----
>       arm_split_atomic_op (<CODE>, NULL, operands[0], operands[1],
>                        operands[2], operands[3], operands[4]);
>       DONE;
> !   }
> !   [(set_attr "length" "<atomic_op_length>")])
>   
>   (define_insn_and_split "atomic_nand_fetch<mode>"
>     [(set (match_operand:QHSD 0 "s_register_operand" "=&r")
> ***************
> *** 315,321 ****
>       arm_split_atomic_op (NOT, NULL, operands[0], operands[1],
>                        operands[2], operands[3], operands[4]);
>       DONE;
> !   })
>   
>   (define_insn "arm_load_exclusive<mode>"
>     [(set (match_operand:SI 0 "s_register_operand" "=r")
> --- 331,338 ----
>       arm_split_atomic_op (NOT, NULL, operands[0], operands[1],
>                        operands[2], operands[3], operands[4]);
>       DONE;
> !   }
> !   [(set_attr "length" "<atomic_nand_length>")])
>   
>   (define_insn "arm_load_exclusive<mode>"
>     [(set (match_operand:SI 0 "s_register_operand" "=r")
> 




Reply via email to