SUBTARGET_OVERRIDE_OPTIONS;
#endif
+ /* Default to full IEEE compliance mode for Go language. */
+ if (strcmp (lang_hooks.name, "GNU Go") == 0
+ && !(target_flags_explicit & MASK_IEEE))
+ target_flags |= MASK_IEEE;
+
alpha_fprm = ALPHA_FPRM_NORM;
alpha_tp = ALPHA_TP_PROG;
alpha_fptm = ALPHA_FPTM_N;
return 0;
MEM_VOLATILE_P (x) = MEM_VOLATILE_P (orig);
- MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (orig);
- MEM_SCALAR_P (x) = MEM_SCALAR_P (orig);
MEM_NOTRAP_P (x) = MEM_NOTRAP_P (orig);
MEM_READONLY_P (x) = MEM_READONLY_P (orig);
generated from one of the insn patterns. So if everything is
zero, the pattern is already up-to-date. */
if (!MEM_VOLATILE_P (ref)
- && !MEM_IN_STRUCT_P (ref)
- && !MEM_SCALAR_P (ref)
&& !MEM_NOTRAP_P (ref)
&& !MEM_READONLY_P (ref))
return;
{
case EQ: case LE: case LT: case LEU: case LTU:
case UNORDERED:
- /* We have these compares: */
+ /* We have these compares. */
cmp_code = code, branch_code = NE;
break;
switch (code)
{
case EQ: case LE: case LT: case LEU: case LTU:
+ case UNORDERED:
/* We have these compares. */
cmp_code = code, code = NE;
break;
case NE:
- /* This must be reversed. */
- cmp_code = EQ, code = EQ;
+ case ORDERED:
+ /* These must be reversed. */
+ cmp_code = reverse_condition (code), code = EQ;
break;
case GE: case GT: case GEU: case GTU:
gcc_unreachable ();
}
+ if (cmp_mode == DImode)
+ {
+ if (!reg_or_0_operand (op0, DImode))
+ op0 = force_reg (DImode, op0);
+ if (!reg_or_8bit_operand (op1, DImode))
+ op1 = force_reg (DImode, op1);
+ }
+
tem = gen_reg_rtx (cmp_mode);
emit_insn (gen_rtx_SET (VOIDmode, tem,
gen_rtx_fmt_ee (cmp_code, cmp_mode,
local_fast_math = 1;
}
+ if (cmp_mode == DImode)
+ {
+ if (!reg_or_0_operand (op0, DImode))
+ op0 = force_reg (DImode, op0);
+ if (!reg_or_8bit_operand (op1, DImode))
+ op1 = force_reg (DImode, op1);
+ }
+
/* We may be able to use a conditional move directly.
This avoids emitting spurious compares. */
if (signed_comparison_operator (cmp, VOIDmode)
switch (code)
{
case EQ: case LE: case LT: case LEU: case LTU:
+ case UNORDERED:
/* We have these compares: */
break;
case NE:
- /* This must be reversed. */
+ case ORDERED:
+ /* These must be reversed. */
code = reverse_condition (code);
cmov_code = EQ;
break;
case GE: case GT: case GEU: case GTU:
- /* These must be swapped. */
- if (op1 != CONST0_RTX (cmp_mode))
- {
- code = swap_condition (code);
- tem = op0, op0 = op1, op1 = tem;
- }
+ /* These normally need swapping, but for integer zero we have
+ special patterns that recognize swapped operands. */
+ if (cmp_mode == DImode && op1 == const0_rtx)
+ break;
+ code = swap_condition (code);
+ tem = op0, op0 = op1, op1 = tem;
break;
default:
operands[1] = op1;
out = gen_reg_rtx (DImode);
- /* What's actually returned is -1,0,1, not a proper boolean value,
- so use an EXPR_LIST as with a generic libcall instead of a
- comparison type expression. */
- note = gen_rtx_EXPR_LIST (VOIDmode, op1, NULL_RTX);
- note = gen_rtx_EXPR_LIST (VOIDmode, op0, note);
- note = gen_rtx_EXPR_LIST (VOIDmode, func, note);
+ /* What's actually returned is -1,0,1, not a proper boolean value. */
+ note = gen_rtx_fmt_ee (cmp_code, VOIDmode, op0, op1);
+ note = gen_rtx_UNSPEC (DImode, gen_rtvec (1, note), UNSPEC_XFLT_COMPARE);
alpha_emit_xfloating_libcall (func, out, operands, 2, note);
return out;
if (TARGET_ABI_OPEN_VMS
&& !TREE_PUBLIC (decl)
&& DECL_CONTEXT (decl)
- && !TYPE_P (DECL_CONTEXT (decl)))
+ && !TYPE_P (DECL_CONTEXT (decl))
+ && TREE_CODE (DECL_CONTEXT (decl)) != TRANSLATION_UNIT_DECL)
{
strcpy (tramp_label, fnname);
strcat (tramp_label, "..tr");
}
}
-/* Insert an unop between a noreturn function call and GP load. */
+/* Insert an unop between sibcall or noreturn function call and GP load. */
static void
-alpha_pad_noreturn (void)
+alpha_pad_function_end (void)
{
rtx insn, next;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
if (! (CALL_P (insn)
- && find_reg_note (insn, REG_NORETURN, NULL_RTX)))
+ && (SIBLING_CALL_P (insn)
+ || find_reg_note (insn, REG_NORETURN, NULL_RTX))))
continue;
/* Make sure we do not split a call and its corresponding
static void
alpha_reorg (void)
{
- /* Workaround for a linker error that triggers when an
- exception handler immediatelly follows a noreturn function.
+ /* Workaround for a linker error that triggers when an exception
+ handler immediatelly follows a sibcall or a noreturn function.
+
+In the sibcall case:
+
+ The instruction stream from an object file:
+
+ 1d8: 00 00 fb 6b jmp (t12)
+ 1dc: 00 00 ba 27 ldah gp,0(ra)
+ 1e0: 00 00 bd 23 lda gp,0(gp)
+ 1e4: 00 00 7d a7 ldq t12,0(gp)
+ 1e8: 00 40 5b 6b jsr ra,(t12),1ec <__funcZ+0x1ec>
+
+ was converted in the final link pass to:
+
+ 12003aa88: 67 fa ff c3 br 120039428 <...>
+ 12003aa8c: 00 00 fe 2f unop
+ 12003aa90: 00 00 fe 2f unop
+ 12003aa94: 48 83 7d a7 ldq t12,-31928(gp)
+ 12003aa98: 00 40 5b 6b jsr ra,(t12),12003aa9c <__func+0x1ec>
+
+And in the noreturn case:
The instruction stream from an object file:
GP load instructions were wrongly cleared by the linker relaxation
pass. This workaround prevents removal of GP loads by inserting
- an unop instruction between a noreturn function call and
+ an unop instruction between a sibcall or noreturn function call and
exception handler prologue. */
if (current_function_has_exception_handlers ())
- alpha_pad_noreturn ();
+ alpha_pad_function_end ();
if (alpha_tp != ALPHA_TP_PROG || flag_exceptions)
alpha_handle_trap_shadows ();
{
size_t buf_len;
char *linksym;
+ tree id;
if (name[0] == '*')
name++;
+ /* Follow transparent alias, as this is used for CRTL translations. */
+ id = maybe_get_identifier (name);
+ if (id)
+ {
+ while (IDENTIFIER_TRANSPARENT_ALIAS (id))
+ id = TREE_CHAIN (id);
+ name = IDENTIFIER_POINTER (id);
+ }
+
buf_len = strlen (name) + 8 + 9;
linksym = (char *) alloca (buf_len);
snprintf (linksym, buf_len, "$%d..%s..lk", cfun->funcdef_no, name);
if (link->rkind == KIND_CODEADDR)
{
/* External and used, request code address. */
- fprintf (stream, "\t.code_address %s\n", name);
+ fprintf (stream, "\t.code_address ");
}
else
{
{
/* Locally defined, build linkage pair. */
fprintf (stream, "\t.quad %s..en\n", name);
- fprintf (stream, "\t.quad %s\n", name);
+ fprintf (stream, "\t.quad ");
}
else
{
/* External, request linkage pair. */
- fprintf (stream, "\t.linkage %s\n", name);
+ fprintf (stream, "\t.linkage ");
}
}
+ assemble_name (stream, name);
+ fputs ("\n", stream);
return 0;
}