From 94251f1e0a381251ce64fc7c75052034d260cc98 Mon Sep 17 00:00:00 2001 From: florian Date: Tue, 25 Sep 2018 20:31:03 +0000 Subject: * correctly take care of short boolean evaluation when rearranging nodes during CSE git-svn-id: https://svn.freepascal.org/svn/fpc/branches/laksen@39803 3ad0048d-3df7-0310-abae-a5850022a9f2 --- riscv_new/compiler/nutils.pas | 13 ++++++++++++- riscv_new/compiler/optcse.pas | 12 ++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/riscv_new/compiler/nutils.pas b/riscv_new/compiler/nutils.pas index fa91b3bee4..c276217800 100644 --- a/riscv_new/compiler/nutils.pas +++ b/riscv_new/compiler/nutils.pas @@ -161,6 +161,10 @@ interface { include or exclude cs from p.localswitches } procedure node_change_local_switch(p : tnode;cs : tlocalswitch;enable : boolean); + { returns true, if p is a node which shall be short boolean evaluated, + if it is not an orn/andn with boolean operans, the result is undefined } + function doshortbooleval(p : tnode) : Boolean; + implementation uses @@ -1459,7 +1463,8 @@ implementation exclude(p.localswitches, plocalswitchchange(plsc)^.cs); result:=fen_true; end; - + + procedure node_change_local_switch(p : tnode;cs : tlocalswitch;enable : boolean); var lsc : tlocalswitchchange; @@ -1469,4 +1474,10 @@ implementation foreachnodestatic(p,@do_change_local_settings,@lsc); end; + + function doshortbooleval(p : tnode) : Boolean; + begin + Result:=(p.nodetype in [orn,andn]) and ((nf_short_bool in taddnode(p).flags) or not(cs_full_boolean_eval in p.localswitches)); + end; + end. diff --git a/riscv_new/compiler/optcse.pas b/riscv_new/compiler/optcse.pas index 32db6b26bc..c34da85563 100644 --- a/riscv_new/compiler/optcse.pas +++ b/riscv_new/compiler/optcse.pas @@ -298,9 +298,9 @@ unit optcse; if not(csedomain) then begin { try to transform the tree to get better cse domains, consider: - + + + (1) / \ - + C + (2) + C / \ A B @@ -320,8 +320,7 @@ unit optcse; { either if fastmath is on } ((cs_opt_fastmath in current_settings.optimizerswitches) or { or for the logical operators, they cannot overflow } - ((n.nodetype in [andn,orn]) and - (n.localswitches*[cs_full_boolean_eval]=[])) or + (n.nodetype in [andn,orn]) or { or for integers if range checking is off } ((is_integer(n.resultdef) and (n.localswitches*[cs_check_range,cs_check_overflow]=[]) and @@ -330,8 +329,9 @@ unit optcse; (is_set(n.resultdef)) ) then while (n.nodetype=tbinarynode(n).left.nodetype) and - { don't swap elements with full boolean evaluation. this might not be safe } - (tbinarynode(n).left.localswitches*[cs_full_boolean_eval]=[]) and + { if node (1) is fully boolean evaluated and node (2) not, we cannot do the swap as is might result in B being evaluated always, + the other way round is no problem, C is still evaluated only if needed } + (not(is_boolean(n.resultdef)) or not(n.nodetype in [andn,orn]) or doshortbooleval(n) or not(doshortbooleval(tbinarynode(n).left))) and { the resulttypes of the operands we'll swap must be equal, required in case of a 32x32->64 multiplication, then we cannot swap out one of the 32 bit operands for a 64 bit one -- cgit v1.2.1