epsilon-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [epsilon-devel] How to write a simple code generation which is not t


From: Jose E. Marchesi
Subject: Re: [epsilon-devel] How to write a simple code generation which is not terrible
Date: Thu, 31 Jan 2019 14:11:29 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux)

    
    > What would be instruction definition look for the `plus'?
    
    The instruction will look like this (to make things even nicer let us
    say that 1 and 2 are both common literals occurring in the first or
    second position, so they will not even be ever residualized):
    
    instruction plus (?RSn 1 2, ?RSn 1 2, !RS)
      begin
        OUTPUT2_LVALUE = INPUT0_RVALUE + INPUT1_RVALUE;
      end
    end
    
    The instruction has three operands, two input-mode and one output-mode.
    I'm putting, arbitrarily, the output operand on the right.  Each of the
    inputs can be a register, a stack or an immediate.  The output can be a
    register or a stack -- of course, not an immediate.
    
    Every input operand of a stack kind entails a pop.  Having a stack-kind
    output entails a push.

    Here are the stack effects, Forth-style, for a
    few unspecialized uses of plus, which map to different specializations:
    
      plus 1, 2, %s   ( -- 3 )
      plus %s, 1, %s  ( a -- a+1 )
      plus %r0, %s, %s  ( a -- %r0+a )
      plus %s, %s, %s  ( a b -- a+b )
      plus %r1, 2, %r1  ( -- )
    
    The stack effect would be achieved automatically, by machine-generating
    code taking action before the user code is run.

I guess the pops and pushes are always generated in left-to-right order?
What about adding something like S{n} to indicate the ordering of the
stack operations?  Something like:

instruction plus (?RS{0}n 1 2, ?RS{1}n 1 2, !RS{0})

The default can be left-to-right.
    
    Nothing is needed from the user point of view.  Before the user code is
    run, the stack has been already popped or pushed (with unspecified
    elements) to achieve the stack effect of the particular specialization
    we are in.  Input (r-value) macros for stack-kind input-mode operands
    will also have been defined by reading stack elements *before* altering
    the stack, and output macros for stack-kind output-mode operands will be
    defined as l-values referring the result stack -- these may include the
    TOS.  My manual tests show that the machine code quality does not suffer
    at all despite complicated stack effect on TOS-optimized stacks, where
    push and drop also involves loads and stores; this is the discovery
    which surprised me in the first place.

Yes, I hear you.  I try to be careful while writing my instruction
definitions to save a drop here, or a push there... when it seems that
GCC can do a better job :P
    
    > Also, how would this support non-consuming instructions?  Using an
    > instruction attribute?
    
    I would say a new mode; we can call it @, for example.  The idea would
    make sense for writing as well.  We could sat that @ works exactly like
    ?, except that when the operand kind is a stack, then the argument is
    not dropped.

Makes sense.
    
    I haven't thought very hard on non-consuming instructions.  They make
    things less intuitive and less orthogonal when such instructions are
    few, but I understand that they would be nice, in a context where you
    don't have a complete set of instructions with every possible operand
    kind in every position: a non-consuming plus would be useless when you
    have my plus defined above, but that might be expensive or undesirable
    to have for every instruction.
    
    Do you find any flaws with this?
    
Well... with the explicit (and optional) ordering of stack operands, I
guess I would certainly use this for many of my instructions: the code
generated would be much smaller.  Really complex instructions involving
the stack will still have to be manually written, but that's just ok.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]