본문으로 이동

불필요한 코드 제거

위키백과, 우리 모두의 백과사전.

컴파일러 이론에서 불필요한 코드 제거(Dead-code elimination, DCE, dead-code removal, dead-code stripping, 또는 dead-code strip)는 불필요한 코드(프로그램 결과에 영향을 미치지 않는 코드)를 제거하는 컴파일러 최적화이다. 이러한 코드를 제거하면 몇 가지 이점이 있다. 프로그램 크기를 줄여 일부 상황에서 중요한 고려 사항이 되고[1] 전송할 바이트 수와 같은 리소스 사용량을 줄이며 실행 중인 프로그램이 관련 없는 연산을 실행하는 것을 피하게 하여 실행 시간을 단축한다. 또한 프로그램 구조를 단순화하여 추가 최적화를 가능하게 한다. 불필요한 코드에는 절대로 실행될 수 없는 코드(도달 불가능한 코드)와 불필요한 변수(쓰여졌지만 다시는 읽히지 않는 변수)에만 영향을 미치는, 즉 프로그램과 무관한 코드가 포함된다.

예시

[편집]

다음은 C로 작성된 예시이다.

int foo(void) {
  int a = 24;
  int b = 25; /* Assignment to dead variable */
  int c;
  c = a * 4;
  return c;
  b = 24; /* Unreachable code */
  return 0;
}

값 사용에 대한 간단한 분석은 첫 번째 할당 후 b의 값이 foo 내부에서 사용되지 않음을 보여준다. 게다가 bfoo 내부에 지역 변수로 선언되었으므로 foo 외부에서는 그 값을 사용할 수 없다. 따라서 변수 b는 불필요하며 최적화 프로그램은 해당 저장 공간을 회수하고 초기화를 제거할 수 있다.

또한 첫 번째 return 문이 무조건 실행되고 그 뒤에 "goto"가 도달할 수 있는 레이블이 없으므로, 두 번째 b에 대한 할당에 도달하는 실행 경로는 존재하지 않는다. 따라서 해당 할당은 도달 불가능하며 제거될 수 있다. 만약 해당 프로시저에 return 문 뒤에 레이블이 있고 프로시저의 다른 곳에 goto와 같은 더 복잡한 제어 흐름이 있었다면, b에 대한 할당에 도달할 수 있는 실행 경로가 존재했을 수도 있다.

또한 함수 내에서 일부 계산이 수행되더라도 그 값은 이 함수 스코프 외부에서 접근 가능한 위치에 저장되지 않는다. 게다가 함수가 정적 값(96)을 반환한다는 점을 고려할 때, 반환하는 값으로 단순화될 수 있다 (이 단순화는 상수 폴딩이라고 한다).

대부분의 고급 컴파일러는 불필요한 코드 제거를 활성화하는 옵션을 제공하며, 때로는 다양한 수준으로 제공한다. 낮은 수준은 실행될 수 없는 명령어만 제거할 수 있다. 높은 수준은 사용되지 않는 변수에 대한 공간도 예약하지 않을 수 있다. 더 높은 수준은 목적 없는 명령어 또는 함수를 판별하고 제거할 수 있다.

불필요한 코드 제거의 일반적인 사용 사례는 전처리기를 통한 선택적 코드 포함의 대안이다. 다음 코드를 고려해 보자.

int main(void) {
  int a = 5;
  int b = 6;
  int c;
  c = a * (b / 2);
  if (0) {   /* DEBUG */
    printf("%d\n", c);
  }
  return c;
}

표현식 0은 항상 거짓으로 평가되므로 if 문 내부의 코드는 절대로 실행될 수 없으며, 불필요한 코드 제거는 최적화된 프로그램에서 이를 완전히 제거한다. 이 기술은 디버그에서 선택적으로 코드 블록을 활성화하는 데 흔히 사용된다. 불필요한 코드 제거가 있는 최적화 프로그램을 사용하면 동일한 작업을 수행하기 위해 전처리기를 사용할 필요가 없어진다.

