https://issues.dlang.org/show_bug.cgi?id=15573
--- Comment #23 from [email protected] --- There appears to be a codegen bug in dmd. Prior to the idiv instruction (integer division, at n/m), it needs to load EDX:EAX with the (extended) value of n. EAX is loaded correctly but EDX is not correctly zeroed (since we are dividing byte values, EDX should be zeroed). As a result, the idiv instruction will produce a garbage value. In the code compiled without -O -inline, there is an "xor %edx,%edx" instruction prior to the idiv. Apparently, -O and -inline interacts together badly and this instruction somehow gets elided. Here's the disassembly of main(), compiled with dmd -O -inline (with some embedded comments mapping sections to various source code snippets): ------ 0000000000438bc8 <_Dmain>: 438bc8: 55 push %rbp 438bc9: 48 8b ec mov %rsp,%rbp 438bcc: 48 81 ec 80 00 00 00 sub $0x80,%rsp 438bd3: 48 89 5d 88 mov %rbx,-0x78(%rbp) 438bd7: 4c 89 65 90 mov %r12,-0x70(%rbp) 438bdb: 4c 89 6d 98 mov %r13,-0x68(%rbp) 438bdf: 4c 89 75 a0 mov %r14,-0x60(%rbp) 438be3: 4c 89 7d a8 mov %r15,-0x58(%rbp) 438be7: be 01 00 00 00 mov $0x1,%esi 438bec: bf 30 27 68 00 mov $0x682730,%edi // testValues = [-2] 438bf1: e8 b2 21 00 00 callq 43ada8 <_d_arrayliteralTX> 438bf6: 49 89 c4 mov %rax,%r12 438bf9: 41 c6 04 24 fe movb $0xfe,(%r12) 438bfe: 4c 89 65 c8 mov %r12,-0x38(%rbp) 438c02: 48 c7 45 c0 01 00 00 movq $0x1,-0x40(%rbp) 438c09: 00 438c0a: 31 db xor %ebx,%ebx // foreach(m; testValues) 438c0c: 48 83 fb 01 cmp $0x1,%rbx 438c10: 72 0a jb 438c1c <_Dmain+0x54> 438c12: bf 16 00 00 00 mov $0x16,%edi // array bounds check 438c17: e8 94 07 00 00 callq 4393b0 <_D4test7__arrayZ> 438c1c: 48 8b 45 c8 mov -0x38(%rbp),%rax // ecx := testValues[i] 438c20: 0f be 0c 03 movsbl (%rbx,%rax,1),%ecx // -0x8(%rbp) := (byte) m 438c24: 88 4d f8 mov %cl,-0x8(%rbp) 438c27: 45 31 e4 xor %r12d,%r12d 438c2a: 48 89 5d f0 mov %rbx,-0x10(%rbp) // foreach (n; testValues) 438c2e: 49 83 fc 01 cmp $0x1,%r12 438c32: 72 0a jb 438c3e <_Dmain+0x76> 438c34: bf 17 00 00 00 mov $0x17,%edi // array bounds check 438c39: e8 72 07 00 00 callq 4393b0 <_D4test7__arrayZ> 438c3e: 48 8b 55 c8 mov -0x38(%rbp),%rdx // ebx := testValues[i] 438c42: 41 0f be 1c 14 movsbl (%r12,%rdx,1),%ebx // -0x7(%rbp) := (byte) n 438c47: 88 5d f9 mov %bl,-0x7(%rbp) // extend to 32 bits 438c4a: 0f be db movsbl %bl,%ebx 438c4d: 89 5d b0 mov %ebx,-0x50(%rbp) 438c50: db 45 b0 fildl -0x50(%rbp) 438c53: 0f be 45 f8 movsbl -0x8(%rbp),%eax 438c57: 89 45 b0 mov %eax,-0x50(%rbp) 438c5a: db 45 b0 fildl -0x50(%rbp) // theory = cast(real)n / m; 438c5d: de f9 fdivrp %st,%st(1) 438c5f: db 7d d0 fstpt -0x30(%rbp) 438c62: 66 c7 45 da 00 00 movw $0x0,-0x26(%rbp) 438c68: c7 45 dc 00 00 00 00 movl $0x0,-0x24(%rbp) 438c6f: f2 48 0f 10 45 d0 rex.W movsd -0x30(%rbp),%xmm0 438c75: f2 48 0f 11 45 e0 rex.W movsd %xmm0,-0x20(%rbp) 438c7b: f2 48 0f 10 4d d8 rex.W movsd -0x28(%rbp),%xmm1 438c81: f2 48 0f 11 4d e8 rex.W movsd %xmm1,-0x18(%rbp) 438c87: 0f b7 4d d8 movzwl -0x28(%rbp),%ecx // (inlined isNan): EXPMASK & (cast(ushort*)&x)[EXPPOS_SHORT] 438c8b: 66 81 e1 ff 7f and $0x7fff,%cx 438c90: ba ff 7f 00 00 mov $0x7fff,%edx // e == EXPMASK 438c95: 66 3b ca cmp %dx,%cx 438c98: 75 13 jne 438cad <_Dmain+0xe5> // rax := -0x20(%rbp) == ps 438c9a: 48 8b 45 e0 mov -0x20(%rbp),%rax // isNaN: ps & 0x7fff_ffff_ffff_ffff 438c9e: 48 bb ff ff ff ff ff movabs $0x7fffffffffffffff,%rbx 438ca5: ff ff 7f 438ca8: 48 85 c3 test %rax,%rbx 438cab: 75 05 jne 438cb2 <_Dmain+0xea> // isNaN == false 438cad: 45 31 ed xor %r13d,%r13d // r13d := return value of isNaN 438cb0: eb 06 jmp 438cb8 <_Dmain+0xf0> // isNaN == true 438cb2: 41 bd 01 00 00 00 mov $0x1,%r13d // r13d := return value of isNaN // NOTE: r13d == thrInval (enregistered) // esi := IntFlag.NULL 438cb8: 31 f6 xor %esi,%esi 438cba: 64 48 8b 0c 25 00 00 mov %fs:0x0,%rcx 438cc1: 00 00 438cc3: 48 8b 15 66 91 24 00 mov 0x249166(%rip),%rdx # 681e30 <_DYNAMIC+0x258> 438cca: 89 34 11 mov %esi,(%rcx,%rdx,1) // (inlined safeDiv): right == 0 438ccd: 38 75 f8 cmp %dh,-0x8(%rbp) // r14b := div0 = (right == 0) 438cd0: 41 0f 94 c6 sete %r14b // eax := left == n 438cd4: 0f be 45 f9 movsbl -0x7(%rbp),%eax // left == int.min 438cd8: 3d 00 00 00 80 cmp $0x80000000,%eax 438cdd: 75 06 jne 438ce5 <_Dmain+0x11d> // cast(bool)right 438cdf: 40 38 75 f8 cmp %sil,-0x8(%rbp) 438ce3: 75 05 jne 438cea <_Dmain+0x122> // r15d := posOver := false 438ce5: 45 31 ff xor %r15d,%r15d 438ce8: eb 06 jmp 438cf0 <_Dmain+0x128> // r15d := posOver := true 438cea: 41 bf 01 00 00 00 mov $0x1,%r15d // if (div0) 438cf0: 45 84 f6 test %r14b,%r14b ************* PROBLEM: EDX not zeroed here ********************* 438cf3: 74 1e je 438d13 <_Dmain+0x14b> 438cf5: 41 80 ff 01 cmp $0x1,%r15b 438cf9: bb 01 00 00 00 mov $0x1,%ebx 438cfe: 64 48 8b 0c 25 00 00 mov %fs:0x0,%rcx 438d05: 00 00 438d07: 48 8b 15 22 91 24 00 mov 0x249122(%rip),%rdx # 681e30 <_DYNAMIC+0x258> 438d0e: 89 1c 11 mov %ebx,(%rcx,%rdx,1) // return 0; 438d11: eb 0b jmp 438d1e <_Dmain+0x156> // >>from: 438cf3 (if (!div0)) // return left / right // edi := m 438d13: 40 0f be 7d f8 rex movsbl -0x8(%rbp),%edi 438d18: 99 cltd // left / right // (edi == right == m) // idiv: EDX:EAX / edi <--- *** PROBLEM: EDX not loaded with correct value // eax := quotient // edx := remainder 438d19: f7 ff idiv %edi 438d1b: 48 89 c6 mov %rax,%rsi // >>from: safeDiv: if (div0) 438d1e: 89 75 b0 mov %esi,-0x50(%rbp) 438d21: db 45 b0 fildl -0x50(%rbp) 438d24: db 6d d0 fldt -0x30(%rbp) 438d27: df e9 fucomip %st(1),%st 438d29: dd d8 fstp %st(0) 438d2b: bf 01 00 00 00 mov $0x1,%edi 438d30: 7a 02 jp 438d34 <_Dmain+0x16c> 438d32: 74 02 je 438d36 <_Dmain+0x16e> 438d34: 31 ff xor %edi,%edi 438d36: e8 b5 00 00 00 callq 438df0 <_D3std5stdio14__T7writelnTbZ7writelnFNfbZv> 438d3b: 45 84 ed test %r13b,%r13b 438d3e: 74 17 je 438d57 <_Dmain+0x18f> 438d40: 0f be 45 f8 movsbl -0x8(%rbp),%eax 438d44: 64 48 8b 0c 25 00 00 mov %fs:0x0,%rcx 438d4b: 00 00 438d4d: 48 8b 15 ec 90 24 00 mov 0x2490ec(%rip),%rdx # 681e40 <_DYNAMIC+0x268> 438d54: 89 04 11 mov %eax,(%rcx,%rdx,1) 438d57: 49 ff c4 inc %r12 438d5a: 49 83 fc 01 cmp $0x1,%r12 // end inner loop 438d5e: 0f 82 ca fe ff ff jb 438c2e <_Dmain+0x66> 438d64: 48 8b 5d f0 mov -0x10(%rbp),%rbx 438d68: 48 ff c3 inc %rbx 438d6b: 48 83 fb 01 cmp $0x1,%rbx // end outer loop 438d6f: 0f 82 97 fe ff ff jb 438c0c <_Dmain+0x44> 438d75: 31 c0 xor %eax,%eax 438d77: 48 8b 5d 88 mov -0x78(%rbp),%rbx 438d7b: 4c 8b 65 90 mov -0x70(%rbp),%r12 438d7f: 4c 8b 6d 98 mov -0x68(%rbp),%r13 438d83: 4c 8b 75 a0 mov -0x60(%rbp),%r14 438d87: 4c 8b 7d a8 mov -0x58(%rbp),%r15 438d8b: 48 8b e5 mov %rbp,%rsp 438d8e: 5d pop %rbp 438d8f: c3 retq ------ --
