zoukankan      html  css  js  c++  java
  • [Inside HotSpot] C1循环不变代码提升优化

    如果关闭分层编译,执行GVN优化前会使用ShortLoopOptimizer做一些简单的循环优化,其中就包括循环不变代码提升(Loop Invariant Code Motion,LCM)。LCM是指将循环中不变的值移动到循环外面,消除每次进行计算的必要:

    void LoopInvariantCodeMotion::process_block(BlockBegin* block) {
        ...
      // 形参表示位于循环的所有基本块。遍历基本块中的每一条指令
      while (cur != NULL) {
        bool cur_invariant = false;
        // 指令是常量且不能发生trap;指令是算数/逻辑/位运算,操作数都是不变量且不能发生trap
        // 指令读取字段值,字段不是volatile,或者是读取数组中的某个元素,数组是不变量等;
        // 指令获取数组长度,且数组长度是不变量。如果发生上述条件之一,那么该指令是循环不变量
        if (cur->as_Constant() != NULL) {
          cur_invariant = !cur->can_trap();
        } else if (cur->as_ArithmeticOp() != NULL || cur->as_LogicOp() != NULL || cur->as_ShiftOp() != NULL) {
          Op2* op2 = (Op2*)cur;
          cur_invariant = ...;
        } else if (cur->as_LoadField() != NULL) {
          cur_invariant = ...;
        } else if (cur->as_ArrayLength() != NULL) {
          ArrayLength *length = cur->as_ArrayLength();
          cur_invariant = is_invariant(length->array());
        } else if (cur->as_LoadIndexed() != NULL) {
          LoadIndexed *li = (LoadIndexed *)cur->as_LoadIndexed();
          cur_invariant = ...;
        }
        // 如果该指令是循环不变量
        if (cur_invariant) {
          ...
          // 将该指令从循环内部移动到循环前面
          Instruction* next = cur->next();
          Instruction* in = _insertion_point->next();
          _insertion_point = _insertion_point->set_next(cur);
          cur->set_next(in);
          ...
        } else {
          prev = cur;
          cur = cur->next();
        }
      }
    }
    

    LCM遍历构成循环的所有基本块,然后遍历基本块的每一条指令,当发现满足要求的循环不变量时,将循环不变量从循环基本块中移除,然后添加到insertion_point所在的基本块,insertion_point即支配循环头的基本块,具体到例子中,如下Java代码:

    public static void loopInvariant(){
     class LoopInvariantMotion {
        private static int[] arr = new int[]{1,2,3,4};
        public static void loopInvariant(){
            int s = 0;
            for(int i=0;i<10;i++){
                s += arr.length;  // 循环不变量arr.length
                s += arr[2];       // 循环不变量arr[2]
            }
        }
    }
    

    它对应的HIR如下图所示,其中B1和B2构成for循环,B0基本块支配B1基本块:

    当发现循环基本块B2中的两个不变量后,C1会将它移到循环外面的B0基本块,该基本块支配循环头基本块B1,如下图所示:

  • 相关阅读:
    项目常见异常
    mysql 存储过程中使用事物+事件定时执行存储过程
    Spring Mvc 配置 之 ContextLoaderListener
    Spring Boot 之 https
    Spring Boot 之 annotation注解
    用python打印99乘法口诀表
    gerrit代码审核工具之“error unpack failed error Missing unknown”错误解决思路
    在eclipse搭建python开发环境
    python2与python3语法区别之_重定向
    2_jenkins_git创建创建及项目构建
  • 原文地址:https://www.cnblogs.com/kelthuzadx/p/12340658.html
Copyright © 2011-2022 走看看