【问题标题】:Compiler optimizations on case statement编译器对 case 语句的优化
【发布时间】:2011-01-02 16:24:50
【问题描述】:

我想拓宽我在编译器编写方面的知识和技能,尤其是优化方面。我想知道对于字符串类型的 case 表达式的 case 语句有哪些优化。例如在 Object Pascal 中:

ReadLn(s);
case s of
  'abc','def': ...;
  'xyz'      : ...;
  otherwise    ...;
end;

在 Free Pascal 中,这被转换为 AnsiCompareText 的后续调用。其他语言实现呢?我知道至少 PHP、Nimrod 和 Octave 都支持这个。

【问题讨论】:

    标签: string compiler-optimization case-statement


    【解决方案1】:

    作为应用程序开发人员,我希望将最有可能执行的案例放在最前面,以限制比较的次数。不幸的是,从编译器的角度来看,直到运行时您才会知道这一点。

    如果我正在编写自己的编译器并遇到像上面这样的 case 语句,我可能会尝试对比较进行排序并进行二分查找以确定采用哪条路径。这有望稍微改善最坏的情况。

    【讨论】:

    • 我实际上正在考虑将后缀树“集成到”结果代码中。我的意思是说没有构建真正的后缀树,但是指令序列的工作方式就像在后缀树中搜索一样。这种优化是非常优化的(也许更多的是消除死路)并且只花费 O(n),其中 n 是变量中字符串的长度
    • @LeleDumbo 这实际上是我的想法,但找不到单词。考虑到您在运行时了解整个数据集,没有理由不能做出非常有效的搜索算法。
    【解决方案2】:

    在 C 中,char 数组(字符串)没有“大小写”等价物,但在某种程度上可以使用位移宏和切换大小写来完成

    #define FIVE_CHARS(c1,c2,c3,c4,c5)  (((((((((c5)<<7)|(c4))<<6)|(c3))<<6)|(c2))<<6)|(c1))
    
    while (argc-->0){
      switch ( FIVE_CHARS(argv[argc][0],argv[argc][1],argv[argc][2],argv[argc][3],argv[argc][4]) ){
         case FIVE_CHARS('-','h','e','l','p')  :
         case FIVE_CHARS('-','-','h','e','l')   :
         case FIVE_CHARS('-','h','\0','\0','\0')   :
         case FIVE_CHARS('-','?','\0','\0','\0')   :
           usage();
         break;
         case FIVE_CHARS('-','a','r','g','1')   :
           setflag1();
         break;
         default:
           assert("Argument not supported");
      }
    }
    

    编译器可能会将其编译为具有少量比较的一系列 if 或具有大量比较的跳转表。这可以显着提高代码大小和速度,因为大多数位移(在 case 语句中的位移)是在编译时而不是运行时完成的,其余位移操作(开关中的位移)相对便宜且一次比较只需要一次(基本上否定了将最常见的路径放在首位的任何需要)......对于匹配五个字符的情况,您可以为不常见的字符/字符添加额外的 switch case,或者只使用 strcmp() 。 .. 不过,在少数情况下只需要 strcmp,而不是 if strcmp() {} else if strcmp() {} else ...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多