diff options
author | Jakub Jelinek <jakub@redhat.com> | 2008-12-23 00:34:07 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2008-12-23 00:34:07 +0100 |
commit | 805903b5251042186344830f35161eaec7fedb69 (patch) | |
tree | 5971e3d6c2cd233e84f89d0395f6d5c1beecc681 | |
parent | d797a4ed797b6ba140e7fc9059835b74335cbcf5 (diff) | |
download | gcc-805903b5251042186344830f35161eaec7fedb69.zip gcc-805903b5251042186344830f35161eaec7fedb69.tar.gz gcc-805903b5251042186344830f35161eaec7fedb69.tar.bz2 |
re PR target/38488 (x86_64 generates much larger and slightly slower code for memset)
* config/i386/i386.c (expand_setmem_via_rep_stos): Add ORIG_VALUE
argument. If ORIG_VALUE is const0_rtx and COUNT is constant,
set MEM_SIZE on DESTMEM.
(ix86_expand_setmem): Adjust callers.
PR target/38488
* expr.h (get_mem_align_offset): New prototype.
* emit-rtl.c (get_mem_align_offset): New function.
* config/i386/i386.c (expand_movmem_via_rep_mov): Set MEM_SIZE correctly.
(expand_constant_movmem_prologue, expand_constant_setmem_prologue):
New functions.
(ix86_expand_movmem): Optimize if COUNT_EXP
is constant, desired_align > align and dst & (desired_align - 1)
is computable at compile time.
(ix86_expand_setmem): Likewise.
* builtins.c (get_memory_rtx): Try to derive MEM_ATTRS from not yet
resolved SAVE_EXPR or POINTER_PLUS_EXPR.
From-SVN: r142891
-rw-r--r-- | gcc/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/builtins.c | 24 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 256 | ||||
-rw-r--r-- | gcc/emit-rtl.c | 84 | ||||
-rw-r--r-- | gcc/expr.h | 5 |
5 files changed, 359 insertions, 31 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2ab5852..61b5a80 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2008-12-23 Jakub Jelinek <jakub@redhat.com> + + * config/i386/i386.c (expand_setmem_via_rep_stos): Add ORIG_VALUE + argument. If ORIG_VALUE is const0_rtx and COUNT is constant, + set MEM_SIZE on DESTMEM. + (ix86_expand_setmem): Adjust callers. + + PR target/38488 + * expr.h (get_mem_align_offset): New prototype. + * emit-rtl.c (get_mem_align_offset): New function. + * config/i386/i386.c (expand_movmem_via_rep_mov): Set MEM_SIZE correctly. + (expand_constant_movmem_prologue, expand_constant_setmem_prologue): + New functions. + (ix86_expand_movmem): Optimize if COUNT_EXP + is constant, desired_align > align and dst & (desired_align - 1) + is computable at compile time. + (ix86_expand_setmem): Likewise. + + * builtins.c (get_memory_rtx): Try to derive MEM_ATTRS from not yet + resolved SAVE_EXPR or POINTER_PLUS_EXPR. + 2008-12-22 Uros Bizjak <ubizjak@gmail.com> * config/alpha/alpha.h (ASM_OUTPUT_EXTERNAL): New macro. diff --git a/gcc/builtins.c b/gcc/builtins.c index d64290d..607d7dd 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -1094,8 +1094,17 @@ expand_builtin_prefetch (tree exp) static rtx get_memory_rtx (tree exp, tree len) { - rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_NORMAL); - rtx mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr)); + tree orig_exp = exp; + rtx addr, mem; + HOST_WIDE_INT off; + + /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived + from its expression, for expr->a.b only <variable>.a.b is recorded. */ + if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp)) + exp = TREE_OPERAND (exp, 0); + + addr = expand_expr (orig_exp, NULL_RTX, ptr_mode, EXPAND_NORMAL); + mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr)); /* Get an expression we can use to find the attributes to assign to MEM. If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if @@ -1104,7 +1113,13 @@ get_memory_rtx (tree exp, tree len) && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0)))) exp = TREE_OPERAND (exp, 0); - if (TREE_CODE (exp) == ADDR_EXPR) + off = 0; + if (TREE_CODE (exp) == POINTER_PLUS_EXPR + && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR + && host_integerp (TREE_OPERAND (exp, 1), 0) + && (off = tree_low_cst (TREE_OPERAND (exp, 1), 0)) > 0) + exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); + else if (TREE_CODE (exp) == ADDR_EXPR) exp = TREE_OPERAND (exp, 0); else if (POINTER_TYPE_P (TREE_TYPE (exp))) exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp); @@ -1118,6 +1133,9 @@ get_memory_rtx (tree exp, tree len) { set_mem_attributes (mem, exp, 0); + if (off) + mem = adjust_automodify_address_nv (mem, BLKmode, NULL, off); + /* Allow the string and memory builtins to overflow from one field into another, see http://gcc.gnu.org/PR23561. Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index bae3f42..9ad964b 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -16636,6 +16636,22 @@ expand_movmem_via_rep_mov (rtx destmem, rtx srcmem, destexp = gen_rtx_PLUS (Pmode, destptr, countreg); srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg); } + if (CONST_INT_P (count)) + { + count = GEN_INT (INTVAL (count) + & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1)); + destmem = shallow_copy_rtx (destmem); + srcmem = shallow_copy_rtx (srcmem); + set_mem_size (destmem, count); + set_mem_size (srcmem, count); + } + else + { + if (MEM_SIZE (destmem)) + set_mem_size (destmem, NULL_RTX); + if (MEM_SIZE (srcmem)) + set_mem_size (srcmem, NULL_RTX); + } emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg, destexp, srcexp)); } @@ -16644,8 +16660,8 @@ expand_movmem_via_rep_mov (rtx destmem, rtx srcmem, Arguments have same meaning as for previous function */ static void expand_setmem_via_rep_stos (rtx destmem, rtx destptr, rtx value, - rtx count, - enum machine_mode mode) + rtx count, enum machine_mode mode, + rtx orig_value) { rtx destexp; rtx countreg; @@ -16662,6 +16678,15 @@ expand_setmem_via_rep_stos (rtx destmem, rtx destptr, rtx value, } else destexp = gen_rtx_PLUS (Pmode, destptr, countreg); + if (orig_value == const0_rtx && CONST_INT_P (count)) + { + count = GEN_INT (INTVAL (count) + & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1)); + destmem = shallow_copy_rtx (destmem); + set_mem_size (destmem, count); + } + else if (MEM_SIZE (destmem)) + set_mem_size (destmem, NULL_RTX); emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp)); } @@ -16995,6 +17020,85 @@ expand_movmem_prologue (rtx destmem, rtx srcmem, gcc_assert (desired_alignment <= 8); } +/* Copy enough from DST to SRC to align DST known to DESIRED_ALIGN. + ALIGN_BYTES is how many bytes need to be copied. */ +static rtx +expand_constant_movmem_prologue (rtx dst, rtx *srcp, rtx destreg, rtx srcreg, + int desired_align, int align_bytes) +{ + rtx src = *srcp; + rtx src_size, dst_size; + int off = 0; + int src_align_bytes = get_mem_align_offset (src, desired_align * BITS_PER_UNIT); + if (src_align_bytes >= 0) + src_align_bytes = desired_align - src_align_bytes; + src_size = MEM_SIZE (src); + dst_size = MEM_SIZE (dst); + if (align_bytes & 1) + { + dst = adjust_automodify_address_nv (dst, QImode, destreg, 0); + src = adjust_automodify_address_nv (src, QImode, srcreg, 0); + off = 1; + emit_insn (gen_strmov (destreg, dst, srcreg, src)); + } + if (align_bytes & 2) + { + dst = adjust_automodify_address_nv (dst, HImode, destreg, off); + src = adjust_automodify_address_nv (src, HImode, srcreg, off); + if (MEM_ALIGN (dst) < 2 * BITS_PER_UNIT) + set_mem_align (dst, 2 * BITS_PER_UNIT); + if (src_align_bytes >= 0 + && (src_align_bytes & 1) == (align_bytes & 1) + && MEM_ALIGN (src) < 2 * BITS_PER_UNIT) + set_mem_align (src, 2 * BITS_PER_UNIT); + off = 2; + emit_insn (gen_strmov (destreg, dst, srcreg, src)); + } + if (align_bytes & 4) + { + dst = adjust_automodify_address_nv (dst, SImode, destreg, off); + src = adjust_automodify_address_nv (src, SImode, srcreg, off); + if (MEM_ALIGN (dst) < 4 * BITS_PER_UNIT) + set_mem_align (dst, 4 * BITS_PER_UNIT); + if (src_align_bytes >= 0) + { + unsigned int src_align = 0; + if ((src_align_bytes & 3) == (align_bytes & 3)) + src_align = 4; + else if ((src_align_bytes & 1) == (align_bytes & 1)) + src_align = 2; + if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT) + set_mem_align (src, src_align * BITS_PER_UNIT); + } + off = 4; + emit_insn (gen_strmov (destreg, dst, srcreg, src)); + } + dst = adjust_automodify_address_nv (dst, BLKmode, destreg, off); + src = adjust_automodify_address_nv (src, BLKmode, srcreg, off); + if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT) + set_mem_align (dst, desired_align * BITS_PER_UNIT); + if (src_align_bytes >= 0) + { + unsigned int src_align = 0; + if ((src_align_bytes & 7) == (align_bytes & 7)) + src_align = 8; + else if ((src_align_bytes & 3) == (align_bytes & 3)) + src_align = 4; + else if ((src_align_bytes & 1) == (align_bytes & 1)) + src_align = 2; + if (src_align > (unsigned int) desired_align) + src_align = desired_align; + if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT) + set_mem_align (src, src_align * BITS_PER_UNIT); + } + if (dst_size) + set_mem_size (dst, GEN_INT (INTVAL (dst_size) - align_bytes)); + if (src_size) + set_mem_size (dst, GEN_INT (INTVAL (src_size) - align_bytes)); + *srcp = src; + return dst; +} + /* Set enough from DEST to align DEST known to by aligned by ALIGN to DESIRED_ALIGNMENT. */ static void @@ -17031,6 +17135,47 @@ expand_setmem_prologue (rtx destmem, rtx destptr, rtx value, rtx count, gcc_assert (desired_alignment <= 8); } +/* Set enough from DST to align DST known to by aligned by ALIGN to + DESIRED_ALIGN. ALIGN_BYTES is how many bytes need to be stored. */ +static rtx +expand_constant_setmem_prologue (rtx dst, rtx destreg, rtx value, + int desired_align, int align_bytes) +{ + int off = 0; + rtx dst_size = MEM_SIZE (dst); + if (align_bytes & 1) + { + dst = adjust_automodify_address_nv (dst, QImode, destreg, 0); + off = 1; + emit_insn (gen_strset (destreg, dst, + gen_lowpart (QImode, value))); + } + if (align_bytes & 2) + { + dst = adjust_automodify_address_nv (dst, HImode, destreg, off); + if (MEM_ALIGN (dst) < 2 * BITS_PER_UNIT) + set_mem_align (dst, 2 * BITS_PER_UNIT); + off = 2; + emit_insn (gen_strset (destreg, dst, + gen_lowpart (HImode, value))); + } + if (align_bytes & 4) + { + dst = adjust_automodify_address_nv (dst, SImode, destreg, off); + if (MEM_ALIGN (dst) < 4 * BITS_PER_UNIT) + set_mem_align (dst, 4 * BITS_PER_UNIT); + off = 4; + emit_insn (gen_strset (destreg, dst, + gen_lowpart (SImode, value))); + } + dst = adjust_automodify_address_nv (dst, BLKmode, destreg, off); + if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT) + set_mem_align (dst, desired_align * BITS_PER_UNIT); + if (dst_size) + set_mem_size (dst, GEN_INT (INTVAL (dst_size) - align_bytes)); + return dst; +} + /* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation. */ static enum stringop_alg decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset, @@ -17262,7 +17407,7 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp, unsigned HOST_WIDE_INT count = 0; HOST_WIDE_INT expected_size = -1; int size_needed = 0, epilogue_size_needed; - int desired_align = 0; + int desired_align = 0, align_bytes = 0; enum stringop_alg alg; int dynamic_check; bool need_zero_guard = false; @@ -17273,6 +17418,11 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp, if (CONST_INT_P (expected_align_exp) && INTVAL (expected_align_exp) > align) align = INTVAL (expected_align_exp); + /* ALIGN is the minimum of destination and source alignment, but we care here + just about destination alignment. */ + else if (MEM_ALIGN (dst) > (unsigned HOST_WIDE_INT) align * BITS_PER_UNIT) + align = MEM_ALIGN (dst) / BITS_PER_UNIT; + if (CONST_INT_P (count_exp)) count = expected_size = INTVAL (count_exp); if (CONST_INT_P (expected_size_exp) && count == 0) @@ -17332,7 +17482,20 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp, /* Alignment code needs count to be in register. */ if (CONST_INT_P (count_exp) && desired_align > align) - count_exp = force_reg (counter_mode (count_exp), count_exp); + { + if (INTVAL (count_exp) > desired_align + && INTVAL (count_exp) > size_needed) + { + align_bytes + = get_mem_align_offset (dst, desired_align * BITS_PER_UNIT); + if (align_bytes <= 0) + align_bytes = 0; + else + align_bytes = desired_align - align_bytes; + } + if (align_bytes == 0) + count_exp = force_reg (counter_mode (count_exp), count_exp); + } gcc_assert (desired_align >= 1 && align >= 1); /* Ensure that alignment prologue won't copy past end of block. */ @@ -17391,14 +17554,26 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp, if (desired_align > align) { - /* Except for the first move in epilogue, we no longer know - constant offset in aliasing info. It don't seems to worth - the pain to maintain it for the first move, so throw away - the info early. */ - src = change_address (src, BLKmode, srcreg); - dst = change_address (dst, BLKmode, destreg); - expand_movmem_prologue (dst, src, destreg, srcreg, count_exp, align, - desired_align); + if (align_bytes == 0) + { + /* Except for the first move in epilogue, we no longer know + constant offset in aliasing info. It don't seems to worth + the pain to maintain it for the first move, so throw away + the info early. */ + src = change_address (src, BLKmode, srcreg); + dst = change_address (dst, BLKmode, destreg); + expand_movmem_prologue (dst, src, destreg, srcreg, count_exp, align, + desired_align); + } + else + { + /* If we know how many bytes need to be stored before dst is + sufficiently aligned, maintain aliasing info accurately. */ + dst = expand_constant_movmem_prologue (dst, &src, destreg, srcreg, + desired_align, align_bytes); + count_exp = plus_constant (count_exp, -align_bytes); + count -= align_bytes; + } if (need_zero_guard && !count) { /* It is possible that we copied enough so the main loop will not @@ -17607,7 +17782,7 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, unsigned HOST_WIDE_INT count = 0; HOST_WIDE_INT expected_size = -1; int size_needed = 0, epilogue_size_needed; - int desired_align = 0; + int desired_align = 0, align_bytes = 0; enum stringop_alg alg; rtx promoted_val = NULL; bool force_loopy_epilogue = false; @@ -17678,10 +17853,23 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, /* Alignment code needs count to be in register. */ if (CONST_INT_P (count_exp) && desired_align > align) { - enum machine_mode mode = SImode; - if (TARGET_64BIT && (count & ~0xffffffff)) - mode = DImode; - count_exp = force_reg (mode, count_exp); + if (INTVAL (count_exp) > desired_align + && INTVAL (count_exp) > size_needed) + { + align_bytes + = get_mem_align_offset (dst, desired_align * BITS_PER_UNIT); + if (align_bytes <= 0) + align_bytes = 0; + else + align_bytes = desired_align - align_bytes; + } + if (align_bytes == 0) + { + enum machine_mode mode = SImode; + if (TARGET_64BIT && (count & ~0xffffffff)) + mode = DImode; + count_exp = force_reg (mode, count_exp); + } } /* Do the cheap promotion to allow better CSE across the main loop and epilogue (ie one load of the big constant in the @@ -17693,7 +17881,7 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, if (size_needed > 1 || (desired_align > 1 && desired_align > align)) { epilogue_size_needed = MAX (size_needed - 1, desired_align - align); - /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes. + /* Epilogue always copies COUNT_EXP & (EPILOGUE_SIZE_NEEDED - 1) bytes. Make sure it is power of 2. */ epilogue_size_needed = smallest_pow2_greater_than (epilogue_size_needed); @@ -17736,13 +17924,25 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, if (desired_align > align) { - /* Except for the first move in epilogue, we no longer know - constant offset in aliasing info. It don't seems to worth - the pain to maintain it for the first move, so throw away - the info early. */ - dst = change_address (dst, BLKmode, destreg); - expand_setmem_prologue (dst, destreg, promoted_val, count_exp, align, - desired_align); + if (align_bytes == 0) + { + /* Except for the first move in epilogue, we no longer know + constant offset in aliasing info. It don't seems to worth + the pain to maintain it for the first move, so throw away + the info early. */ + dst = change_address (dst, BLKmode, destreg); + expand_setmem_prologue (dst, destreg, promoted_val, count_exp, align, + desired_align); + } + else + { + /* If we know how many bytes need to be stored before dst is + sufficiently aligned, maintain aliasing info accurately. */ + dst = expand_constant_setmem_prologue (dst, destreg, promoted_val, + desired_align, align_bytes); + count_exp = plus_constant (count_exp, -align_bytes); + count -= align_bytes; + } if (need_zero_guard && !count) { /* It is possible that we copied enough so the main loop will not @@ -17785,15 +17985,15 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, break; case rep_prefix_8_byte: expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp, - DImode); + DImode, val_exp); break; case rep_prefix_4_byte: expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp, - SImode); + SImode, val_exp); break; case rep_prefix_1_byte: expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp, - QImode); + QImode, val_exp); break; } /* Adjust properly the offset of src and dest memory for aliasing. */ diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 0738f38..830ce1d 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -1490,6 +1490,90 @@ mem_expr_equal_p (const_tree expr1, const_tree expr2) return 0; } +/* Return OFFSET if XEXP (MEM, 0) - OFFSET is known to be ALIGN + bits aligned for 0 <= OFFSET < ALIGN / BITS_PER_UNIT, or + -1 if not known. */ + +int +get_mem_align_offset (rtx mem, int align) +{ + tree expr; + unsigned HOST_WIDE_INT offset; + + /* This function can't use + if (!MEM_EXPR (mem) || !MEM_OFFSET (mem) + || !CONST_INT_P (MEM_OFFSET (mem)) + || (get_object_alignment (MEM_EXPR (mem), MEM_ALIGN (mem), align) + < align)) + return -1; + else + return (- INTVAL (MEM_OFFSET (mem))) & (align / BITS_PER_UNIT - 1); + for two reasons: + - COMPONENT_REFs in MEM_EXPR can have NULL first operand, + for <variable>. get_inner_reference doesn't handle it and + even if it did, the alignment in that case needs to be determined + from DECL_FIELD_CONTEXT's TYPE_ALIGN. + - it would do suboptimal job for COMPONENT_REFs, even if MEM_EXPR + isn't sufficiently aligned, the object it is in might be. */ + gcc_assert (MEM_P (mem)); + expr = MEM_EXPR (mem); + if (expr == NULL_TREE + || MEM_OFFSET (mem) == NULL_RTX + || !CONST_INT_P (MEM_OFFSET (mem))) + return -1; + + offset = INTVAL (MEM_OFFSET (mem)); + if (DECL_P (expr)) + { + if (DECL_ALIGN (expr) < align) + return -1; + } + else if (INDIRECT_REF_P (expr)) + { + if (TYPE_ALIGN (TREE_TYPE (expr)) < (unsigned int) align) + return -1; + } + else if (TREE_CODE (expr) == COMPONENT_REF) + { + while (1) + { + tree inner = TREE_OPERAND (expr, 0); + tree field = TREE_OPERAND (expr, 1); + tree byte_offset = component_ref_field_offset (expr); + tree bit_offset = DECL_FIELD_BIT_OFFSET (field); + + if (!byte_offset + || !host_integerp (byte_offset, 1) + || !host_integerp (bit_offset, 1)) + return -1; + + offset += tree_low_cst (byte_offset, 1); + offset += tree_low_cst (bit_offset, 1) / BITS_PER_UNIT; + + if (inner == NULL_TREE) + { + if (TYPE_ALIGN (DECL_FIELD_CONTEXT (field)) + < (unsigned int) align) + return -1; + break; + } + else if (DECL_P (inner)) + { + if (DECL_ALIGN (inner) < align) + return -1; + break; + } + else if (TREE_CODE (inner) != COMPONENT_REF) + return -1; + expr = inner; + } + } + else + return -1; + + return offset & ((align / BITS_PER_UNIT) - 1); +} + /* Given REF (a MEM) and T, either the type of X or the expression corresponding to REF, set the memory attributes. OBJECTP is nonzero if we are making a new object of this type. BITPOS is nonzero if @@ -695,6 +695,11 @@ extern void set_mem_attributes (rtx, tree, int); expecting that it'll be added back in later. */ extern void set_mem_attributes_minus_bitpos (rtx, tree, int, HOST_WIDE_INT); +/* Return OFFSET if XEXP (MEM, 0) - OFFSET is known to be ALIGN + bits aligned for 0 <= OFFSET < ALIGN / BITS_PER_UNIT, or + -1 if not known. */ +extern int get_mem_align_offset (rtx, int); + /* Assemble the static constant template for function entry trampolines. */ extern rtx assemble_trampoline_template (void); |