From ae034542b71b20246bd3852c65f2ea99d8087879 Mon Sep 17 00:00:00 2001 From: simonmar Date: Mon, 13 Nov 2000 11:04:07 +0000 Subject: [PATCH] [project @ 2000-11-13 11:04:06 by simonmar] Merge register allocation fix for idiv from before-ghci-branch: 1.59.2.1 +2 -37 fptools/ghc/compiler/nativeGen/MachCode.lhs 1.40.2.1 +15 -4 fptools/ghc/compiler/nativeGen/MachMisc.lhs 1.43.2.1 +20 -1 fptools/ghc/compiler/nativeGen/PprMach.lhs 1.26.2.1 +8 -15 fptools/ghc/compiler/nativeGen/RegAllocInfo.lhs --- ghc/compiler/nativeGen/MachCode.lhs | 39 ++----------------------------- ghc/compiler/nativeGen/MachMisc.lhs | 19 +++++++++++---- ghc/compiler/nativeGen/PprMach.lhs | 21 ++++++++++++++++- ghc/compiler/nativeGen/RegAllocInfo.lhs | 23 +++++++----------- 4 files changed, 45 insertions(+), 57 deletions(-) diff --git a/ghc/compiler/nativeGen/MachCode.lhs b/ghc/compiler/nativeGen/MachCode.lhs index 4406d45..df4c2a6 100644 --- a/ghc/compiler/nativeGen/MachCode.lhs +++ b/ghc/compiler/nativeGen/MachCode.lhs @@ -665,8 +665,8 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps IntAddOp -> add_code L x y IntSubOp -> sub_code L x y - IntQuotOp -> quot_code L x y True{-division-} - IntRemOp -> quot_code L x y False{-remainder-} + IntQuotOp -> trivialCode (IQUOT L) Nothing x y + IntRemOp -> trivialCode (IREM L) Nothing x y IntMulOp -> let op = IMUL L in trivialCode op (Just op) x y FloatAddOp -> trivialFCode FloatRep GADD x y @@ -832,41 +832,6 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps sub_code sz x y = trivialCode (SUB sz) Nothing x y - -------------------- - quot_code - :: Size - -> StixTree -> StixTree - -> Bool -- True => division, False => remainder operation - -> NatM Register - - -- x must go into eax, edx must be a sign-extension of eax, and y - -- should go in some other register (or memory), so that we get - -- edx:eax / reg -> eax (remainder in edx). Currently we choose - -- to put y on the C stack, since that avoids tying up yet another - -- precious register. - - quot_code sz x y is_division - = getRegister x `thenNat` \ register1 -> - getRegister y `thenNat` \ register2 -> - getNewRegNCG IntRep `thenNat` \ tmp -> - getDeltaNat `thenNat` \ delta -> - let - code1 = registerCode register1 tmp - src1 = registerName register1 tmp - code2 = registerCode register2 tmp - src2 = registerName register2 tmp - code__2 = code2 `snocOL` -- src2 := y - PUSH L (OpReg src2) `snocOL` -- -4(%esp) := y - DELTA (delta-4) `appOL` - code1 `snocOL` -- src1 := x - MOV L (OpReg src1) (OpReg eax) `snocOL` -- eax := x - CLTD `snocOL` - IDIV sz (OpAddr (spRel 0)) `snocOL` - ADD L (OpImm (ImmInt 4)) (OpReg esp) `snocOL` - DELTA delta - in - returnNat (Fixed IntRep (if is_division then eax else edx) code__2) - ----------------------- getRegister (StInd pk mem) = getAmode mem `thenNat` \ amode -> diff --git a/ghc/compiler/nativeGen/MachMisc.lhs b/ghc/compiler/nativeGen/MachMisc.lhs index a98eb16..7113822 100644 --- a/ghc/compiler/nativeGen/MachMisc.lhs +++ b/ghc/compiler/nativeGen/MachMisc.lhs @@ -438,6 +438,15 @@ We might as well make use of whatever unique FP facilities Intel have chosen to bless us with (let's not be churlish, after all). Hence GLDZ and GLD1. Bwahahahahahahaha! +LATER (10 Nov 2000): idiv gives problems with the register spiller, +because the spiller is simpleminded and because idiv has fixed uses of +%eax and %edx. Rather than make the spiller cleverer, we do away with +idiv, and instead have iquot and irem fake (integer) insns, which have +no operand register constraints -- ie, they behave like add, sub, mul. +The printer-outer transforms them to a sequence of real insns which does +the Right Thing (tm). As with the FP stuff, this gives ropey code, +but we don't care, since it doesn't get used much. We hope. + \begin{code} #if i386_TARGET_ARCH @@ -457,12 +466,14 @@ Hence GLDZ and GLD1. Bwahahahahahahaha! | ADD Size Operand Operand | SUB Size Operand Operand + | IMUL Size Operand Operand --- Multiplication (signed and unsigned), Division (signed and unsigned), --- result in %eax, %edx. +-- Quotient and remainder. SEE comment above -- these are not +-- real x86 insns; instead they are expanded when printed +-- into a sequence of real insns. - | IMUL Size Operand Operand - | IDIV Size Operand + | IQUOT Size Operand Operand + | IREM Size Operand Operand -- Simple bit-twiddling. diff --git a/ghc/compiler/nativeGen/PprMach.lhs b/ghc/compiler/nativeGen/PprMach.lhs index f647768..b8e75f4 100644 --- a/ghc/compiler/nativeGen/PprMach.lhs +++ b/ghc/compiler/nativeGen/PprMach.lhs @@ -931,7 +931,6 @@ pprInstr (ADD size src dst) = pprSizeOpOp SLIT("add") size src dst pprInstr (SUB size src dst) = pprSizeOpOp SLIT("sub") size src dst pprInstr (IMUL size op1 op2) = pprSizeOpOp SLIT("imul") size op1 op2 -pprInstr (IDIV size op) = pprSizeOp SLIT("idiv") size op pprInstr (AND size src dst) = pprSizeOpOp SLIT("and") size src dst pprInstr (OR size src dst) = pprSizeOpOp SLIT("or") size src dst @@ -962,6 +961,8 @@ pprInstr (JMP dsts (OpImm imm)) = (<>) (ptext SLIT("\tjmp ")) (pprImm imm) pprInstr (JMP dsts op) = (<>) (ptext SLIT("\tjmp *")) (pprOperand L op) pprInstr (CALL imm) = (<>) (ptext SLIT("\tcall ")) (pprImm imm) +pprInstr (IQUOT sz src dst) = pprInstr_quotRem True sz src dst +pprInstr (IREM sz src dst) = pprInstr_quotRem False sz src dst -- Simulating a flat register set on the x86 FP stack is tricky. -- you have to free %st(7) before pushing anything on the FP reg stack @@ -1099,6 +1100,24 @@ pprInstr GFREE ptext SLIT("\tffree %st(4) ;ffree %st(5) ;ffree %st(6) ;ffree %st(7)") ] + +pprInstr_quotRem isQuot sz src dst + | case sz of L -> False; _ -> True + = panic "pprInstr_quotRem: dunno how to do non-32bit operands" + | otherwise + = vcat [ + (text "\t# BEGIN " <> fakeInsn), + (text "\tpushl $0; pushl %eax; pushl %edx; pushl " <> pprOperand sz src), + (text "\tmovl " <> pprOperand sz dst <> text ",%eax; xorl %edx,%edx; cltd"), + (text "\tdivl 0(%esp); movl " <> text resReg <> text ",12(%esp)"), + (text "\tpopl %edx; popl %edx; popl %eax; popl " <> pprOperand sz dst), + (text "\t# END " <> fakeInsn) + ] + where + resReg = if isQuot then "%eax" else "%edx" + opStr = if isQuot then "IQUOT" else "IREM" + fakeInsn = text opStr <+> pprOperand sz src <> char ',' <+> pprOperand sz dst + -------------------------- -- coerce %st(0) to the specified size diff --git a/ghc/compiler/nativeGen/RegAllocInfo.lhs b/ghc/compiler/nativeGen/RegAllocInfo.lhs index 09f7083..4cc220b 100644 --- a/ghc/compiler/nativeGen/RegAllocInfo.lhs +++ b/ghc/compiler/nativeGen/RegAllocInfo.lhs @@ -236,7 +236,8 @@ regUsage instr = case instr of ADD sz src dst -> usageRM src dst SUB sz src dst -> usageRM src dst IMUL sz src dst -> usageRM src dst - IDIV sz src -> mkRU (eax:edx:use_R src) [eax,edx] + IQUOT sz src dst -> usageRM src dst + IREM sz src dst -> usageRM src dst AND sz src dst -> usageRM src dst OR sz src dst -> usageRM src dst XOR sz src dst -> usageRM src dst @@ -330,14 +331,6 @@ regUsage instr = case instr of mkRU src dst = RU (regSetFromList (filter interesting src)) (regSetFromList (filter interesting dst)) --- Allow the spiller to de\cide whether or not it can use --- %edx as a spill temporary. -hasFixedEDX instr - = case instr of - IDIV _ _ -> True - CLTD -> True - other -> False - #endif {- i386_TARGET_ARCH -} -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #if sparc_TARGET_ARCH @@ -438,10 +431,9 @@ findReservedRegs instrs #endif #if i386_TARGET_ARCH -- We can use %fake4 and %fake5 safely for float temps. - -- Int regs are more troublesome. Only %ecx is definitely - -- available. If there are no division insns, we can use %edx - -- too. At a pinch, we also could bag %eax if there are no - -- divisions and no ccalls, but so far we've never encountered + -- Int regs are more troublesome. Only %ecx and %edx are + -- definitely. At a pinch, we also could bag %eax if there + -- are no ccalls, but so far we've never encountered -- a situation where three integer temporaries are necessary. -- -- Because registers are in short supply on x86, we give the @@ -453,7 +445,7 @@ findReservedRegs instrs = let f1 = fake5 f2 = fake4 intregs_avail - = ecx : if any hasFixedEDX instrs then [] else [edx] + = [ecx, edx] possibilities = case intregs_avail of [i1] -> [ [], [i1], [f1], [i1,f1], [f1,f2], @@ -635,7 +627,8 @@ patchRegs instr env = case instr of ADD sz src dst -> patch2 (ADD sz) src dst SUB sz src dst -> patch2 (SUB sz) src dst IMUL sz src dst -> patch2 (IMUL sz) src dst - IDIV sz src -> patch1 (IDIV sz) src + IQUOT sz src dst -> patch2 (IQUOT sz) src dst + IREM sz src dst -> patch2 (IREM sz) src dst AND sz src dst -> patch2 (AND sz) src dst OR sz src dst -> patch2 (OR sz) src dst XOR sz src dst -> patch2 (XOR sz) src dst -- 1.7.10.4