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.