실제로 최적화 프로그램이 발견하는 불필요한 코드의 대부분은 최적화 프로그램의 다른 변환에 의해 생성된다. 예를 들어, 연산자 강도 감소의 고전적인 기술은 코드에 새로운 계산을 삽입하고 이전의 더 비싼 계산을 불필요하게 만든다.[2] 이어진 불필요한 코드 제거는 이러한 계산을 제거하고 효과를 완료한다 (강도 감소 알고리즘을 복잡하게 하지 않고).

역사적으로 불필요한 코드 제거는 데이터 흐름 분석에서 파생된 정보를 사용하여 수행되었다.[3] 정적 단일 대입 형식(SSA)에 기반한 알고리즘은 론 사이트론(Ron Cytron) 등이 쓴 SSA 형식에 대한 원본 학술 논문에 나타난다.[4] 로버트 실링스버그(Robert Shillingsburg, aka Shillner)는 이 알고리즘을 개선하고 쓸모없는 제어 흐름 연산을 제거하기 위한 동반 알고리즘을 개발했다.[5]

동적으로 불필요한 코드 제거

[편집]

불필요한 코드는 일반적으로 무조건 불필요한 것으로 간주된다. 따라서 컴파일 타임에 불필요한 코드 제거를 통해 불필요한 코드를 제거하는 것이 합리적이다.

그러나 실제로 특정 조건에서만 불필요하거나 도달 불가능한 코드 섹션이 되는 경우가 흔하며, 이는 컴파일 또는 어셈블리 시점에는 알려지지 않을 수 있다. 이러한 조건은 다양한 런타임 환경(예: 운영 체제의 다른 버전, 특정 대상 환경에 로드된 드라이버 또는 서비스의 다른 세트 및 조합)에 의해 부과될 수 있으며, 이는 코드에 다른 특수 사례 세트를 요구하지만 동시에 다른 경우에 대해 조건부 불필요한 코드가 될 수 있다.[6][7] 또한 소프트웨어(예: 드라이버 또는 상주 서비스)는 사용자 기본 설정에 따라 특정 기능을 포함하거나 제외하도록 구성될 수 있어 특정 시나리오에서 사용되지 않는 코드 부분이 쓸모없게 될 수 있다.[6][7] 모듈형 소프트웨어는 필요에 따라 동적으로 라이브러리를 로드하도록 개발될 수 있지만, 대부분의 경우 특정 라이브러리에서 관련 루틴만 로드하는 것은 불가능하며, 설령 이것이 지원되더라도 루틴에는 주어진 시나리오에서 불필요한 코드로 간주될 수 있지만 컴파일 타임에는 제외될 수 없었던 코드 섹션이 포함될 수 있다.

수요를 동적으로 감지하고, 종속성을 식별 및 해결하며, 이러한 조건부 불필요한 코드를 제거하고, 로드 또는 런타임에 나머지 코드를 재결합하는 데 사용되는 기술을 동적 불필요한 코드 제거[8][9][10] 또는 동적 불필요한 명령어 제거[11]라고 한다.

대부분의 프로그래밍 언어, 컴파일러 및 운영 체제는 동적 적재 라이브러리 및 늦은 연결 외에는 거의 또는 전혀 지원을 제공하지 않으므로 선행 컴파일된 언어로 작성되거나 어셈블리어로 작성된 언어와 함께 동적 불필요한 코드 제거를 활용하는 소프트웨어는 매우 드물다.[12][13][14] 그러나 Just-in-time 컴파일을 수행하는 언어 구현은 동적으로 불필요한 코드 제거를 위해 최적화할 수 있다.[10][15][16]

비록 초점은 다소 다르지만, 유사한 접근 방식은 때때로 동적 소프트웨어 업데이트핫 패치에도 활용된다.

같이 보기

[편집]

각주

