### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: Optimization of Case statements with enumeration types  (Read 318 times)

#### lagprogramming

• Sr. Member
• Posts: 391
##### Optimization of Case statements with enumeration types
« on: March 16, 2023, 12:29:56 pm »
When all elements of an enumeration type appear in a case statement, FPC should produce code as if the last one would be an "else".
Here is the simplest example I could think of.
Code: Pascal  [Select][+][-]
1. program project1;
2.
3. type TNo=(zero,one);
4.
5. function version1(const input:TNo):sizeuint;
6. begin
7.   result:=0;
8.   case input of
9.     zero: inc(result);
10.     one: inc(result);
11.   end;
12. end;
13.
14. function version2(const input:TNo):sizeuint;
15. begin
16.   result:=0;
17.   case input of
18.     zero: inc(result);
19.     else inc(result); //Instead of "one: inc(result);"
20.   end;
21. end;
22.
23.
24. var
25.   x:TNo;
26. begin
27.   if paramcount=0 then x:=zero else x:=one;
28.   writeln(version1(x));
29.   writeln(version2(x));
30. end.

Here is the code produced with maximum level of optimizations.
Code: Pascal  [Select][+][-]
1. .section .text.n_p\$project1_\$\$_version1\$tno\$\$qword,"ax"
2.         .balign 16,0x90
3. .globl  P\$PROJECT1_\$\$_VERSION1\$TNO\$\$QWORD
4.         .type   P\$PROJECT1_\$\$_VERSION1\$TNO\$\$QWORD,@function
5. P\$PROJECT1_\$\$_VERSION1\$TNO\$\$QWORD:
6. .Lc2:
7. # Var input located in register edi
8. # [project1.lpr]
9. # [6] begin
10. # Var \$result located in register rax
11. .Ll1:
12. # [7] result:=0;
13.         xorl    %eax,%eax
14. .Ll2:
15. # [8] case input of
16.         testl   %edi,%edi
17.         je      .Lj6
18.         subl    \$1,%edi
19.         je      .Lj7
20.         ret
21.         .balign 16,0x90
22. .Lj6:
23. .Ll3:
24. # [9] zero: inc(result);
26.         ret
27.         .balign 16,0x90
28. .Lj7:
29. .Ll4:
30. # [10] one: inc(result);
32.         .balign 16,0x90
33. .Lc3:
34. .Ll5:
35. # [12] end;
36.         ret
37. .Lc1:
38. .Lt2:
39. .Le0:
40.         .size   P\$PROJECT1_\$\$_VERSION1\$TNO\$\$QWORD, .Le0 - P\$PROJECT1_\$\$_VERSION1\$TNO\$\$QWORD
41. .Ll6:
42.
43. .section .text.n_p\$project1_\$\$_version2\$tno\$\$qword,"ax"
44.         .balign 16,0x90
45. .globl  P\$PROJECT1_\$\$_VERSION2\$TNO\$\$QWORD
46.         .type   P\$PROJECT1_\$\$_VERSION2\$TNO\$\$QWORD,@function
47. P\$PROJECT1_\$\$_VERSION2\$TNO\$\$QWORD:
48. .Lc5:
49. # Var input located in register edi
50. # [15] begin
51. # Var \$result located in register rax
52. .Ll7:
53. # [16] result:=0;
54.         xorl    %eax,%eax
55. .Ll8:
56. # [17] case input of
57.         testl   %edi,%edi
58.         jne     .Lj11
59. .Ll9:
60. # [18] zero: inc(result);
62.         ret
63.         .p2align 4,,10
64.         .p2align 3
65. .Lj11:
66. .Ll10:
67. # [19] else inc(result);
69. .Lc6:
70. .Ll11:
71. # [21] end;
72.         ret
73. .Lc4:
74. .Lt3:
75. .Le1:
76.         .size   P\$PROJECT1_\$\$_VERSION2\$TNO\$\$QWORD, .Le1 - P\$PROJECT1_\$\$_VERSION2\$TNO\$\$QWORD
77. .Ll12:

The compiler should produce the same code for both versions of the function. Notice that in version2 "one:" is replaced with "else". FPC produces a useless conditional jump for the last one, making the code bigger and slower.
This optimization can't be safely done by a programmer by hand because an addition to the enumeration type would automatically introduce bugs at the "else" parts.