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. --