Recent

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

lagprogramming

  • Sr. Member
  • ****
  • Posts: 406
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);
  25.         addq    $1,%rax
  26.         ret
  27.         .balign 16,0x90
  28. .Lj7:
  29. .Ll4:
  30. # [10] one: inc(result);
  31.         addq    $1,%rax
  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);
  61.         addq    $1,%rax
  62.         ret
  63.         .p2align 4,,10
  64.         .p2align 3
  65. .Lj11:
  66. .Ll10:
  67. # [19] else inc(result);
  68.         addq    $1,%rax
  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.

 

TinyPortal © 2005-2018