[편집]
  1. Malavolta, Ivano et al. “JavaScript Dead Code Identification, Elimination, and Empirical Assessment.” IEEE transactions on software engineering 49.7 (2023): 3692–3714. Web.
  2. Allen, Frances; Cocke, John; Kennedy, Ken (June 1981). 〈Reduction of Operator Strength〉. Jones, Neil D.; Muchnick, Steven Stanley (편집). 《Program Flow Analysis: Theory & Application》. 프렌티스 홀. ISBN 0-13729681-9. 
  3. Kennedy, Ken (June 1981). 〈A Survey of Data-flow Analysis Techniques〉. Jones, Neil D.; Muchnick, Steven Stanley (편집). 《Program Flow Analysis: Theory & Application》. 프렌티스 홀. ISBN 0-13729681-9. 
  4. Cytron, Ron K.; Ferrante, Jeanne; Rosen, Barry K.; Zadeck, F. Kenneth (1991). 《Efficiently Computing Static Single Assignment Form and the Program Dependence Graph》. ACM TOPLAS 13(4). 
  5. Cooper, Keith D.; Torczon, Linda (2003) [2002-01-01]. 《Engineering a Compiler》. 모건 카우프만. 498ff쪽. ISBN 978-1-55860698-2. 
  6. Paul, Matthias R. (2002년 4월 3일) [2001-06-18]. “[fd-dev] Ctrl+Alt+Del”. 《freedos-dev》. 2017년 9월 9일에 원본 문서에서 보존된 문서. 2017년 9월 9일에 확인함. […] any of the […] options can be "permanently" excluded at installation time (will also save the memory for the corresponding code excerpts due to our Dynamic Dead Code Elimination), or it can be disabled or enabled at any later time via API functions in case someone wants to keep a user from being able to reboot the machine. […] we are considering to add more synchronous cache flush calls […] Due to our Dynamic Dead Code Elimination method this would not cause any kind of bloating when not needed in a particular target configuration as a particular cache flush call would be included in FreeKEYB's runtime image only if the corresponding disk cache is loaded as well or FreeKEYB was told by command line switches to load the corresponding support. 
  7. Paul, Matthias R. (2002년 4월 6일). “[fd-dev] Ctrl+Alt+Del”. 《freedos-dev》. 2019년 4월 27일에 원본 문서에서 보존된 문서. 2019년 4월 27일에 확인함. […] FreeKEYB builds the driver's runtime image at initialization time depending on the type of machine it is being loaded on, the type of keyboard, layout, country and code page used, the type of mouse and video adapter(s) installed, the other drivers loaded on that system, the operating system and the load and relocation method(s) used, the individual features included, and the configuration options specified in the command line. Due to the large number of command line switches and options supported […] (around fifty switches […] with multiple possible settings) there is a high number of feature combinations with uncountable dependencies […] resulting in […] endless number of […] different target images. FreeKEYB's Dynamic Dead Code Elimination technique manages to resolve […] these […] dependencies and […] remove dead code and data […] is not restricted to […] include or exclude a somewhat limited number of modules or whole sub-routines and fix up some dispatch tables as in classical TSR programming, but […] works […] at […] byte level […] able to remove […] individual instructions in the middle of larger routines […] distributed all over the code to handle a particular case or support a specific feature […] special tools are used to analyze the code […] and create […] fixup tables […] automated […] using conditional defines […] to declare the various cases […] not only optional at assembly time but at initialization time […] without the […] overhead of having at least some amount of dead code left in the runtime image […] to keep track of all the dependencies between […] these conditionals, dynamically build and relocate the runtime image, fix up all the references between these small, changing, and moving binary parts […] still allowing to use the tiny .COM/.SYS style […] model […] is done at initialization time […] API to import and export object structures between FreeKEYB and the calling application […] to transparently resize and move them internally […] at runtime […] 
  8. Thammanur, Sathyanarayan (2001년 1월 31일). 《A Just in Time Register Allocation and Code Optimization Framework for Embedded Systems》 (MS thesis). 신시내티 대학교, Engineering: Computer Engineering. ucin982089462.  [1] 보관됨 2019-07-28 - 웨이백 머신[2] 보관됨 2019-07-28 - 웨이백 머신
  9. Kubice, Jan (2024년 10월 17일). “Dynamic Dead Code Elimination: Optimizing for Flexibility”. 
  10. Conway, Andrew (1995년 12월 4일). “Cyclic data structures”. 뉴스그룹comp.lang.functional. 2017년 9월 9일에 원본 문서에서 보존된 문서. 2017년 7월 3일에 확인함. […] 느긋한 계산법은 기본적으로 동적 불필요한 코드 제거이다. […]  (NB. 함수형 언어의 느긋한 계산법에 초점을 맞추었지만, 동적 불필요한 코드 제거라는 용어의 첫 공개 사용으로 추정된다.)
  11. Butts, J. Adam; Sohi, Guri (October 2002). “Dynamic Dead-Instruction Detection and Elimination” (PDF). San Jose, CA, USA: 컴퓨터 과학과, 위스콘신-매디슨 대학교. ASPLOS X ACM 1-58113-574-2/02/0010. 2019년 4월 20일에 원본 문서 (PDF)에서 보존된 문서. 2017년 6월 23일에 확인함. 
  12. Paul, Matthias R.; Frinke, Axel C. (1997년 10월 13일) [first published 1991], 《FreeKEYB - Enhanced DOS keyboard and console driver》 v6.5판 (User Manual)  [3] (NB. FreeKEYB는 대부분의 자판 배열, 코드 페이지국가 코드를 지원하는 유니코드 기반 동적 구성 가능한 K3PLUS의 후속이다. 상용 매크로 어셈블러뿐만 아니라 종속성 및 코드 모핑 메타데이터를 생성하여 이진 코드와 함께 실행 파일에 내장하고, 자체 폐기, 완화재배치 로더를 통해 드라이버는 로드 시간에 바이트 수준의 세분화된 동적 불필요한 코드 제거재배치 기술뿐만 아니라 런타임자체 수정 코드 및 재구성 가능성을 구현하여 기본 하드웨어, 운영 체제 및 드라이버 구성뿐만 아니라 선택된 기능 세트 및 로케일(수백 가지 옵션을 가진 약 60개의 구성 스위치로 거의 무한한 수의 가능한 조합)에 따라 메모리 공간을 표준 형식에 가깝게 최소화한다. 이러한 복잡성과 동적 특성은 기존 드라이버와 마찬가지로 단일 실행 파일만 다루는 사용자에게는 숨겨져 있다. K3PLUS는 당시 독일에 널리 배포된 도스용 확장 키보드 드라이버였으며, 다른 몇몇 유럽 언어에 대한 적응도 가능했다. 이미 기능의 하위 집합을 지원했지만 동적 불필요한 코드 제거는 구현하지 않았다.)
  13. Paul, Matthias R.; Frinke, Axel C. (2006년 1월 16일), 《FreeKEYB - Advanced international DOS keyboard and console driver》 v7 preliminary판 (User Manual) 
  14. Paul, Matthias R. (2001년 4월 10일). “[ANN] FreeDOS beta 6 released” (독일어). 뉴스그룹de.comp.os.msdos. 2017년 9월 9일에 원본 문서에서 보존된 문서. 2017년 7월 2일에 확인함. […] brandneue[s] Feature, der dynamischen Dead-Code-Elimination, die die jeweils notwendigen Bestandteile des Treibers erst zum Installationszeitpunkt zusammenbastelt und reloziert, so daß keine ungenutzten Code- oder Datenbereiche mehr resident bleiben (z.B. wenn jemand ein bestimmtes FreeKEYB-Feature nicht benötigt). […]  (NB. 이 구현은 어셈블리어선행 컴파일된 소프트웨어에 대한 바이트 수준의 세분화된 동적 불필요한 코드 제거의 첫 번째 알려진 구현이다.)
  15. Johng, Yessong; Danielsson, Per; Ehnsiö, Per; Hermansson, Mats; Jolanki, Mika; Moore, Scott; Strander, Lars; Wettergren, Lars (2002년 11월 8일). 〈Chapter 5. Java overview and iSeries implementation - 5.1.1. Miscellaneous components〉. 《Intentia Movex Java on the IBM iSeries Server - An Implementation Guide - Overview of Movex Java on the iSeries server - Movex Java on iSeries installation and configuration - Operational tips and techniques》 (PDF). Red Books. IBM Corp. 41쪽. ISBN 0-73842461-7. SG24-6545-00. 2013년 10월 8일에 원본 문서 (PDF)에서 보존된 문서. 2019년 4월 20일에 확인함.  [4]
  16. Polito, Guillermo (2015). “Virtualization Support for Application Runtime Specialization and Extension - Programming Languages” (PDF). 릴 과학 기술 대학교. 111–124쪽. HAL Id: tel-01251173. 2017년 6월 23일에 원본 문서 (PDF)에서 보존된 문서. 2017년 6월 23일에 확인함. 

더 읽어보기

[편집]

외부 링크

[편집]