[project @ 2000-11-13 11:04:06 by simonmar]
authorsimonmar <unknown>
Mon, 13 Nov 2000 11:04:07 +0000 (11:04 +0000)
committersimonmar <unknown>
Mon, 13 Nov 2000 11:04:07 +0000 (11:04 +0000)
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
ghc/compiler/nativeGen/MachMisc.lhs
ghc/compiler/nativeGen/PprMach.lhs
ghc/compiler/nativeGen/RegAllocInfo.lhs

index 4406d45..df4c2a6 100644 (file)
@@ -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 ->
index a98eb16..7113822 100644 (file)
@@ -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.
 
index f647768..b8e75f4 100644 (file)
@@ -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
index 09f7083..4cc220b 100644 (file)
@@ -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