+2002-05-23 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (get_pic_label_name): New.
+ (load_pic_register): Remove.
+ (output_set_got): New.
+ (ix86_expand_prologue): Use gen_set_got; mark insn REG_MAYBE_DEAD.
+ * config/i386/i386.md (UNSPEC_SET_GOT): New.
+ (UNSPECV_PROLOGUE_SET_GOT, UNSPECV_PROLOGUE_GET_PC): Remove.
+ (prologue_set_got, prologue_get_pc): Remove.
+ (set_got, set_got_nopic, set_got_deep, set_got_nodeep): New.
+ (builtin_setjmp_receiver): Use gen_set_got.
+ * config/i386/i386-protos.h: Update.
+
Thu May 23 09:22:23 CEST 2002 Jan Hubicka <jh@suse.cz>
* gcse.c (hash_expr): Do not use alias set for hashing.
extern void ix86_setup_frame_addresses PARAMS ((void));
extern void ix86_asm_file_end PARAMS ((FILE *));
-extern void load_pic_register PARAMS ((void));
extern HOST_WIDE_INT ix86_initial_elimination_offset PARAMS((int, int));
extern void ix86_expand_prologue PARAMS ((void));
extern void ix86_expand_epilogue PARAMS ((int));
extern void split_di PARAMS ((rtx[], int, rtx[], rtx[]));
extern void split_ti PARAMS ((rtx[], int, rtx[], rtx[]));
+extern const char *output_set_got PARAMS ((rtx));
extern const char *output_387_binary_op PARAMS ((rtx, rtx*));
extern const char *output_fix_trunc PARAMS ((rtx, rtx*));
extern const char *output_fp_compare PARAMS ((rtx, rtx*, int, int));
static int internal_label_prefix_len;
\f
static int local_symbolic_operand PARAMS ((rtx, enum machine_mode));
+static const char *get_pic_label_name PARAMS ((void));
static void output_pic_addr_const PARAMS ((FILE *, rtx, int));
static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode,
int, int, FILE *));
\f
static char pic_label_name[32];
+static const char *
+get_pic_label_name ()
+{
+ if (! pic_label_name[0])
+ ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
+ return pic_label_name;
+}
+
/* This function generates code for -fpic that loads %ebx with
the return address of the caller and then returns. */
output_asm_insn ("ret", xops);
}
-void
-load_pic_register ()
-{
- rtx gotsym, pclab;
+/* Emit code for the SET_GOT patterns. */
- if (TARGET_64BIT)
- abort ();
+const char *
+output_set_got (dest)
+ rtx dest;
+{
+ rtx xops[3];
- gotsym = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+ xops[0] = dest;
+ xops[1] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
- if (TARGET_DEEP_BRANCH_PREDICTION)
+ if (! TARGET_DEEP_BRANCH_PREDICTION || !flag_pic)
{
- if (! pic_label_name[0])
- ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
- pclab = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, pic_label_name));
+ xops[2] = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
+
+ if (!flag_pic)
+ output_asm_insn ("mov{l}\t{%2, %0|%0, %2}", xops);
+ else
+ output_asm_insn ("call\t%a2", xops);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (XEXP (xops[2], 0)));
+
+ if (flag_pic)
+ output_asm_insn ("pop{l}\t%0", xops);
}
else
{
- pclab = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ xops[2] = gen_rtx_SYMBOL_REF (Pmode, get_pic_label_name ());
+ xops[2] = gen_rtx_MEM (QImode, xops[2]);
+ output_asm_insn ("call\t%X2", xops);
}
- emit_insn (gen_prologue_get_pc (pic_offset_table_rtx, pclab));
-
- if (! TARGET_DEEP_BRANCH_PREDICTION)
- emit_insn (gen_popsi1 (pic_offset_table_rtx));
+ if (!flag_pic || TARGET_DEEP_BRANCH_PREDICTION)
+ output_asm_insn ("add{l}\t{%1, %0|%0, %1}", xops);
+ else
+ output_asm_insn ("add{l}\t{%1+[.-%X2], %0|%0, %a1+(.-%X2)}", xops);
- emit_insn (gen_prologue_set_got (pic_offset_table_rtx, gotsym, pclab));
+ return "";
}
/* Generate an "push" pattern for input ARG. */
#endif
if (pic_reg_used)
- load_pic_register ();
+ {
+ insn = emit_insn (gen_set_got (pic_offset_table_rtx));
+
+ /* ??? The current_function_uses_pic_offset_table flag is woefully
+ inaccurate, as it isn't updated as code gets deleted. Allow the
+ thing to be removed. A better solution would be to actually get
+ proper liveness for ebx, as then we won't save/restore it too. */
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
+ }
/* If we are profiling, make sure no instructions are scheduled before
the call to mcount. However, if -fpic, the above call will have
(UNSPEC_SSE_PROLOGUE_SAVE 13)
(UNSPEC_FLDCW 14)
(UNSPEC_GOTPCREL 15)
+ (UNSPEC_SET_GOT 16)
; For SSE/MMX support:
(UNSPEC_FIX 30)
(define_constants
[(UNSPECV_BLOCKAGE 0)
- (UNSPECV_PROLOGUE_SET_GOT 1)
- (UNSPECV_PROLOGUE_GET_PC 2)
(UNSPECV_EH_RETURN 13)
(UNSPECV_EMMS 31)
(UNSPECV_LDMXCSR 37)
""
"ix86_expand_prologue (); DONE;")
-(define_insn "prologue_set_got"
+(define_expand "set_got"
+ [(parallel [(set (match_operand:SI 0 "register_operand" "")
+ (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
+ (clobber (reg:CC 17))])]
+ "!TARGET_64BIT"
+ "")
+
+(define_insn "*set_got_nopic"
[(set (match_operand:SI 0 "register_operand" "=r")
- (unspec_volatile:SI
- [(plus:SI (match_dup 0)
- (plus:SI (match_operand:SI 1 "symbolic_operand" "")
- (minus:SI (pc) (match_operand 2 "" ""))))]
- UNSPECV_PROLOGUE_SET_GOT))
+ (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
(clobber (reg:CC 17))]
- "!TARGET_64BIT"
-{
- if (GET_CODE (operands[2]) == LABEL_REF)
- operands[2] = XEXP (operands[2], 0);
- if (TARGET_DEEP_BRANCH_PREDICTION)
- return "add{l}\t{%1, %0|%0, %1}";
- else
- return "add{l}\t{%1+[.-%X2], %0|%0, %a1+(.-%X2)}";
-}
- [(set_attr "type" "alu")
- ; Since this insn may have two constant operands, we must set the
- ; length manually.
- (set_attr "length_immediate" "4")
- (set_attr "mode" "SI")])
+ "!TARGET_64BIT && !flag_pic"
+ { return output_set_got (operands[0]); }
+ [(set_attr "type" "multi")
+ (set_attr "length" "11")])
-(define_insn "prologue_get_pc"
+(define_insn "*set_got_deep"
+ [(set (match_operand:SI 0 "register_operand" "=b")
+ (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
+ (clobber (reg:CC 17))]
+ "!TARGET_64BIT && TARGET_DEEP_BRANCH_PREDICTION"
+ { return output_set_got (operands[0]); }
+ [(set_attr "type" "multi")
+ (set_attr "length" "11")])
+
+(define_insn "*set_got_nodeep"
[(set (match_operand:SI 0 "register_operand" "=r")
- (unspec_volatile:SI [(plus:SI (pc) (match_operand 1 "" ""))]
- UNSPECV_PROLOGUE_GET_PC))]
+ (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
+ (clobber (reg:CC 17))]
"!TARGET_64BIT"
-{
- if (GET_CODE (operands[1]) == LABEL_REF)
- operands[1] = XEXP (operands[1], 0);
- output_asm_insn ("call\t%X1", operands);
- if (! TARGET_DEEP_BRANCH_PREDICTION)
- {
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
- CODE_LABEL_NUMBER (operands[1]));
- }
- RET;
-}
- [(set_attr "type" "multi")])
+ { return output_set_got (operands[0]); }
+ [(set_attr "type" "multi")
+ (set_attr "length" "12")])
(define_expand "epilogue"
[(const_int 1)]
[(label_ref (match_operand 0 "" ""))]
"!TARGET_64BIT && flag_pic"
{
- load_pic_register ();
+ emit_insn (gen_set_got (pic_offset_table_rtx));
DONE;
})
\f