summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorflorian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2>2018-09-25 20:31:03 +0000
committerflorian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2>2018-09-25 20:31:03 +0000
commit94251f1e0a381251ce64fc7c75052034d260cc98 (patch)
tree4a846177c7a479901ea4314e8c9892c3918d5e0e
parent59ba4252495da6e8b43eef54fb187d811996f903 (diff)
downloadfpc-laksen.tar.gz
* correctly take care of short boolean evaluation when rearranging nodes during CSElaksen
git-svn-id: https://svn.freepascal.org/svn/fpc/branches/laksen@39803 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--riscv_new/compiler/nutils.pas13
-rw-r--r--riscv_new/compiler/optcse.pas12
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