Skip to content

Commit

Permalink
fbc: x86_64: optimize SHL MOD INTDIV to use 32-bit operands
Browse files Browse the repository at this point in the history
- optimize SHL MOD INTDIV to use 32-bit operation when result will be converted to U|LONG
- convert 'clng(cint(a<32>) BOP<64> cint(b<32>))' to 'a<32> BOP<32> b<32>'

For example:
    dim as ulong a, b
    var x = a \ b         '' same as before, a & b promoted to integer, returns integer
    var y = culng(a \ b)  '' optimized to use 32-bit division, return ulong

- use this optimization for conversion to U|BYTE and U|SHORT results also
- enabled for x86_64 targets only

- code clean-up of previous commit; compare data type sizes instead of specific data types
  • Loading branch information
jayrm committed Jul 23, 2023
1 parent cfce8e8 commit d7c91fd
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 44 deletions.
1 change: 1 addition & 0 deletions changelog.txt
Expand Up @@ -7,6 +7,7 @@ Version 1.20.0
- if (float-expression) then .. equivalent to if cbool(float-expression) ...

[added]
- x86_64: optimize SHL MOD INTDIV to use 32-bit operation when result will be converted to long/ulong

[fixed]
- github #410: give consistent floating point comparisons results involving NaNs.
Expand Down
71 changes: 27 additions & 44 deletions src/compiler/ast-optimize.bas
Expand Up @@ -942,33 +942,22 @@ private function hOperandMayBe32bit( byval n as ASTNODE ptr ) as integer
return FALSE
end if

'' already a U|LONG?
select case astGetDataType(n)
case FB_DATATYPE_LONG, FB_DATATYPE_ULONG
return TRUE
end select

'' otherwise only if a conversion
if( n->class <> AST_NODECLASS_CONV ) then
return FALSE
end if

'' and integer
'' only integers, don't allow floats
if( astGetDataClass( n ) <> FB_DATACLASS_INTEGER ) then
return FALSE
end if

'' conversion must yeild a numeric integer
select case astGetDataType( n )
case FB_DATATYPE_BYTE, FB_DATATYPE_UBYTE, _
FB_DATATYPE_SHORT, FB_DATATYPE_USHORT, _
FB_DATATYPE_LONG, FB_DATATYPE_ULONG, _
FB_DATATYPE_INTEGER, FB_DATATYPE_UINT, _
FB_DATATYPE_LONGINT, FB_DATATYPE_ULONGINT _

'' already 32-bit?
select case typeGetSizeType( astGetDataType(n) )
case FB_SIZETYPE_INT32, FB_SIZETYPE_UINT32
return TRUE
end select

'' otherwise only if a conversion already exists
if( n->class = AST_NODECLASS_CONV ) then
return TRUE
end if

return FALSE
end function

Expand All @@ -984,7 +973,7 @@ private function hOptBOP32 _
return n
end if

'' !!!TODO!!! add to IR_OPT_* and use irGetOption() to
'' TODO: maybe should add to IR_OPT_* and let irGetOption()
'' control optimization of 32 bit operations on 64 bit target
if( fbGetCpuFamily() <> FB_CPUFAMILY_X86_64 ) then
return n
Expand Down Expand Up @@ -1028,44 +1017,38 @@ private function hOptBOP32 _
return n
end select

'' result of CONV is U|LONG or smaller?
select case astGetDataType( n )
case FB_DATATYPE_BYTE, FB_DATATYPE_UBYTE
case FB_DATATYPE_SHORT, FB_DATATYPE_USHORT
case FB_DATATYPE_LONG, FB_DATATYPE_ULONG
case else
'' only integers
if( astGetDataClass( n ) <> FB_DATACLASS_INTEGER ) then
return n
end select
end if

'' can't optimize if result of CONV is larger than 32bit
if( typeGetSize( astGetDataType( n ) ) > typeGetSize( FB_DATATYPE_LONG ) ) then
return n
end if

'' BOP must not yet be optimized
select case astGetDataType( l )
case FB_DATATYPE_INTEGER, FB_DATATYPE_UINT
case FB_DATATYPE_LONGINT, FB_DATATYPE_ULONGINT
case else
if( typeGetSize( astGetDataType( l ) ) <= typeGetSize( FB_DATATYPE_LONG ) ) then
return n
end select
end if

'' left side of BOP must be numeric integer
'' left side of BOP must be 32 bit or be allowed to be 32 bit
if( hOperandMayBe32bit( l->l ) = FALSE ) then
return n
end if

'' right side of BOP must be numeric integer
'' right side of BOP must be 32 bit or be allowed to be 32 bit
if( hOperandMayBe32bit( l->r ) = FALSE ) then
return n
end if

'' set the BOP's return type to U|LONG
select case astGetDataType( n )
case FB_DATATYPE_BYTE, FB_DATATYPE_SHORT, FB_DATATYPE_LONG
l->dtype = typeJoin( l->dtype, FB_DATATYPE_LONG )
'' Remove top CONV node
if( typeGetSize( astGetDataType( n ) ) <= typeGetSize( FB_DATATYPE_LONG ) ) then
l->dtype = typeJoin( l->dtype, iif( typeIsSigned( astGetDataType( n ) ), _
FB_DATATYPE_LONG, FB_DATATYPE_ULONG ) )
astDelNode( n )
n = l
case FB_DATATYPE_UBYTE, FB_DATATYPE_USHORT, FB_DATATYPE_ULONG
l->dtype = typeJoin( l->dtype, FB_DATATYPE_ULONG )
astDelNode( n )
n = l
end select
end if

'' Remove CONV to U|LONG
l->l = hTryRemoveCAST( l->l )
Expand Down

0 comments on commit d7c91fd

Please sign in to comment.