* problems with read-write "asm" operands
@ 2002-11-05 18:19 Ben Liblit
2002-11-05 18:44 ` Ben Liblit
0 siblings, 1 reply; 2+ messages in thread
From: Ben Liblit @ 2002-11-05 18:19 UTC (permalink / raw)
To: gcc-help
I'm having trouble with a complex bit of inline x86 assembly code in GCC
3.2. I have two read-write operands, but GCC is treating their prior
values as dead.
Here's the problematic code:
unsigned counters[3];
int bump(int left, int right)
{
int lt = 0;
int le = 0;
asm ("cmp %3,%4\n"
"setl %b0\n"
"setle %b1\n"
"add %k1,%k0\n"
"incl %2(,%k0,4)\n"
: "+&q,&q" (lt), "+&q,&q" (le)
: "rV,rV" (counters), "r,g" (left), "g,r" (right)
: "cc");
}
The purpose of this function is to bump one of three counters depending
on the relative values of left and right. Specifically, it is intended
to be a faster version of:
counters[0] += (left < right);
counters[1] += (left == right);
counters[2] += (left > right);
The x86 "setl" and "setle" instructions only set the low-order byte of a
32-bit register. So it's important that the registers holding (lt) and
(le) be zeroed at the outset. I'm trying to do that in the C code,
since that way GCC can see the initializations and move or optimize them
more freely. The (lt) and (le) operands are declared using "+" to tell
GCC that they are read-write: I use the initial zero value (read), and
I will scribble over that value (write).
However, the generated assembly code contains no zero initialization! I
would have expected to see "xor %eax,%eax", for example, if register
%eax had been selected. But there's nothing. We jump right into the
"cmp" instruction with no clearing of the registers selected for (lt)
and (le).
What am I doing wrong here? I thought that "+" would suffice to tell
GCC that I care about these operands' values before the assembly
directive. But for some reason its throwing those initializing
assignments away. :-(
- * -
Secondary question: this assembly code has a side effect. It modifies
one of counter[0], counter[1], or counter[2]. But there doesn't seem to
be any way for me to tell GCC about this. I could put "memory" in the
clobber list, but that seems to be *too* strong. After all, this isn't
going to touch arbitrary memory. It's just going to update one of only
three possible locations. How can I express that?
- * -
Thanks for any advice. (Oh, and if you think you know a faster way to
code the same functionality, I'd love to see it!)
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: problems with read-write "asm" operands
2002-11-05 18:19 problems with read-write "asm" operands Ben Liblit
@ 2002-11-05 18:44 ` Ben Liblit
0 siblings, 0 replies; 2+ messages in thread
From: Ben Liblit @ 2002-11-05 18:44 UTC (permalink / raw)
To: gcc-help
Sorry to reply to my own posting, but here's a slightly simpler version
of the same code with nearly the same problem:
unsigned counters[3];
int bump(int left, int right)
{
int slot = 0;
int le = 0;
asm
("cmp %2,%3\n"
"setl %b0\n"
"setle %b1\n"
"add %k1,%k0\n"
: "+&q,&q" (slot), "+&q,&q" (le)
: "r,g" (left), "g,r" (right)
: "cc");
++counters[slot];
}
The job of the inline assembly code is now just to set "slot" to either
0, 1, or 2 depending on whether left is <, ==, or > right. Manipulation
of the counters array is done in C code, which makes things somewhat
more readable and more clearly expresses what kinds of side effects can
occur.
Both "slot" and "le" are zero initialized in the C code, and both are
declared as read-write ("+") operands. However....
- If I compile with "-O9", the register selected for "slot" is
correctly zero initialized. The register selected for "le",
however, is not. It simply inherits whatever leftover value
might previously have been in that register.
- If I compile with "-g", neither register is zero initialized.
Each simply inherits whatever leftover value might previously have
been in its selected register.
This is getting mighty strange. Anybody got a clue?
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2002-11-06 2:44 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-11-05 18:19 problems with read-write "asm" operands Ben Liblit
2002-11-05 18:44 ` Ben Liblit
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).