---
title: "분기 목적지 예측: taken을 맞혔는데 다음 명령은 틀렸다"
author: "브레이브브라우저쓰자"
published_at: "2026-10-13T10:55:02.289Z"
updated_at: "2026-10-06T00:26:03.326Z"
tags: ["분기 목적지 예측"]
canonical_url: "https://ariser.io/@writer_a9817d5a8de0/%EB%B6%84%EA%B8%B0-%EB%AA%A9%EC%A0%81%EC%A7%80-%EC%98%88%EC%B8%A1-taken%EC%9D%84-%EB%A7%9E%ED%98%94%EB%8A%94%EB%8D%B0-%EB%8B%A4%EC%9D%8C-%EB%AA%85%EB%A0%B9%EC%9D%80-%ED%8B%80%EB%A0%B8%EB%8B%A4"
ai_assisted: true
---

# 분기 목적지 예측: taken을 맞혔는데 다음 명령은 틀렸다

이 글은 AI가 활용됐습니다.

[원문](https://ariser.io/@writer_a9817d5a8de0/%EB%B6%84%EA%B8%B0-%EB%AA%A9%EC%A0%81%EC%A7%80-%EC%98%88%EC%B8%A1-taken%EC%9D%84-%EB%A7%9E%ED%98%94%EB%8A%94%EB%8D%B0-%EB%8B%A4%EC%9D%8C-%EB%AA%85%EB%A0%B9%EC%9D%80-%ED%8B%80%EB%A0%B8%EB%8B%A4)

분기가 실행될 것이라는 예측은 100% 맞았다. 그런데 CPU는 여전히 잘못된 명령을 가져오고 복구한다. taken이면 어디로 갈지까지 맞아야 다음 PC가 맞기 때문이다. 분기 목적지 예측은 방향 예측의 부록처럼 보이지만, 프런트엔드가 쉬지 않고 명령을 가져오는 데 독립적인 역할을 한다.

분기를 예측한다는 말을 풀면 적어도 세 가지 정보가 들어 있다. 가져오는 명령 중 어느 것이 제어 흐름을 바꾸는지, 그것을 따라갈지, 따라간다면 어느 주소로 갈지다. 이 정보들이 준비되는 시점이 서로 다르면 한 항목의 높은 정확도가 전체 흐름의 정확도를 보장하지 못한다.

## 명령에 목적지가 써 있어도 일찍 보이지 않을 수 있다

RISC-V의 조건 분기는 명령에 들어 있는 상대 offset을 현재 분기의 PC에 더하여 목적지를 구한다. 명령 비트를 읽고 해독했다면 주소 계산 자체는 비교적 명확하다. 하지만 프런트엔드는 그 비트들이 명령 캐시에서 돌아오기 전에 다음 fetch를 시작하고 싶다. 목적지가 명령에 있다는 사실과 지금 목적지를 알고 있다는 사실은 다르다.

무조건 직접 점프인 JAL도 PC와 명령의 offset으로 주소를 만든다. 반면 JALR는 레지스터 rs1의 값에 signed immediate를 더하고 결과의 최하위 비트를 0으로 만든다. 이때 목적지 계산에 현재 PC를 더하지 않는다. 명령이 같은 PC에 있더라도 레지스터 값이 바뀌면 목적지가 바뀔 수 있다. [RISC-V RV32I 원문, Control Transfer Instructions](https://github.com/riscv/riscv-isa-manual/blob/main/src/unpriv/rv32.adoc)

가상의 JALR가 rs1=0x2000, immediate=12이면 목적지는 0x200C다. 같은 명령에서 rs1이 0x3000으로 바뀌면 0x300C다. 무조건 점프이므로 taken 자체는 의문이 없지만, PC마다 이전 목적지 하나만 기억하는 방식은 변화한 값을 맞히지 못할 수 있다. 함수 포인터처럼 목적지가 여러 개 있는 간접 점프가 방향만으로 해결되지 않는 이유다.

## 이전 주소는 계산을 대신하는 추측이다

목적지를 미리 제공하는 대표 구조가 BTB다. 분기나 점프의 주소를 식별하고 이전에 관측한 목적지를 저장한다. 기록이 현재 실행에도 유효하다고 추측하여 그 주소부터 명령을 가져온다. 실제 명령의 주소 계산을 없애는 것이 아니라, 주소가 확정될 때까지 기다리는 시간을 줄이려는 방식이다.

BOOM의 NLP는 BTB, 방향을 판단하는 표, return용 구조를 함께 사용한다. 문서는 무조건 점프에는 조건 분기의 방향 표를 조회하지 않고, return의 목적지는 return 주소 구조에서 받을 수 있다고 설명한다. 또한 BPD는 조건 분기의 taken/not-taken을 제공하며 목적지 정보는 다른 구조나 명령 해독에 의존한다. [BOOM NLP Predictions](https://docs.boom-core.org/en/latest/sections/branch-prediction/nl-predictor.html), [BOOM BPD Making Predictions 및 Jump Instructions](https://docs.boom-core.org/en/latest/sections/branch-prediction/backing-predictor.html)

이처럼 방향과 주소를 분리하면 서로 다른 정보를 각 구조에 담을 수 있다. 조건 분기의 방향은 입력 데이터나 과거 분기 패턴에 의존하지만, 직접 분기의 목적지는 같은 명령이면 대체로 변하지 않는다. 간접 점프는 반대로 방향 판단이 간단해도 목적지가 실행 문맥에 따라 바뀐다. 서로 다른 실패 원인을 하나의 정확도 숫자로 뭉치면 어디를 개선할지 찾기 어렵다.

## 96%가 90%가 되는 작은 집계

가상의 조건 분기 100회를 보자. 실제 taken이 50회, not-taken이 50회다. 방향 예측은 각 그룹에서 48회씩 맞아 총 96회가 맞았다. 그중 올바르게 taken을 예측한 48회에서는 목적지까지 맞은 것이 42회라고 하자.

그러면 올바른 다음 PC는 not-taken 쪽의 48회와 taken 쪽의 42회를 합한 90회다. 방향 정확도 96%와 올바른 taken에 대한 목적지 정확도 42/48=87.5%가 함께 있어도 전체 다음 PC 정확도는 90%다. 여기서는 분기 식별, not-taken의 다음 명령 주소, 다른 제어 흐름 문제는 모두 정상이라고 가정했다. 두 정확도를 무조건 곱하는 계산도 이 구분을 대신하지 못한다.

실제 측정에서는 BTB miss, 잘못된 목적지 hit, 방향 오예측, 한 fetch 묶음에서 다른 분기를 선택한 오류를 구분하는 것이 유용하다. 목적지를 아직 몰라 늦게 redirect한 상황과 잘못된 목적지를 적극적으로 선택한 상황도 비용이 다를 수 있다. 최종 주소는 같아도 프런트엔드가 그 주소에 도달한 시점이 다르기 때문이다.

목적지 예측을 크게 만든다고 모든 문제가 사라지는 것도 아니다. 더 많은 주소와 문맥을 보관하면 저장 공간과 조회 비용이 늘고, 복잡한 판단이 늦게 도착할 수 있다. 빠르지만 작은 구조와 늦지만 정보가 많은 구조 사이에서 어디에 추측을 맡길지 정해야 한다.

taken을 안다는 것은 갈림길에서 꺾을지 안다는 뜻이다. 올바른 명령을 계속 가져오려면 어느 갈림길인지와 꺾은 뒤의 주소도 제때 알아야 한다. 분기 목적지 예측을 별도로 평가하면 높은 방향 정확도 뒤에 남아 있던 프런트엔드의 실패를 볼 수 있다.

