진짜 ALU
정수 폭이 정해지고, SHA-256 probe가 위장하던 bitwise 연산자가 드디어 존재할 수 있게 되었다. 여섯 개의 builtin —— and, or, xor, not, 왼쪽 시프트, 산술 오른쪽 시프트 —— 가 4 backend 전부에서 기계 명령으로 일제히 떨어진다. 해시의 위장 산술 ALU에 갈아 끼우니, 1 block이 29밀리초에서 7마이크로초 미만으로, 약 4000배 빨라졌다. 흥미로운 것은 다시 쓰기가 드러낸 잔해다: 잘못된 폭 그대로 남은 임시 변수, 두 backend가 emit을 잊은 helper, 그리고 앞 이야기 자신의 changelog에 있던 틀린 한 줄.
앞 이야기는 정수의 폭을 정했다. 이 이야기는 그 기초 다지기를, SHA-256 probe가 정말로 원하던 기능에 쓰고, 그것을 더함으로써 보이게 된 어질러짐을 치운다 —— 그쪽이 이야기의 정직한 절반이다.
여섯 개의 builtin, 각각 하나의 기계 명령
bitwise 산술은 잔꾀가 나설 자리가 아니다. 언어는 여섯 개의 builtin을 얻었다 —— AND, OR, XOR,
NOT, 왼쪽 시프트, 산술(부호 전파) 오른쪽 시프트 —— 그리고 각각이 기계 자신의 명령으로 딱
떨어진다: C의 & 일가 연산자, wasm의 i32.and 일가 명령, LLVM의 and i32 일가, interpreter의
native land 일가. infix 연산자가 아니라 함수로 한 것은, 몇 이야기 전 Unicode 작업과 같은
본능이다: 능력을 우선 날 builtin으로 더하고, 연산자 구문을 주장하는 것은 추측이 아니라 진짜
pain에 나중에 맡긴다. 표준 라이브러리의 prelude는 어느 backend에서나 돌아야 하므로, 여섯은 같은
릴리스에서 구성상 4 backend에 착지했다. 3 backend가 갖고 하나가 안 갖는 창은 한 번도 없었다.
payoff는 SHA-256 example이었다. 그 inner loop은 모든 AND와 XOR를 32 반복의 나눗셈과 나머지 루프로 위장하고 있었다 —— 옳고, 흉하게 느리다. 진짜 연산자로 갈아 끼우니, 1 compression block이 interpreter에서 약 29밀리초에서 native 6.7마이크로초로 —— 대략 4000배 빠르게 —— NIST test vector를 전부 통과한 채. 위장은 알고리즘을 증명하는 좋은 방법이었다. 돌리기에는 최악의 방법이었다.
다시 쓰기가 빛 속으로 끌어낸 것
깨끗한 기능이라면 짧은 이야기가 된다. 이 이야기가 길이를 버는 것은, 다시 쓰기가 우연히 드러낸
무관한 세 가지에서다. 첫째: abs, min, max, clamp가 내부 임시 변수를 아직 옛 32-bit C
타입으로 선언하고 있었다. 정수 이행이 backend의 나머지를 쓸어냈을 때 남겨진 것이다 —— 그래서
20억 초과 값의 min이 말없이 truncate했다. 앞 이야기와 똑같은 버그가, 아무도 재확인하려 하지
않은 helper에 숨어 있었다. 둘째: 정수를 변수 경유로 문자열로 변환하면, top-level 바인딩 아래
에서는 show builtin만 등록하던 helper 함수를 참조했다 —— 그래서 emit된 모듈은 정의되지 않는
함수를 지목했다. wasm 과 LLVM 두 backend 모두에서, probe의 소박한 print (str_of_int x)가
드디어 방아쇠를 당긴 잠재 크래시다. 셋째, 그리고 가장 겸허하게 하는 것: 앞 이야기의 changelog는
LLVM backend의 정수가 이미 64-bit라고 주장했다. 재보니 달랐다 —— LLVM의 int는 wasm과 같은
32-bit다. 주장은 그 자리에서 정정되고, LLVM도 wasm과 같은 범위 밖 리터럴 compile 에러를 얻었고,
64-bit화는 SHA-256 example을 상설 forcing program으로 하여 deferred 목록에 올랐다. 교훈은 이
Part가 계속 가르치는 것이다: 기능은 작고 밝은 것이며, 그것이 드리우는 그림자야말로 실제 일의
소재지다. 다음 이야기는 bytes의 이야기로 돌아간다 —— 파일 안의 수가 아니라, 파일의 바이트가
애초에 프로그램에 들어갈 수 있는가의 이야기다.