ninja. I now also tried ninja clang, but that didn’t make it better, the wall time is +155%:
| main | main+CIR | increase | main | main+CIR | increase | |
|---|---|---|---|---|---|---|
ninja |
ninja |
ninja clang |
ninja clang |
|||
| CMake wall time | 22.01 | 33.26 | +51.1% | |||
| Build CPU time | 8004.51 | 19010.74 | +137.5% | 6946.63 | 15945.48 | +129.5% |
| Build wall time | 113.20 | 262.03 | +131.5% | 95.71 | 243.70 | +154.6% |
| max-rss | 948304k | 2935520k | +209.6% | 948860k | 2939264k | +209.8% |
| build dir size | 2.0G | 4.0G | +100.4% | 1.5G | 3.0G | +98.8% |
| Build edges | (lost) | 7377 | 3750 | 6059 | +61.6% |
CC=clang CXX=clang++ /usr/bin/time cmake -DLLVM_ENABLE_PROJECTS="llvm;clang" -DLLVM_TARGETS_TO_BUILD="X86" -DCMAKE_BUILD_TYPE=Release -G Ninja -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_LINK_LLVM_DYLIB=ON -DLLVM_USE_LINKER=lld -B llvm-build-tmp32 -S llvm-project/llvm && /usr/bin/time ninja -C llvm-build-tmp32 clang
CC=clang CXX=clang++ /usr/bin/time cmake -DLLVM_ENABLE_PROJECTS="llvm;clang;mlir" -DLLVM_TARGETS_TO_BUILD="X86" -DCMAKE_BUILD_TYPE=Release -G Ninja -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_LINK_LLVM_DYLIB=ON -DLLVM_USE_LINKER=lld -B llvm-build-tmp33 -S llvm-project/llvm -DCLANG_ENABLE_CIR=ON && /usr/bin/time ninja -C llvm-build-tmp33 clang
NB: building fewer things is great for CPU time, but on my 48c/96t machine I noticed the the wall-time dominating part seems to come from really slow CUs, e.g. CIR/CIRDialect.cpp.o 68s, LLVMIR/LLVMDialect.cpp.o 121s, LLVMIR/NVVMDialect.cpp.o 108s, LLVMIR/ROCDLDialect.cpp.o 134s, and it seems that at least some of these files are required. Optimization should also reduce the latency of these files.
stage2-O0-g +0.17%, stage2-O3 +0.05%, actually, just from building with ClangIR.
I also wanted to get stats (time, page-faults, etc.) on the time it takes to compile a simple C program, but the Clang-with-ClangIR crashed in the dylib build…
$ echo 'int main(){return 0;}' > hello.c && ./llvm-build-tmp33/bin/clang -c hello.c
Attribute list does not match Module context!
AttributeList[
{ function => noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
]
ptr @main
fatal error: error in backend: Broken module found, compilation aborted!
clang: error: clang frontend command failed with exit code 70 (use -v to see invocation)
clang version 24.0.0git (https://github.com/llvm/llvm-project.git f4ad12c3e4371874aaf40078785fb3d00a664aa0)
...
$ echo '' > empty.c && ./llvm-build-tmp33/bin/clang -c empty.c
Pass 'Pre-ISel Intrinsic Lowering' is not initialized.
Verify if there is a pass dependency cycle.
Required Passes:
Target Transform Information
Target Library Information
clang: /home/engelke/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:706: void llvm::PMTopLevelManager::schedulePass(Pass *): Assertion `PI && "Expected required passes to be initialized"' failed.
clang: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 24.0.0git (https://github.com/llvm/llvm-project.git f4ad12c3e4371874aaf40078785fb3d00a664aa0)
This did succeed, though: echo '' > empty.c && ./llvm-build-tmp33/bin/clang -emit-llvm -c empty.c -o /dev/null, so we have:
hyperfine -L n 32,33 './llvm-build-tmp{n}/bin/clang -emit-llvm -c empty.c -o /dev/null'
Benchmark 1: ./llvm-build-tmp32/bin/clang -emit-llvm -c empty.c -o /dev/null
Time (mean ± σ): 15.4 ms ± 1.2 ms [User: 5.3 ms, System: 10.0 ms]
Range (min … max): 13.4 ms … 17.7 ms 180 runs
Benchmark 2: ./llvm-build-tmp33/bin/clang -emit-llvm -c empty.c -o /dev/null
Time (mean ± σ): 26.4 ms ± 1.8 ms [User: 12.9 ms, System: 13.5 ms]
Range (min … max): 23.3 ms … 29.0 ms 108 runs
Summary
./llvm-build-tmp32/bin/clang -emit-llvm -c empty.c -o /dev/null ran
1.72 ± 0.18 times faster than ./llvm-build-tmp33/bin/clang -emit-llvm -c empty.c -o /dev/null
Other stats: page-faults 2,400 → 3,394 (+41%), instructions 38,271,658 → 72,081,509 (+88%), max-rss 77208k → 112812k (+46%). There are some dylib-only costs in here, but most distros build Clang/LLVM as dylibs, so that’s what most users will get. So there’s certainly a significant cost that comes from just shipping Clang-with-ClangIR for all users (even if this experiment is synthetic and amplifies the increase).
… but also a lot less general.
I’d rather say: this is the sales-pitch of any well-designed IR. I consider MLIR to be a not-particularly-good implementation of that idea and this thread shows some of MLIR’s key downsides. Maybe ClangIR would’ve been better off from not using MLIR – but let’s not derail this thread into “should ClangIR use MLIR”, philosophical-ideological discussions tend to lead nowhere.
