Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(612)

Unified Diff: gcc/gcc/config/i386/i386.c

Issue 2873014: [gcc] Use new constraint for LEA address operands. (Closed) Base URL: ssh://git@chromiumos-git/nacl-toolchain.git
Patch Set: Fixes for code review. Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
Download patch
« no previous file with comments | « gcc/gcc/config/i386/constraints.md ('k') | gcc/gcc/config/i386/i386.md » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gcc/gcc/config/i386/i386.c
diff --git a/gcc/gcc/config/i386/i386.c b/gcc/gcc/config/i386/i386.c
index 24a9cf0e5614205f39b507d335484f697da90f61..1d91ca04b0dae06740554f72266bd8a8e2d34baf 100644
--- a/gcc/gcc/config/i386/i386.c
+++ b/gcc/gcc/config/i386/i386.c
@@ -1818,6 +1818,9 @@ static bool ix86_valid_target_attribute_p (tree, tree, tree, int);
static bool ix86_valid_target_attribute_inner_p (tree, char *[]);
static bool ix86_can_inline_p (tree, tree);
static void ix86_set_current_function (tree);
+static int ix86_lea_decompose_address (rtx, struct ix86_address *);
+static int legitimate_address_parts_p (const struct ix86_address *, int);
+static void print_operand_address_parts (FILE *, const struct ix86_address *);
/* The svr4 ABI for the i386 says that records and unions are returned
@@ -6593,7 +6596,7 @@ setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum)
sse_prologue_save insn template that produces computed jump across
SSE saves. We need some preparation work to get this working. */
- if (!flag_control_integrity)
+ if (!TARGET_NACL)
{
label = gen_label_rtx ();
label_ref = gen_rtx_LABEL_REF (Pmode, label);
@@ -6641,7 +6644,7 @@ setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum)
set_mem_align (mem, BITS_PER_WORD);
/* And finally do the dirty job! */
- if (flag_control_integrity)
+ if (TARGET_NACL)
{
emit_insn (gen_nacl_sse_prologue_save (mem,
GEN_INT (cum->sse_regno)));
@@ -7463,7 +7466,7 @@ ix86_file_end (void)
(*targetm.asm_out.unique_section) (decl, 0);
switch_to_section (get_named_section (decl, NULL, 0));
- if (flag_control_integrity && !getenv("NONACLRET"))
+ if (TARGET_NACL && !getenv("NONACLRET"))
fprintf (asm_out_file, ".p2align %d\n", NACL_ALIGN_POW2);
(*targetm.asm_out.globalize_label) (asm_out_file, name);
fputs ("\t.hidden\t", asm_out_file);
@@ -7474,12 +7477,12 @@ ix86_file_end (void)
else
{
switch_to_section (text_section);
- if (flag_control_integrity && !getenv("NONACLRET"))
+ if (TARGET_NACL && !getenv("NONACLRET"))
fprintf (asm_out_file, ".p2align %d\n", NACL_ALIGN_POW2);
ASM_OUTPUT_LABEL (asm_out_file, name);
}
- if (flag_control_integrity && !getenv("NONACLRET"))
+ if (TARGET_NACL && !getenv("NONACLRET"))
{
xops[0] = gen_rtx_REG (Pmode, regno);
output_asm_insn ("pop{l}\t%0", xops);
@@ -8631,7 +8634,7 @@ ix86_expand_epilogue (int style)
+ frame.padding0),
style);
/* If not an i386, mov & pop is faster than "leave". */
- else if (!flag_control_integrity &&
+ else if (!TARGET_NACL &&
(TARGET_USE_LEAVE || optimize_function_for_size_p (cfun)
|| !cfun->machine->use_fast_prologue_epilogue))
emit_insn ((*ix86_gen_leave) ());
@@ -8728,7 +8731,7 @@ ix86_expand_epilogue (int style)
return address, do explicit add, and jump indirectly to the
caller. */
- if ((flag_control_integrity && !getenv("NONACLRET")) ||
+ if ((TARGET_NACL && !getenv("NONACLRET")) ||
(crtl->args.pops_args >= 65536))
{
/* x86_64 dedicates R11 for call-scratch needs */
@@ -8737,7 +8740,7 @@ ix86_expand_epilogue (int style)
emit_insn ((*ix86_gen_pop1) (reg1));
emit_insn ((*ix86_gen_add3) (stack_pointer_rtx, stack_pointer_rtx, popc));
- if (flag_control_integrity && !getenv("NONACLRET")) {
+ if (TARGET_NACL && !getenv("NONACLRET")) {
emit_jump_insn (gen_nacl_return_indirectsi (reg2));
} else {
emit_jump_insn (gen_return_indirect_internal (reg1));
@@ -8748,7 +8751,7 @@ ix86_expand_epilogue (int style)
}
else
{
- if (flag_control_integrity && !getenv("NONACLRET"))
+ if (TARGET_NACL && !getenv("NONACLRET"))
{
/* x86_64 dedicates R11 for call-scratch needs */
rtx reg1 = gen_rtx_REG (Pmode, TARGET_64BIT ? R11_REG : CX_REG);
@@ -8789,20 +8792,192 @@ ix86_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
}
-/* Extract the parts of an RTL expression that is a valid memory address
- for an instruction. Return 0 if the structure of the address is
- grossly off. Return -1 if the address contains ASHIFT, so it is not
- strictly valid, but still used for computing length of lea instruction. */
+/* Extract the parts of an RTL expression that is a valid address for lea
+ instruction.
+ WARNING: This is a copy-paste of the original ix86_decompose_address. */
+
+static int
+ix86_lea_decompose_address (rtx addr, struct ix86_address *out)
+{
+ rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX;
+ rtx base_reg, index_reg;
+ HOST_WIDE_INT scale = 1;
+ rtx scale_rtx = NULL_RTX;
+ int retval = 1;
+ enum ix86_address_seg seg = SEG_DEFAULT;
+
+ if (REG_P (addr) || GET_CODE (addr) == SUBREG)
+ base = addr;
+ else if (GET_CODE (addr) == PLUS)
+ {
+ rtx addends[4], op;
+ int n = 0, i;
+
+ op = addr;
+ do
+ {
+ if (n >= 4)
+ return 0;
+ /* Original version handled nested PLUS only if it was a left child.
+ Here we also handle nested PLUS that is a right child.
+ TODO: what if (plus (plus a b) (plus c d)) ? */
+ if (GET_CODE (XEXP (op, 1)) == PLUS)
+ {
+ addends[n++] = XEXP (op, 0);
+ op = XEXP (op, 1);
+ }
+ else
+ {
+ addends[n++] = XEXP (op, 1);
+ op = XEXP (op, 0);
+ }
+ }
+ while (GET_CODE (op) == PLUS);
+ if (n >= 4)
+ return 0;
+ addends[n] = op;
+
+ for (i = n; i >= 0; --i)
+ {
+ op = addends[i];
+ switch (GET_CODE (op))
+ {
+ case MULT:
+ if (index)
+ return 0;
+ index = XEXP (op, 0);
+ scale_rtx = XEXP (op, 1);
+ break;
+
+ case UNSPEC:
+ if (XINT (op, 1) == UNSPEC_TP
+ && TARGET_TLS_DIRECT_SEG_REFS
+ && seg == SEG_DEFAULT)
+ seg = TARGET_64BIT ? SEG_FS : SEG_GS;
+ else
+ return 0;
+ break;
+
+ case REG:
+ case SUBREG:
+ if (!base)
+ base = op;
+ else if (!index)
+ index = op;
+ else
+ return 0;
+ break;
+
+ case CONST:
+ case CONST_INT:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ if (disp)
+ return 0;
+ disp = op;
+ break;
+
+ default:
+ return 0;
+ }
+ }
+ }
+ else if (GET_CODE (addr) == MULT)
+ {
+ index = XEXP (addr, 0); /* index*scale */
+ scale_rtx = XEXP (addr, 1);
+ }
+ else if (GET_CODE (addr) == ASHIFT)
+ {
+ rtx tmp;
+
+ /* We're called for lea too, which implements ashift on occasion. */
+ index = XEXP (addr, 0);
+ tmp = XEXP (addr, 1);
+ if (!CONST_INT_P (tmp))
+ return 0;
+ scale = INTVAL (tmp);
+ if ((unsigned HOST_WIDE_INT) scale > 3)
+ return 0;
+ scale = 1 << scale;
+ retval = -1;
+ }
+ else
+ disp = addr; /* displacement */
+
+ /* Extract the integral value of scale. */
+ if (scale_rtx)
+ {
+ if (!CONST_INT_P (scale_rtx))
+ return 0;
+ scale = INTVAL (scale_rtx);
+ }
+
+ base_reg = base && GET_CODE (base) == SUBREG ? SUBREG_REG (base) : base;
+ index_reg = index && GET_CODE (index) == SUBREG ? SUBREG_REG (index) : index;
+
+ /* Allow arg pointer and stack pointer as index if there is not scaling. */
+ if (base_reg && index_reg && scale == 1
+ && (index_reg == arg_pointer_rtx
+ || index_reg == frame_pointer_rtx
+ || (REG_P (index_reg) && REGNO (index_reg) == STACK_POINTER_REGNUM)))
+ {
+ rtx tmp;
+ tmp = base, base = index, index = tmp;
+ tmp = base_reg, base_reg = index_reg, index_reg = tmp;
+ }
+
+ /* Special case: %ebp cannot be encoded as a base without a displacement. */
+ if ((base_reg == hard_frame_pointer_rtx
+ || base_reg == frame_pointer_rtx
+ || base_reg == arg_pointer_rtx) && !disp)
+ disp = const0_rtx;
+
+ /* Special case: on K6, [%esi] makes the instruction vector decoded.
+ Avoid this by transforming to [%esi+0].
+ Reload calls address legitimization without cfun defined, so we need
+ to test cfun for being non-NULL. */
+ if (TARGET_K6 && cfun && optimize_function_for_speed_p (cfun)
+ && base_reg && !index_reg && !disp
+ && REG_P (base_reg)
+ && REGNO_REG_CLASS (REGNO (base_reg)) == SIREG)
+ disp = const0_rtx;
+
+ /* Special case: encode reg+reg instead of reg*2. */
+ if (!base && index && scale && scale == 2)
+ base = index, base_reg = index_reg, scale = 1;
+
+ /* Special case: scaling cannot be encoded without base or displacement. */
+ if (!base && !disp && index && scale != 1)
+ disp = const0_rtx;
+
+ out->base = base;
+ out->index = index;
+ out->disp = disp;
+ out->scale = scale;
+ out->seg = seg;
+
+ return retval;
+}
int NACL_LEA_MATCH_ADDRESS_OPERAND = 0;
int
lea_match_address_operand (rtx op, enum machine_mode mode)
{
- int retval;
- NACL_LEA_MATCH_ADDRESS_OPERAND++;
- retval = memory_address_p (mode, op);
- NACL_LEA_MATCH_ADDRESS_OPERAND--;
- return retval;
+ struct ix86_address parts;
+
+ /* 1 and -1 are valid decompose address results for lea operand. */
+ if (ix86_lea_decompose_address (op, &parts) == 0)
+ return 0;
+
+ if (parts.seg != SEG_DEFAULT)
+ return 0;
+
+#ifdef REG_OK_STRICT
+ return legitimate_address_parts_p (&parts, 1);
+#else
+ return legitimate_address_parts_p (&parts, 0);
+#endif
}
/* Check if instruction is a LEA instruction.
@@ -8856,9 +9031,10 @@ gen_r15(rtx reg)
rtx base_reg;
/* In lea mode don't use R15, don't use nacl: prefix */
- if (NACL_LEA_MATCH_ADDRESS_OPERAND
- || !flag_control_integrity || !TARGET_64BIT) return 0;
- if (!reg) return 1;
+ if (!TARGET_NACL || !TARGET_64BIT)
+ return 0;
+ if (!reg)
+ return 1;
base_reg = GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg;
switch (REGNO(base_reg))
{
@@ -8876,6 +9052,11 @@ gen_r15(rtx reg)
}
}
+/* Extract the parts of an RTL expression that is a valid memory address
+ for an instruction. Return 0 if the structure of the address is
+ grossly off. Return -1 if the address contains ASHIFT, so it is not
+ strictly valid, but still used for computing length of lea instruction. */
+
int
ix86_decompose_address (rtx addr, struct ix86_address *out)
{
@@ -8972,12 +9153,11 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
if (!base)
base = op;
else if (!index)
- {
- index = op;
- if (!NACL_LEA_MATCH_ADDRESS_OPERAND
- && flag_control_integrity && TARGET_64BIT)
- seg = SEG_NACL;
- }
+ {
+ index = op;
+ if (TARGET_NACL && TARGET_64BIT)
+ seg = SEG_NACL;
+ }
else
return 0;
break;
@@ -9068,8 +9248,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
* jne .L2
* */
if (!getenv("NACL_ALLOW_MAGIC_DISP") &&
- TARGET_64BIT && flag_control_integrity &&
- !NACL_LEA_MATCH_ADDRESS_OPERAND &&
+ TARGET_64BIT && TARGET_NACL &&
index_reg &&
disp && GET_CODE(disp) == CONST)
{
@@ -9490,21 +9669,27 @@ legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
rtx addr, int strict)
{
struct ix86_address parts;
+
+ if (ix86_decompose_address (addr, &parts) <= 0)
+ return FALSE;
+
+ return legitimate_address_parts_p (&parts, strict);
+}
+
+/* Check if the decomposed address is a valid memory address. */
+
+static int
+legitimate_address_parts_p (const struct ix86_address *parts, int strict)
+{
rtx base, index, disp;
HOST_WIDE_INT scale;
const char *reason = NULL;
rtx reason_rtx = NULL_RTX;
- if (ix86_decompose_address (addr, &parts) <= 0)
- {
- reason = "decomposition failed";
- goto report_error;
- }
-
- base = parts.base;
- index = parts.index;
- disp = parts.disp;
- scale = parts.scale;
+ base = parts->base;
+ index = parts->index;
+ disp = parts->disp;
+ scale = parts->scale;
/* Validate base register.
@@ -10121,7 +10306,7 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
break;
case TLS_MODEL_LOCAL_EXEC:
- if (TARGET_64BIT && flag_control_integrity)
+ if (TARGET_64BIT && TARGET_NACL)
{
rtx rax = gen_rtx_REG (Pmode, AX_REG);
emit_insn (gen_naclcall_tls (rax, x));
@@ -11572,6 +11757,30 @@ print_operand (FILE *file, rtx x, int code)
#endif
return;
+ case 'Z':
+ {
+ struct ix86_address parts;
+ int ok;
+
+ ok = ix86_lea_decompose_address (x, &parts);
+ gcc_assert (ok);
+
+ /* final.c:output_address calls walk_alter_subreg before calling
+ PRINT_OPERAND_ADDRESS. We might want to call it here as well,
+ but its current implementation does not process ASHIFT (which
+ matched to LEA).
+ We should probably fix walk_alter_subreg, but I'm not sure if
+ allowing ASHIFT there is ok.
+ For now, just fix decomposed address parts. */
+ if (parts.base != NULL_RTX && GET_CODE (parts.base) == SUBREG)
+ parts.base = alter_subreg (&parts.base);
+ if (parts.index != NULL_RTX && GET_CODE (parts.index) == SUBREG)
+ parts.index = alter_subreg (&parts.index);
+
+ print_operand_address_parts (file, &parts);
+ }
+ return;
+
default:
output_operand_lossage ("invalid operand code '%c'", code);
}
@@ -11701,18 +11910,26 @@ void
print_operand_address (FILE *file, rtx addr)
{
struct ix86_address parts;
- rtx base, index, disp;
- int scale;
int ok = ix86_decompose_address (addr, &parts);
gcc_assert (ok);
+ print_operand_address_parts (file, &parts);
+}
- base = parts.base;
- index = parts.index;
- disp = parts.disp;
- scale = parts.scale;
+/* Print a memory operand whose decomposed address is PARTS. */
- switch (parts.seg)
+static void
+print_operand_address_parts (FILE *file, const struct ix86_address *parts)
+{
+ rtx base, index, disp;
+ int scale;
+
+ base = parts->base;
+ index = parts->index;
+ disp = parts->disp;
+ scale = parts->scale;
+
+ switch (parts->seg)
{
case SEG_DEFAULT:
break;
@@ -11721,7 +11938,7 @@ print_operand_address (FILE *file, rtx addr)
case SEG_NACL:
if (ASSEMBLER_DIALECT == ASM_ATT)
putc ('%', file);
- switch (parts.seg)
+ switch (parts->seg)
{
case SEG_FS:
fputs ("fs:", file);
@@ -11761,7 +11978,7 @@ print_operand_address (FILE *file, rtx addr)
if (CONST_INT_P (disp))
{
- if (ASSEMBLER_DIALECT == ASM_INTEL && parts.seg == SEG_DEFAULT)
+ if (ASSEMBLER_DIALECT == ASM_INTEL && parts->seg == SEG_DEFAULT)
fputs ("ds:", file);
fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (disp));
}
@@ -19369,7 +19586,7 @@ ix86_attr_length_address_default (rtx insn)
{
int i;
- if (insn_is_nacl_lea(insn))
+ if (get_attr_type (insn) == TYPE_LEA)
{
rtx set = PATTERN (insn);
@@ -19378,10 +19595,14 @@ ix86_attr_length_address_default (rtx insn)
gcc_assert (GET_CODE (set) == SET);
- NACL_LEA_MATCH_ADDRESS_OPERAND++;
- i = memory_address_length (SET_SRC (set));
- NACL_LEA_MATCH_ADDRESS_OPERAND--;
- return i;
+ /* HACK: this is used to calculate min instruction size. It is probably
+ safe to return 0 from here.
+ TODO: factor out memory_address_parts_length and call it here with
+ x86_lea_decompose_address parts. */
+ if (TARGET_NACL)
+ return 0;
+
+ return memory_address_length (SET_SRC (set));
}
extract_insn_cached (insn);
« no previous file with comments | « gcc/gcc/config/i386/constraints.md ('k') | gcc/gcc/config/i386/i386.md » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698