On Wed, Sep 24, 2014 at 2:51 PM, Ilya Enkovich wrote: > 2014-09-24 16:47 GMT+04:00 Steven Bosscher : > It is not a control flow instruction. It copies value of instruction > pointer into a general purpose register. Therefore REG_LABEL_OPERAND > seems to be correct.
OK - sorry for being a bit slow on the up-take, I got confused by the asm syntax :-) So I'm going to speculate a bit more... What you want to have is: foo: insns... L2: leaq L2(%rip), rXX What happens is that L2 is "deleted", which is to say converted to a NOTE_INSN_DELETED_LABEL. Then the notes are re-ordered (NOTE_INSN_DELETED_LABEL notes are not tied to anything in the insns stream and can end up anywhere) so you end up with something like, foo: L2: # (was deleted) insns... leaq L2(%rip),rXX I bet you'd find that in the failing test case the label is output to the assembly file but it's simply in the wrong place. For the large code model, we get away with it because the prologue is output late and the order of the insns is not adjusted (a few passes later, the CFG doesn't even exist anymore so you don't go through cfgcleanup). But if you emit the label early and let it go through the entire RTL pipeline then anything can happen. If the above makes sense, then you'll want to emit the label late, or not at all, to the insns stream. If you emit the label late into the insns stream, you'd rewrite the set_rip as a define_insn_and_split that emits the label as part of the last splitting pass. But there is no splitting pass late enough to guarantee that the label and insns won't get separated. If you don't emit the label to the insns stream, you would write ix86_output_set_rip() and call that from the define_insns for set_rip. You'd not emit the label in the expander. You'd create it and make it an operand, but not emit it. Your ix86_output_set_rip() would write the label and the set_rip instruction. This is probably the only way to make 100% sure that the label is always exactly at the set_rip instruction. Something like below (completely untested, etc...). Hope this helps, Ciao! Steven Index: config/i386/i386-protos.h =================================================================== --- config/i386/i386-protos.h (revision 215483) +++ config/i386/i386-protos.h (working copy) @@ -303,6 +303,7 @@ extern enum attr_cpu ix86_schedule; #endif extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op); +extern const char * ix86_output_set_rip_insn (rtx *operands); #ifdef RTX_CODE /* Target data for multipass lookahead scheduling. Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 215483) +++ config/i386/i386.c (working copy) @@ -11225,8 +11225,6 @@ ix86_expand_prologue (void) gcc_assert (Pmode == DImode); label = gen_label_rtx (); - emit_label (label); - LABEL_PRESERVE_P (label) = 1; tmp_reg = gen_rtx_REG (Pmode, R11_REG); gcc_assert (REGNO (pic_offset_table_rtx) != REGNO (tmp_reg)); insn = emit_insn (gen_set_rip_rex64 (pic_offset_table_rtx, @@ -12034,8 +12032,6 @@ ix86_expand_split_stack_prologue (void) rtx x; label = gen_label_rtx (); - emit_label (label); - LABEL_PRESERVE_P (label) = 1; emit_insn (gen_set_rip_rex64 (reg10, label)); emit_insn (gen_set_got_offset_rex64 (reg11, label)); emit_insn (ix86_gen_add3 (reg10, reg10, reg11)); @@ -25016,6 +25012,17 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op return ""; } + +/* Output the assembly for a SET_RIP instruction. We do so with this output + function to ensure that the label and %rip load instruction are together. */ + +const char * +ix86_output_set_rip_insn (rtx *operands) +{ + output_asm_label (operands[1]); + output_asm_insn ("lea{q}\t{%l1(%%rip), %0|%0, %l1[rip]}", operands); + return ""; +} /* Clear stack slot assignments remembered from previous functions. This is called from INIT_EXPANDERS once before RTL is emitted for each Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 215483) +++ config/i386/i386.md (working copy) @@ -12010,7 +12010,7 @@ [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(label_ref (match_operand 1))] UNSPEC_SET_RIP))] "TARGET_64BIT" - "lea{q}\t{%l1(%%rip), %0|%0, %l1[rip]}" + "* return ix86_output_set_rip_insn (operands);" [(set_attr "type" "lea") (set_attr "length_address" "4") (set_attr "mode" "DI")])