This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
help setting a register to a constant
- From: Mihai Burcea <burceam at eecg dot toronto dot edu>
- To: gcc at gcc dot gnu dot org
- Cc: Mihai Burcea <burceam at eecg dot utoronto dot ca>
- Date: Fri, 7 Nov 2003 16:48:46 -0500 (EST)
- Subject: help setting a register to a constant
Hi,
This may seem trivial to some of you, so I apologize for that in advance.
I am using gcc-3.3.1, and basically I am trying to replace a function call
with a constant value. For some reason, that doesn't work.
What I am doing works fine when using optimizations, because of this in
toplev.c (roughly line 3320):
/* If optimizing, allocate remaining pseudo-regs. Do the reload
pass fixing up any insns that are invalid. */
if (optimize)
failure = global_alloc (rtl_dump_file);
else
{
build_insn_chain (insns);
failure = reload (insns, 0);
}
When I don't use optimizations, just my own simple pass, I get a compiler
internal error, because the reload() is called. My stuff works fine when
using -Ox, however, precisely because reload() is not called.
This is what the code looks like at various stages:
This is the original (i.e., without my pass) RTL code (tmp.c.00.rtl):
(call_insn 16 15 17 (nil) (set (reg:SI 0 eax)
(call (mem:QI (symbol_ref:SI ("myfunc")) [0 S1 A8])
(const_int 0 [0x0]))) -1 (nil)
(nil)
(nil))
(insn 17 16 18 (nil) (set (reg:SI 61)
(reg:SI 0 eax)) -1 (nil)
(nil))
So myfunc is called, its result returned in eax (insn 16), and then the
contents of eax are moved into pseudo-reg 61 (insn 17).
All fine.
What I am doing is eliminating both of these instructions, and putting my
own constant value in reg 61.
So this is what the code looks like after I've done this
(tmp.c.10.addressof):
(insn 15 11 33 0 0x4005a2c0 (set (reg/f:SI 60) ...
(insn 33 15 18 0 (nil) (set (reg:SI 61)
(const_int 7 [0x7])) -1 (nil)
(nil))
(insn 18 33 19 0 0x4005a2c0 (parallel [...
The 2 insns have disappeared, replaced by my own (insn 33).
If I don't use optimizations, pass 21 (regmove) is not called. At pass 23
(lreg), the code still looks the same (i.e., my insn is not modified in
any way, everything is ok).
To be sure there is nothing out of the ordinary with that particular
register (61), this is from tmp.c.23.lreg:
Register 61 used 2 times across 2 insns in block 0; set 1 time;
GENERAL_REGS or none.
This is exactly the same as with all the other pseudo registers in that
BB; it is not used outside of the BB, it is not set again, etc. There is
nothing (to my understanding, or that shows in the RTL dump tmp.c.23.lreg)
that distinguishes it from any other pseudo-reg in that BB.
However, this is from pass 24 (greg):
Spilling for insn 33.
Using reg 2 for reload 0
Spilling for insn 33.
Using reg 2 for reload 0
Reloads for insn # 33
Reload 0: reload_out (SI) = (reg:SI 61)
GENERAL_REGS, RELOAD_FOR_OUTPUT (opnum = 0)
reload_out_reg: (reg:SI 61)
reload_reg_rtx: (reg:SI 2 ecx)
;; Register dispositions:
58 in 0 59 in 0 60 in 1 61 in 0 62 in 0 63 in 0
64 in 0
---cut----
(insn 15 11 33 0 0x4005a2c0 (set ...
(insn 33 15 35 0 (nil) (set (reg:SI 2 ecx)
(const_int 7 [0x7])) 45 {*movsi_1} (nil)
(nil))
(insn 35 33 18 0 (nil) (set (reg:SI 61)
(reg:SI 2 ecx)) 45 {*movsi_1} (nil)
(nil))
(insn 18 35 19 0 0x4005a2c0 (parallel [...
In my insn the pseudo-reg has been replaced by ecx, fine, no problem, but
then a new insn is generated (insn 35) which spills ecx's contents back
into reg 61 !
Then, as you may expect, I get this:
omp_getnumthreads.c:12: error: insn does not satisfy its constraints:
(insn 35 33 18 (nil) (set (reg:SI 61)
(reg:SI 2 ecx)) 45 {*movsi_1} (nil)
(nil))
omp_getnumthreads.c:12: internal compiler error: in
extract_constrain_insn_cached, at recog.c:2090
My pass basically consists of this:
1. find the function call
2. read the pseudo-reg of its NEXT_INSN (store it in vreg2)
3. remove the function call's NEXT_INSN (remove_insn)
4. generate my own insn
new_rtx = gen_rtx (SET, VOIDmode,
gen_rtx (REG, SImode, vreg2),
gen_rtx (CONST_INT, SImode, 7));
5. insert this before the function call (emit_insn_before)
6. remove the function call insn (remove_insn)
The troublesome insn is the one automatically generated.
I have several questions:
1. why does it crash ? I have tracked it through gdb, but I can't figure
out the primary cause for this. Is it because this is the only insn that's
using soft regs instead of hard ones ?
2. why does it choose to generate a reload for my insn ? I have no reason
for hanging onto reg61 or whatever that happens to be, but reload() seems
to believe it has to spill it back in.
3. is there something wrong with the way I am trying to do this ?
i.e., should I be using other kind/type of insn to assign a constant to a
reg ? (set seemed the straightforward way to me).
I have tried the following example:
int func1 (void) {
return 7;
}
void main () {
int a;
a = func1();
printf ("a=%d\n", a);
}
This is an excerpt from its RTL dump (00.rtl):
;; Function func1
(note 2 0 3 NOTE_INSN_DELETED)
---lots of other insns deleted---
(note 9 8 10 NOTE_INSN_DELETED)
(insn 10 9 11 (nil) (set (reg:SI 58)
(const_int 7 [0x7])) -1 (nil)
(nil))
(jump_insn 11 10 12 (nil) (set (pc)
(label_ref 15)) -1 (nil)
(nil))
(barrier 12 11 13)
(note 13 12 17 NOTE_INSN_FUNCTION_END)
My point is that insn 10 is identical with mine. However, in this case
(no optimizations, and without calling my pass), there is no spilling
done, and no reload in the register allocation pass, i.e., in
test2.c.24.greg, the insn looks like this:
(insn 10 20 13 0 (nil) (set (reg:SI 0 eax [58])
(const_int 7 [0x7])) 45 {*movsi_1} (nil)
(nil))
and there is no extra insn generated, no spilling, no reloading, etc.
I would appreciate any feedback and/or suggestions.
Thank you very much, and please let me know if you need more details.
Please reply to this address as well, I am not (yet) subscribed to the
mailing list.
Thank you
mihai