diff --git a/.gitattributes b/.gitattributes index e33fff124b..6ada342ede 100644 --- a/.gitattributes +++ b/.gitattributes @@ -18621,6 +18621,7 @@ tests/webtbs/tw38238.pp svneol=native#text/pascal tests/webtbs/tw38249.pp svneol=native#text/pascal tests/webtbs/tw38259.pp svneol=native#text/pascal tests/webtbs/tw38267a.pp svneol=native#text/pascal +tests/webtbs/tw38267b.pp svneol=native#text/pascal tests/webtbs/tw3827.pp svneol=native#text/plain tests/webtbs/tw3829.pp svneol=native#text/plain tests/webtbs/tw3833.pp svneol=native#text/plain diff --git a/compiler/nadd.pas b/compiler/nadd.pas index b484c2449f..62689f4fe4 100644 --- a/compiler/nadd.pas +++ b/compiler/nadd.pas @@ -512,9 +512,10 @@ implementation var hp,hp2 : tnode; begin - { keep the order of val+const else pointer operations might cause an error } + { keep the order of val+const else pointer and string operations might cause an error } hp:=taddnode(left).left; - taddnode(left).left:=right; + taddnode(left).left:=taddnode(left).right; + taddnode(left).right:=right; left.resultdef:=nil; do_typecheckpass(left); hp2:=left.simplify(forinline); @@ -1206,7 +1207,23 @@ implementation exit; end; - { set constant evaluation } + { try to fold + op + / \ + op const1 + / \ + val const2 + + while operating on strings + } + if (cs_opt_level2 in current_settings.optimizerswitches) and (nodetype=addn) and ((rt=stringconstn) or is_constcharnode(right)) and (left.nodetype=nodetype) and + (compare_defs(resultdef,left.resultdef,nothingn)=te_exact) and ((taddnode(left).right.nodetype=stringconstn) or is_constcharnode(taddnode(left).right)) then + begin + Result:=SwapRightWithLeftLeft; + exit; + end; + + { set constant evaluation } if (right.nodetype=setconstn) and not assigned(tsetconstnode(right).left) and (left.nodetype=setconstn) and diff --git a/tests/webtbs/tw38267b.pp b/tests/webtbs/tw38267b.pp new file mode 100644 index 0000000000..4dd0449d81 --- /dev/null +++ b/tests/webtbs/tw38267b.pp @@ -0,0 +1,92 @@ +{ %opt=-O3 -Sg } +{$mode objfpc} {$longstrings+} +label start1, end1, start2, end2, start3, end3; + +var + s: string; + +begin + writeln('31 concatenated string literals, completely folded:'); +start1: + s := + 'Once like a Great House' + LineEnding + + 'founded on sand,' + LineEnding + + 'Stood our Temple' + LineEnding + + 'whose pillars on troubles were based.' + LineEnding + + 'Now mischievous spirits, bound,' + LineEnding + + 'in dim corners stand,' + LineEnding + + 'Rotted columns, but' + LineEnding + + 'with iron-bound bands embraced' + LineEnding + + 'Cracked, crumbling marble,' + LineEnding + + 'tempered on every hand,' + LineEnding + + 'By strong steel' + LineEnding + + 'forged in fire and faith.' + LineEnding + + 'Shackled, these wayward servants' + LineEnding + + 'serve the land,' + LineEnding + + 'The Temple secured' + LineEnding + + 'by the Builder’s grace.'; +end1: + writeln(Copy(s, 1, 0), PtrUint(CodePointer(@end1) - CodePointer(@start1)), ' b of code'); + { more than 100 bytes of code might point out that the constants are not folded } + if PtrUint(CodePointer(@end1) - CodePointer(@start1))>100 then + halt(1); + writeln; + + writeln('1 dynamic string concatenated with 31 literals, they could fold but didn''t at all:'); +start2: + s := Copy('', 1, 0) + + 'Once like a Great House' + LineEnding + + 'founded on sand,' + LineEnding + + 'Stood our Temple' + LineEnding + + 'whose pillars on troubles were based.' + LineEnding + + 'Now mischievous spirits, bound,' + LineEnding + + 'in dim corners stand,' + LineEnding + + 'Rotted columns, but' + LineEnding + + 'with iron-bound bands embraced' + LineEnding + + 'Cracked, crumbling marble,' + LineEnding + + 'tempered on every hand,' + LineEnding + + 'By strong steel' + LineEnding + + 'forged in fire and faith.' + LineEnding + + 'Shackled, these wayward servants' + LineEnding + + 'serve the land,' + LineEnding + + 'The Temple secured' + LineEnding + + 'by the Builder’s grace.'; +end2: + writeln(Copy(s, 1, 0), PtrUint(CodePointer(@end2) - CodePointer(@start2)), ' b of code'); + { more than 100 bytes of code might point out that the constants are not folded, + example x86_64-linux: not folded: 639 bytes; folded: 76 bytes + } + if PtrUint(CodePointer(@end2) - CodePointer(@start2))>100 then + halt(2); + writeln; + + writeln('16 literals concatenated with 1 dynamic string and 15 more literals, first 16 folded but last 15 did not:'); +start3: + s := + 'Once like a Great House' + LineEnding + + 'founded on sand,' + LineEnding + + 'Stood our Temple' + LineEnding + + 'whose pillars on troubles were based.' + LineEnding + + 'Now mischievous spirits, bound,' + LineEnding + + 'in dim corners stand,' + LineEnding + + 'Rotted columns, but' + LineEnding + + 'with iron-bound bands embraced' + LineEnding + + Copy('', 1, 0) + + 'Cracked, crumbling marble,' + LineEnding + + 'tempered on every hand,' + LineEnding + + 'By strong steel' + LineEnding + + 'forged in fire and faith.' + LineEnding + + 'Shackled, these wayward servants' + LineEnding + + 'serve the land,' + LineEnding + + 'The Temple secured' + LineEnding + + 'by the Builder’s grace.'; +end3: + writeln(Copy(s, 1, 0), PtrUint(CodePointer(@end3) - CodePointer(@start3)), ' b of code'); + { more than 300 bytes of code might point out that the constants are not folded, + example x86_64-linux: not folded: 369 bytes; folded: 120 bytes + } + if PtrUint(CodePointer(@end3) - CodePointer(@start3))>300 then + halt(3); + writeln; + writeln('ok'); +end.