From: Bernd Edlinger Date: Mon, 6 Jun 2016 12:31:59 +0000 (+0000) Subject: re PR c/24414 (Old-style asms don't clobber memory) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=93671519e202e3bc5ab592bb6318aa738e4ae58f;p=gcc.git re PR c/24414 (Old-style asms don't clobber memory) gcc/ 2016-06-06 Bernd Edlinger PR c/24414 * cfgexpand.c (expand_asm_loc): Remove handling for ADDR_EXPR. Implicitly clobber memory for basic asm with non-empty assembler string. Use targetm.md_asm_adjust also here. * compare-elim.c (arithmetic_flags_clobber_p): Use asm_noperands here. * final.c (final_scan_insn): Handle basic asm in PARALLEL block. * gimple.c (gimple_asm_clobbers_memory_p): Handle basic asm with non-empty assembler string. * ira.c (compute_regs_asm_clobbered): Use asm_noperands here. * recog.c (asm_noperands): Handle basic asm in PARALLEL block. (decode_asm_operands): Handle basic asm in PARALLEL block. (extract_insn): Handle basic asm in PARALLEL block. * doc/extend.texi: Mention new behavior of basic asm. * config/ia64/ia64 (rtx_needs_barrier): Handle ASM_INPUT here. * config/pa/pa.c (branch_to_delay_slot_p, branch_needs_nop_p, branch_needs_nop_p): Use asm_noperands. gcc/testsuite/ 2016-06-06 Bernd Edlinger PR c/24414 * gcc.target/i386/pr24414.c: New test. From-SVN: r237133 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a0255b1d399..3bffb744b8d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2016-06-06 Bernd Edlinger + + PR c/24414 + * cfgexpand.c (expand_asm_loc): Remove handling for ADDR_EXPR. + Implicitly clobber memory for basic asm with non-empty assembler + string. Use targetm.md_asm_adjust also here. + * compare-elim.c (arithmetic_flags_clobber_p): Use asm_noperands here. + * final.c (final_scan_insn): Handle basic asm in PARALLEL block. + * gimple.c (gimple_asm_clobbers_memory_p): Handle basic asm with + non-empty assembler string. + * ira.c (compute_regs_asm_clobbered): Use asm_noperands here. + * recog.c (asm_noperands): Handle basic asm in PARALLEL block. + (decode_asm_operands): Handle basic asm in PARALLEL block. + (extract_insn): Handle basic asm in PARALLEL block. + * doc/extend.texi: Mention new behavior of basic asm. + * config/ia64/ia64 (rtx_needs_barrier): Handle ASM_INPUT here. + * config/pa/pa.c (branch_to_delay_slot_p, branch_needs_nop_p, + branch_needs_nop_p): Use asm_noperands. + 2016-06-06 Jose E. Marchesi * config/sparc/sparc.md (cpu): Add niagara7 cpu type. diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 56ef71dfbab..e4ddb3aac9f 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -2674,15 +2674,40 @@ expand_asm_loc (tree string, int vol, location_t locus) { rtx body; - if (TREE_CODE (string) == ADDR_EXPR) - string = TREE_OPERAND (string, 0); - body = gen_rtx_ASM_INPUT_loc (VOIDmode, ggc_strdup (TREE_STRING_POINTER (string)), locus); MEM_VOLATILE_P (body) = vol; + /* Non-empty basic ASM implicitly clobbers memory. */ + if (TREE_STRING_LENGTH (string) != 0) + { + rtx asm_op, clob; + unsigned i, nclobbers; + auto_vec input_rvec, output_rvec; + auto_vec constraints; + auto_vec clobber_rvec; + HARD_REG_SET clobbered_regs; + CLEAR_HARD_REG_SET (clobbered_regs); + + clob = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)); + clobber_rvec.safe_push (clob); + + if (targetm.md_asm_adjust) + targetm.md_asm_adjust (output_rvec, input_rvec, + constraints, clobber_rvec, + clobbered_regs); + + asm_op = body; + nclobbers = clobber_rvec.length (); + body = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (1 + nclobbers)); + + XVECEXP (body, 0, 0) = asm_op; + for (i = 0; i < nclobbers; i++) + XVECEXP (body, 0, i + 1) = gen_rtx_CLOBBER (VOIDmode, clobber_rvec[i]); + } + emit_insn (body); } diff --git a/gcc/compare-elim.c b/gcc/compare-elim.c index a5ce2bfcf2c..e7fdce83734 100644 --- a/gcc/compare-elim.c +++ b/gcc/compare-elim.c @@ -162,7 +162,7 @@ arithmetic_flags_clobber_p (rtx_insn *insn) if (!NONJUMP_INSN_P (insn)) return false; pat = PATTERN (insn); - if (extract_asm_operands (pat)) + if (asm_noperands (pat) >= 0) return false; if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) == 2) diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 742123f401e..7f439d3fe82 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -6558,6 +6558,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred) case USE: case CALL: case ASM_OPERANDS: + case ASM_INPUT: need_barrier |= rtx_needs_barrier (pat, flags, pred); break; diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 8b1c8327c79..a78405ab792 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -6442,7 +6442,7 @@ branch_to_delay_slot_p (rtx_insn *insn) the branch is followed by an asm. */ if (!insn || GET_CODE (PATTERN (insn)) == ASM_INPUT - || extract_asm_operands (PATTERN (insn)) != NULL_RTX + || asm_noperands (PATTERN (insn)) >= 0 || get_attr_length (insn) > 0) break; } @@ -6473,7 +6473,7 @@ branch_needs_nop_p (rtx_insn *insn) return TRUE; if (!(GET_CODE (PATTERN (insn)) == ASM_INPUT - || extract_asm_operands (PATTERN (insn)) != NULL_RTX) + || asm_noperands (PATTERN (insn)) >= 0) && get_attr_length (insn) > 0) break; } @@ -6497,7 +6497,7 @@ use_skip_p (rtx_insn *insn) /* We can't rely on the length of asms, so we can't skip asms. */ if (!insn || GET_CODE (PATTERN (insn)) == ASM_INPUT - || extract_asm_operands (PATTERN (insn)) != NULL_RTX) + || asm_noperands (PATTERN (insn)) >= 0) break; if (get_attr_length (insn) == 4 && jump_insn == next_active_insn (insn)) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index c85e6dbb5fe..7208f33e76c 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -7581,7 +7581,7 @@ means there is no way to communicate to the compiler what is happening inside them. GCC has no visibility of symbols in the @code{asm} and may discard them as unreferenced. It also does not know about side effects of the assembler code, such as modifications to memory or registers. Unlike -some compilers, GCC assumes that no changes to either memory or registers +some compilers, GCC assumes that no changes to general purpose registers occur. This assumption may change in a future release. To avoid complications from future changes to the semantics and the @@ -7605,6 +7605,10 @@ all basic @code{asm} blocks use the assembler dialect specified by the Basic @code{asm} provides no mechanism to provide different assembler strings for different dialects. +For basic @code{asm} with non-empty assembler string GCC assumes +the assembler block does not change any general purpose registers, +but it may read or write any globally accessible variable. + Here is an example of basic @code{asm} for i386: @example diff --git a/gcc/final.c b/gcc/final.c index 55cf509611f..5b04311218e 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -2566,6 +2566,10 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, (*debug_hooks->source_line) (last_linenum, last_filename, last_discriminator, is_stmt); + if (GET_CODE (body) == PARALLEL + && GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT) + body = XVECEXP (body, 0, 0); + if (GET_CODE (body) == ASM_INPUT) { const char *string = XSTR (body, 0); diff --git a/gcc/gimple.c b/gcc/gimple.c index 226b0801072..75a1ed8ee0b 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -2583,6 +2583,10 @@ gimple_asm_clobbers_memory_p (const gasm *stmt) return true; } + /* Non-empty basic ASM implicitly clobbers memory. */ + if (gimple_asm_input_p (stmt) && strlen (gimple_asm_string (stmt)) != 0) + return true; + return false; } diff --git a/gcc/ira.c b/gcc/ira.c index 3c4e3b6bd08..c66bb9e78fc 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -2233,7 +2233,7 @@ compute_regs_asm_clobbered (void) { df_ref def; - if (NONDEBUG_INSN_P (insn) && extract_asm_operands (PATTERN (insn))) + if (NONDEBUG_INSN_P (insn) && asm_noperands (PATTERN (insn)) >= 0) FOR_EACH_INSN_DEF (def, insn) { unsigned int dregno = DF_REF_REGNO (def); diff --git a/gcc/recog.c b/gcc/recog.c index 92b2aa31a77..80d1779f7e1 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -1470,22 +1470,34 @@ extract_asm_operands (rtx body) /* If BODY is an insn body that uses ASM_OPERANDS, return the number of operands (both input and output) in the insn. + If BODY is an insn body that uses ASM_INPUT with CLOBBERS in PARALLEL, + return 0. Otherwise return -1. */ int asm_noperands (const_rtx body) { rtx asm_op = extract_asm_operands (CONST_CAST_RTX (body)); - int n_sets = 0; + int i, n_sets = 0; if (asm_op == NULL) - return -1; + { + if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) >= 2 + && GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT) + { + /* body is [(asm_input ...) (clobber (reg ...))...]. */ + for (i = XVECLEN (body, 0) - 1; i > 0; i--) + if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER) + return -1; + return 0; + } + return -1; + } if (GET_CODE (body) == SET) n_sets = 1; else if (GET_CODE (body) == PARALLEL) { - int i; if (GET_CODE (XVECEXP (body, 0, 0)) == SET) { /* Multiple output operands, or 1 output plus some clobbers: @@ -1540,9 +1552,12 @@ asm_noperands (const_rtx body) the locations of the operands within the insn into the vector OPERAND_LOCS, and the constraints for the operands into CONSTRAINTS. Write the modes of the operands into MODES. + Write the location info into LOC. Return the assembler-template. + If BODY is an insn body that uses ASM_INPUT with CLOBBERS in PARALLEL, + return the basic assembly string. - If MODES, OPERAND_LOCS, CONSTRAINTS or OPERANDS is 0, + If LOC, MODES, OPERAND_LOCS, CONSTRAINTS or OPERANDS is 0, we don't store that info. */ const char * @@ -1603,6 +1618,12 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs, } nbase = i; } + else if (GET_CODE (asmop) == ASM_INPUT) + { + if (loc) + *loc = ASM_INPUT_SOURCE_LOCATION (asmop); + return XSTR (asmop, 0); + } break; } @@ -2245,7 +2266,8 @@ extract_insn (rtx_insn *insn) case PARALLEL: if ((GET_CODE (XVECEXP (body, 0, 0)) == SET && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS) - || GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS) + || GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS + || GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT) goto asm_insn; else goto normal_insn; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e5d1407c9e3..0940e916b16 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-06-06 Bernd Edlinger + + PR c/24414 + * gcc.target/i386/pr24414.c: New test. + 2016-06-06 Jose E. Marchesi * gcc.target/sparc/vis4misc.c: New file. diff --git a/gcc/testsuite/gcc.target/i386/pr24414.c b/gcc/testsuite/gcc.target/i386/pr24414.c new file mode 100644 index 00000000000..bd12f0c8492 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr24414.c @@ -0,0 +1,13 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +int test; + +int +main () +{ + int x = test; + asm ("movl $1,test"); + if (x + test != 1) + __builtin_trap (); + return 0; +}