박종훈 기술블로그

JDK-8377309 기여기: Min/Max GVN 검증 예외 제거

JDK-8377309에 기여해보기로 했다.

이슈의 제목은 다음과 같다.

Remove PhaseIterGVN::verify_Identity_for exclusion for Min/Max find identity op

이슈 내용

이슈 본문은 다음과 같다.

With JDK-8373134 fixed, and JDK-8374896 shortly to be fixed, the following section in PhaseIterGVN::verify_Identity_for can now be removed:

    // MaxNode::find_identity_operation
    // Finds patterns like Max(A, Max(A, B)) -> Max(A, B)
    // This can be a 2-hop search, so maybe notification is not
    // good enough.
    //
    // Found with:
    // compiler/codegen/TestBooleanVect.java
    // -XX:VerifyIterativeGVN=1110
    case Op_MaxL:
    case Op_MinL:
    case Op_MaxI:
    case Op_MinI:
    case Op_MaxF:
    case Op_MinF:
    case Op_MaxHF:
    case Op_MinHF:
    case Op_MaxD:
    case Op_MinD:
      return;

To be specific, the fix in JDK-8373134 already made compiler/codegen/TestBooleanVect.java with verify iterative gvn pass, but it was decided to leave removing this section out of the original PR due to JDK-8374896 (see comment).

So, once JDK-8374896 is fixed, removing this section can go ahead.


해야 할 것 자체는 간단하다. 위에 언급된 코드를 제거하면 된다. 하지만 내가 하는 작업이 무엇인지 이해하고 싶었기에 관련 지식을 공부하고 아래의 글들을 작성해 보았다.

선행 이슈 분석

이슈 본문에서 JDK-8373134와 JDK-8374896을 언급하고 있다. 이 두 이슈에서 어떤 작업을 했길래 위 코드를 삭제해도 되는 것인지 이해하는 것이 이번 글의 핵심이다.

JDK-8373134: Min/Max 부모 노드를 GVN worklist에 추가

  • 이슈: C2: Min/Max users of Min/Max uses should be enqueued for GVN
  • PR: openjdk/jdk#28895

제목을 조금 더 풀어보자면 다음과 같다. “Min/Max 노드를 입력으로 사용하는 부모 노드가 똑같이 Min/Max 노드라면, 이를 GVN 대기열에 추가한다.”

Max(A, Max(A, B)) → Max(A, B) 같은 패턴을 찾으려면 2-hop 탐색이 필요한데, 기존에는 Min/Max 노드가 변경되었을 때 그 부모 노드가 GVN worklist에 추가되지 않아 최적화 기회를 놓치고 있었다. 이 이슈에서 해당 문제를 수정했다.

JDK-8374896: int/long 타입의 Min/Max identity 최적화 누락 수정

  • 이슈: Min/Max identity optimization opportunities missing for int and long
  • PR: openjdk/jdk#29518

기존에는 조건을 OP 비교로 처리하고 있어서 일부 타입의 Min/Max 노드만 worklist에 추가되고 있었다. is_MinMax()로 변경하여 모든 타입(int, long, float, double, Float16)의 Min/Max 노드를 worklist에 추가하도록 수정했다.

참고로 Float16(HF, Half Float)은 Java 24에 도입되었다. Float은 32 bit인 반면 Float16은 그 절반인 16 bit을 사용한다.

최적화 예시

이 개선 사항들을 통해 아래와 같은 최적화가 가능해졌다고 한다.

// 최적화 전: max 연산 2회
int result = Math.max(a, Math.max(a, b));

// 최적화 후: max 연산 1회
int result = Math.max(a, b);
// 최적화 전: min + max 연산 2회
int result = Math.max(a, Math.min(a, b));

// 최적화 후: 연산 0회
int result = a;

JDK-8377309의 작업 내용

그동안에는 Min/Max 케이스가 worklist에 추가되지 않았기 때문에 VerifyIterativeGVN의 검증을 통과하지 못했고, 그래서 임시로 예외 처리해 둔 상태였다.

위의 두 선행 이슈에서 이 문제가 해결되었기 때문에, 예외 처리를 제거하는 작업이 Jira 이슈로 등록된 것이다. JDK-8377309에서는 이 예외 처리 코드를 제거하여, Min/Max 노드도 다른 노드들과 동일하게 GVN 검증 대상에 포함되도록 한다.

변경사항 검증

이슈에 언급된 두 가지 테스트와 Tier 1-3 테스트를 진행하였다.

make test CONF=macosx-aarch64-server-fastdebug \
     TEST=compiler/codegen/TestBooleanVect.java \
     JTREG="JAVA_OPTIONS=-XX:VerifyIterativeGVN=1110"
make test CONF=macosx-aarch64-server-fastdebug \
     TEST=compiler/igvn/TestMinMaxIdentity.java \
     JTREG="JAVA_OPTIONS=-XX:VerifyIterativeGVN=1110"
make test-tier1
make test-tier2
make test-tier3

마무리

선행된 PR에서도 코드 변경사항 자체는 크지 않았다. 하지만, 컴파일러 지식을 알아야 한다는 것이 작업의 난이도를 높게 만든 것 같다. 학부 시절에 컴파일러 수업을 듣지 않은 게 아쉬워지는 작업이었다. 오픈소스 기여를 하면서 이런 부분들을 공부할 수 있어서 좋았다. 앞으로 기회가 된다면 컴파일러에 대해서 공부해봐야겠다는 생각이 들었다.

categories: 개발

tags: JDK , OpenJDK , GVN , 컴파일러 , 오픈소스 기여