Skip to content

Commit

Permalink
fbc: float to boolean conversion handling
Browse files Browse the repository at this point in the history
- fbc: internal add AST_OP_BOOLNOT logical unary operator
- gcc backend: used internally by gcc backend for emitting the logical not '!' operator
- gas SSE backend: add operation to load Boolean from Float
- gas SSE/x86 backend: check parity (NaN) on Float to boolean conversion, extra check is removed
  when using '-fpmode fast' and enabled in '-fpmode precise' (the default).
- test-suite: add test for float to bool

The intent with this change is have cbool(float) behave consistently across all targets
- cbool( float ) is FALSE if and only if float = 0.
- For any other value (including NaN's) cbool(float) returns TRUE
  • Loading branch information
jayrm committed Jun 25, 2023
1 parent 94db491 commit 404c117
Show file tree
Hide file tree
Showing 8 changed files with 306 additions and 35 deletions.
1 change: 1 addition & 0 deletions changelog.txt
Expand Up @@ -3,6 +3,7 @@ Version 1.20.0
[changed]
- internal: (WIP) changes to all backends gcc/llvm/gas64/gas/gas+SSE for floating point comparison handling
- allow '-fpmode fast' command line option for any target (previously was SSE only) - this can be used augment floating point handling where some accuracy is sacrificed for smaller and faster code generation
- CBOOL(float-expression) returns false if and only if float-expression is zero (0), otherwise returns true (including NaN's)

[added]

Expand Down
1 change: 1 addition & 0 deletions src/compiler/ast-node-misc.bas
Expand Up @@ -799,6 +799,7 @@ dim shared dbg_astNodeOpNames( 0 to AST_OPCODES - 1 ) as NameInfo = _
( /' @"AST_OP_LE" , '/ @"<=" /' , 0 '/ ), _
( /' @"AST_OP_IS" , '/ @"IS" /' , 0 '/ ), _
( /' @"AST_OP_NOT" , '/ @"NOT" /' , 0 '/ ), _
( /' @"AST_OP_BOOLNOT" , '/ @"BOOLNOT" /' , 0 '/ ), _
( /' @"AST_OP_PLUS" , '/ @"+" /' , 0 '/ ), _
( /' @"AST_OP_NEG" , '/ @"NEG" /' , 0 '/ ), _
( /' @"AST_OP_HADD" , '/ @"HADD" /' , 0 '/ ), _
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/ast-op.bi
Expand Up @@ -60,7 +60,8 @@ enum AST_OP
AST_OP_LE
AST_OP_IS

AST_OP_NOT
AST_OP_NOT '' bitwise NOT
AST_OP_BOOLNOT '' logical NOT, used internally in gcc backend
AST_OP_PLUS
AST_OP_NEG

Expand Down
1 change: 1 addition & 0 deletions src/compiler/ast.bas
Expand Up @@ -125,6 +125,7 @@ dim shared ast_opTB( 0 to AST_OPCODES-1 ) as AST_OPINFO => _
(AST_NODECLASS_COMP , AST_OPFLAGS_NONE or AST_OPFLAGS_RELATIONAL, @"<=" ), _ '' AST_OP_LE
(AST_NODECLASS_COMP , AST_OPFLAGS_NONE, @"is" ), _ '' AST_OP_IS
(AST_NODECLASS_UOP , AST_OPFLAGS_NONE, @"not" ), _ '' AST_OP_NOT
(AST_NODECLASS_UOP , AST_OPFLAGS_NONE, @"boolnot" ), _ '' AST_OP_BOOLNOT
(AST_NODECLASS_UOP , AST_OPFLAGS_NONE, @"+" ), _ '' AST_OP_PLUS
(AST_NODECLASS_UOP , AST_OPFLAGS_NONE, @"-" ), _ '' AST_OP_NEG
(AST_NODECLASS_UOP , AST_OPFLAGS_NONE, @"HADD" ), _ '' AST_OP_HADD
Expand Down
79 changes: 58 additions & 21 deletions src/compiler/emit_SSE.bas
Expand Up @@ -14,6 +14,7 @@
#include once "emit-private.bi"

dim shared _emitLOADB2F_x86 as sub( byval dvreg as IRVREG ptr, byval svreg as IRVREG ptr )
dim shared _emitLOADF2B_x86 as sub( byval dvreg as IRVREG ptr, byval svreg as IRVREG ptr )

private sub hULONG2DBL _
( _
Expand Down Expand Up @@ -68,6 +69,54 @@ private sub _emitLOADB2F_SSE( byval dvreg as IRVREG ptr, byval svreg as IRVREG p

end sub

private sub hMoveSSEREGToFPUSTACK _
( _
byval dvreg as IRVREG ptr, _
byval svreg as IRVREG ptr _
)

dim as string src
dim as integer sdsize

'' use stack to move from SSE register to FPU STACK
'' This is just to get some cbool(expression) stuff
'' working for the test-suite. It should probably
'' have it's own implementation.

'' load SSE register and push to FPU STACK
sdsize = typeGetSize( svreg->dtype )
outp "sub esp" + COMMA + str( sdsize )

hPrepOperand( svreg, src )

if( sdsize > 4 ) then
outp "movlpd qword ptr [esp]" + COMMA + src
outp "fld qword ptr [esp]"
else
outp "movss dword ptr [esp]" + COMMA + src
outp "fld dword ptr [esp]"
end if

outp "add esp" + COMMA + str( sdsize )

end sub

private sub _emitLOADF2B_SSE( byval dvreg as IRVREG ptr, byval svreg as IRVREG ptr )

ASSERT_PROC_DECL( EMIT_BOPCB )

if( svreg->regFamily = IR_REG_SSE ) then
if( svreg->typ = IR_VREGTYPE_REG ) then
hMoveSSEREGToFPUSTACK( dvreg, svreg )
end if
end if

'' let x86 LOADF2B handle it from the FPU STACK to destine
_emitLOADF2B_x86( dvreg, svreg )

end sub


'':::::
private sub _emitSTORF2L_SSE _
( _
Expand All @@ -77,38 +126,20 @@ private sub _emitSTORF2L_SSE _

ASSERT_PROC_DECL( EMIT_BOPCB )

dim as string dst, src
dim as integer sdsize
dim as string dst

'' signed?
if( typeIsSigned( dvreg->dtype ) = 0) then exit sub

if( svreg->regFamily = IR_REG_SSE ) then

sdsize = typeGetSize( svreg->dtype )
outp "sub esp" + COMMA + str( sdsize )

hPrepOperand( svreg, src )

if( sdsize > 4 ) then
outp "movlpd qword ptr [esp]" + COMMA + src
outp "fld qword ptr [esp]"
else
outp "movss dword ptr [esp]" + COMMA + src
outp "fld dword ptr [esp]"
end if

outp "add esp" + COMMA + str( sdsize )
hMoveSSEREGToFPUSTACK( dvreg, svreg )
end if

hPrepOperand( dvreg, dst )

outp "fistp " + dst

end sub



'':::::
private sub _emitSTORF2I_SSE _
( _
Expand Down Expand Up @@ -2971,13 +3002,19 @@ function _init_opFnTB_SSE _
) as integer

'' load
_emitLOADB2F_x86 = _opFnTB_SSE[EMIT_OP_LOADB2F]
if( _emitLOADB2F_x86 = NULL ) then
_emitLOADB2F_x86 = _opFnTB_SSE[EMIT_OP_LOADB2F]
end if
if( _emitLOADF2B_x86 = NULL ) then
_emitLOADF2B_x86 = _opFnTB_SSE[EMIT_OP_LOADF2B]
end if
_opFnTB_SSE[EMIT_OP_LOADF2I] = EMIT_CBENTRY(LOADF2I_SSE)
_opFnTB_SSE[EMIT_OP_LOADI2F] = EMIT_CBENTRY(LOADI2F_SSE)
_opFnTB_SSE[EMIT_OP_LOADF2L] = EMIT_CBENTRY(LOADF2L_SSE)
_opFnTB_SSE[EMIT_OP_LOADL2F] = EMIT_CBENTRY(LOADL2F_SSE)
_opFnTB_SSE[EMIT_OP_LOADF2F] = EMIT_CBENTRY(LOADF2F_SSE)
_opFnTB_SSE[EMIT_OP_LOADB2F] = EMIT_CBENTRY(LOADB2F_SSE)
_opFnTB_SSE[EMIT_OP_LOADF2B] = EMIT_CBENTRY(LOADF2B_SSE)

'' store
_opFnTB_SSE[EMIT_OP_STORF2I] = EMIT_CBENTRY(STORF2I_SSE)
Expand Down
20 changes: 13 additions & 7 deletions src/compiler/emit_x86.bas
Expand Up @@ -6733,21 +6733,27 @@ private sub _emitLOADF2B( byval dvreg as IRVREG ptr, byval svreg as IRVREG ptr )
if( env.clopt.cputype >= FB_CPUTYPE_686 ) then
outp "fldz"
outp "fcomip"
outp "setnz al"

else
outp "ftst"
outp "fnstsw ax"

#if 1
outp "sahf"
end if

if( env.clopt.fpmode = FB_FPMODE_FAST ) then
outp "setnz al"
else
outp "setp ah"
outp "setnz al"
#else
outp "or al, ah"
end if

#if 0
'' alternate to sahf above - requires modification to above logic to use
'' i.e. don't use sahf
outp "test ah, 0b01000000"
outp "setz al"
#endif

end if
#endif

outp "fstp st(0)"

Expand Down
12 changes: 6 additions & 6 deletions src/compiler/ir-hlc.bas
Expand Up @@ -1932,7 +1932,7 @@ private function exprNewUOP _
assert( typeGetPtrCnt( dtype ) > 0 )
dtype = typeDeref( dtype )

case AST_OP_NEG, AST_OP_NOT
case AST_OP_NEG, AST_OP_NOT, AST_OP_BOOLNOT
'' peep-hole optimization:
'' -(-(foo)) -> foo
'' ~(~(foo)) -> foo
Expand Down Expand Up @@ -2273,6 +2273,7 @@ private function hUopToStr _
case AST_OP_DEREF : function = @"*"
case AST_OP_NEG : function = @"-"
case AST_OP_NOT : function = @"~"
case AST_OP_BOOLNOT: function = @"!"

case AST_OP_ABS
is_builtin = TRUE
Expand Down Expand Up @@ -2892,12 +2893,12 @@ private sub _emitBop _

select case as const( op )
case AST_OP_EQ, AST_OP_NE, AST_OP_GT, AST_OP_LT, AST_OP_GE, AST_OP_LE
l = exprNewBOP( op, l, r )

if( (options and IR_EMITOPT_REL_DOINVERSE) <> 0 ) then
op = astGetInverseLogOp( op )
l = exprNewUOP( AST_OP_BOOLNOT, l )
end if

l = exprNewBOP( op, l, r )

'' comparisons returning a boolean produce 0/1,
'' comparisons returning an integer produce 0/-1.
if( vr->dtype <> FB_DATATYPE_BOOLEAN ) then
Expand Down Expand Up @@ -2976,8 +2977,7 @@ private sub _emitUop _
'' the inverse 1/0 boolean. Thus it can't be implemented as
'' bitwise NOT.
'' Do: <expr == 0>
'' We could also do <!expr>, but we don't support emitting the
'' ! operator at the moment.
'' !!!TODO!!! We could also do <!expr>, see AST_OP_BOOLNOT
expr = exprNewBOP( AST_OP_EQ, expr, exprNewIMMi( 0 ) )
else
expr = exprNewUOP( op, expr )
Expand Down

0 comments on commit 404c117

Please sign in to comment.