https://issues.dlang.org/show_bug.cgi?id=12833

yebblies <yebbl...@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzi...@digitalmars.com,
                   |                            |yebbl...@gmail.com

--- Comment #2 from yebblies <yebbl...@gmail.com> ---
So, the problem is:

1. the code is emitted to bitwise and a long with 0xFFFF (and EAX with 0xFFFF,
and EDX with 0x0)
2. the compiler checks and decides to do nothing for the long -> ushort
conversion because the result is already in AX where it should be.
3. the zext code has a really dodgy check (cdshtlng cod4.c:2905) that promotes
(r16 & mask16) into (r32 & mask32), but doesn't bother checking that it's
actually anding the correct register - in this case it sees the "and EDX, 0"
and does nothing.  It also sets the return register to whatever that
instruction was using and as a result later code-gen stupidly uses edx.

Making this change appears to fix it by disallowing the 'optimization' if the
register is wrong:

@@ -2900,11 +2900,11 @@ code *cdshtlng(elem *e,regm_t *pretregs)
         c1 = codelem(e1,&retregs,FALSE);
         c2 = getregs(retregs);
         if (op == OPu16_32 && c1)
         {
             code *cx = code_last(c1);
-            if (cx->Iop == 0x81 && (cx->Irm & modregrm(3,7,0)) ==
modregrm(3,4,0))
+            if (cx->Iop == 0x81 && (cx->Irm & modregrm(3,7,0)) ==
modregrm(3,4,0) && (1 << (cx->Irm & modregrm(0,0,7))) == retregs)
             {
                 // Convert AND of a word to AND of a dword, zeroing upper word
                 retregs = mask[cx->Irm & 7];
                 if (cx->Irex & REX_B)
                     retregs = mask[8 | (cx->Irm & 7)];

Hopefully Walter can comment on the correctness of this patch.

--

Reply via email to