From c59bd8c29a1a6f72a59d4a3dddaec794a9e9626e Mon Sep 17 00:00:00 2001 From: florian Date: Wed, 4 Apr 2018 21:39:46 +0000 Subject: [PATCH] + calculate loop unrolling using node_count_weighted which takes care of nodes generating no code * optimized unrolling calculation git-svn-id: trunk@38688 - --- compiler/nutils.pas | 18 ++++++++++++++++++ compiler/optloop.pas | 8 ++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/compiler/nutils.pas b/compiler/nutils.pas index 16053ba901..c6d1b1e804 100644 --- a/compiler/nutils.pas +++ b/compiler/nutils.pas @@ -123,6 +123,8 @@ interface rough estimation how large the tree "node" is } function node_count(node : tnode) : dword; + function node_count_weighted(node : tnode) : dword; + { returns true, if the value described by node is constant/immutable, this approximation is safe if no dirty tricks like buffer overflows or pointer magic are used } function is_const(node : tnode) : boolean; @@ -1359,6 +1361,22 @@ implementation end; + function donodecount_weighted(var n: tnode; arg: pointer): foreachnoderesult; + begin + if not(n.nodetype in [blockn,statementn,callparan,nothingn]) then + inc(nodecount); + result:=fen_false; + end; + + + function node_count_weighted(node : tnode) : dword; + begin + nodecount:=0; + foreachnodestatic(node,@donodecount_weighted,nil); + result:=nodecount; + end; + + function is_const(node : tnode) : boolean; begin result:=is_constnode(node) or diff --git a/compiler/optloop.pas b/compiler/optloop.pas index 80554c409d..5c2a287b34 100644 --- a/compiler/optloop.pas +++ b/compiler/optloop.pas @@ -51,13 +51,17 @@ unit optloop; function number_unrolls(node : tnode) : cardinal; begin + { calculate how often a loop shall be unrolled. + + The term (60*ord(node_count_weighted(node)<15)) is used to get small loops unrolled more often as + the counter management takes more time in this case. } {$ifdef i386} { multiply by 2 for CPUs with a long pipeline } if current_settings.optimizecputype in [cpu_Pentium4] then - number_unrolls:=60 div node_count(node) + number_unrolls:=trunc(round((60+(60*ord(node_count_weighted(node)<15)))/max(node_count_weighted(node),1))) else {$endif i386} - number_unrolls:=30 div node_count(node); + number_unrolls:=trunc(round((30+(60*ord(node_count_weighted(node)<15)))/max(node_count_weighted(node),1))); if number_unrolls=0 then number_unrolls:=1;