Fix a scary bug with signed division by a power of two. We used to generate:

s:   ;; X / 4
        mov %EAX, DWORD PTR [%ESP + 4]
        mov %ECX, %EAX
        sar %ECX, 1
        shr %ECX, 30
        mov %EDX, %EAX
        add %EDX, %ECX
        sar %EAX, 2
        ret

When we really meant:

s:
        mov %EAX, DWORD PTR [%ESP + 4]
        mov %ECX, %EAX
        sar %ECX, 1
        shr %ECX, 30
        add %EAX, %ECX
        sar %EAX, 2
        ret

Hey, this also reduces register pressure too :)


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16761 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2004-10-06 04:19:43 +00:00
parent 610f1e2785
commit 3ffdff6448

View File

@ -2726,11 +2726,8 @@ void X86ISel::emitDivRemOperation(MachineBasicBlock *BB,
--Log;
unsigned Op0Reg = getReg(Op0, BB, IP);
unsigned TmpReg = makeAnotherReg(Op0->getType());
if (Log != 1)
BuildMI(*BB, IP, SAROpcode[Class], 2, TmpReg)
.addReg(Op0Reg).addImm(Log-1);
else
BuildMI(*BB, IP, MovOpcode[Class], 1, TmpReg).addReg(Op0Reg);
BuildMI(*BB, IP, SAROpcode[Class], 2, TmpReg)
.addReg(Op0Reg).addImm(Log-1);
unsigned TmpReg2 = makeAnotherReg(Op0->getType());
BuildMI(*BB, IP, SHROpcode[Class], 2, TmpReg2)
.addReg(TmpReg).addImm(32-Log);
@ -2740,7 +2737,7 @@ void X86ISel::emitDivRemOperation(MachineBasicBlock *BB,
unsigned TmpReg4 = isNeg ? makeAnotherReg(Op0->getType()) : ResultReg;
BuildMI(*BB, IP, SAROpcode[Class], 2, TmpReg4)
.addReg(Op0Reg).addImm(Log);
.addReg(TmpReg3).addImm(Log);
if (isNeg)
BuildMI(*BB, IP, NEGOpcode[Class], 1, ResultReg).addReg(TmpReg4);
return;