[fpc-devel] Division nodes

J. Gareth Moreton gareth at moreton-family.com
Thu May 11 11:04:04 CEST 2023


Hi everyone,

I need to ask a question about how division nodes are set up (I'm 
looking at possible optimisation techniques).  I've written the 
following procedure:

procedure DoDivMod(N, D: Integer; out Q, R: Integer);
begin
   Q := N div D;
   R := N mod D;
end;

Fairly simple and to the point.  However, even before the first node 
pass, the following node tree is generated for an integer division 
operation:

<statementn pos="24,10">
    <ifn resultdef="$void" pos="24,10" flags="nf_internal">
       <condition>
          <equaln resultdef="Boolean" pos="24,10" flags="nf_internal">
             <loadn resultdef="LongInt" pos="24,14">
                <symbol>D</symbol>
             </loadn>
             <ordconstn resultdef="LongInt" pos="24,10" rangecheck="FALSE">
                <value>-1</value>
             </ordconstn>
          </equaln>
       </condition>
       <then>
          <assignn resultdef="$void" pos="24,10" flags="nf_internal">
             <temprefn resultdef="LongInt" pos="24,10" flags="nf_write" 
id="$7C585E10">
                <typedef>LongInt</typedef>
<tempflags>ti_may_be_in_reg</tempflags>
                <temptype>tt_persistent</temptype>
             </temprefn>
             <unaryminusn resultdef="LongInt" pos="24,10">
                <loadn resultdef="LongInt" pos="24,8">
                   <symbol>N</symbol>
                </loadn>
             </unaryminusn>
          </assignn>
       </then>
       <else>
          <assignn resultdef="$void" pos="24,10" flags="nf_internal">
             <temprefn resultdef="LongInt" pos="24,10" flags="nf_write" 
id="$7C585E10">
                <typedef>LongInt</typedef>
<tempflags>ti_may_be_in_reg</tempflags>
                <temptype>tt_persistent</temptype>
             </temprefn>
             <divn resultdef="LongInt" pos="24,10">
                <loadn resultdef="LongInt" pos="24,8">
                   <symbol>N</symbol>
                </loadn>
                <loadn resultdef="LongInt" pos="24,14">
                   <symbol>D</symbol>
                </loadn>
             </divn>
          </assignn>
       </else>
    </ifn>
</statementn>

Something similar is made for "mod" as well.  I have to ask though... is 
it really necessary to check to see if the divisor is -1 and have a 
distinct assignment for it?  It's a bit of a rare edge case that usually 
just slows things down since it tends to add a comparison and a 
conditional jump to the final assembly language.  Is there some 
anomalous behaviour to a processor's division routine if the divisor is -1?

At the very least, would it be possible to remove the conditional check 
when compiling under -Os?

(I intend to see if it's possible to merge "N div D" and "N mod D" on 
x86, and possibly other processors that have a combined DIV/MOD operator).

Kit



More information about the fpc-devel mailing list