ruby-llvm 16.0.1 → 18.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,712 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LLVM
4
+ class PassBuilder # rubocop:disable Metrics/ClassLength
5
+ extend FFI::Library
6
+ ffi_lib ["libLLVM-18.so.1", "libLLVM.so.18", "LLVM-18"]
7
+
8
+ attr_reader :passes
9
+ attr_accessor :inliner_threshold, :merge_functions
10
+
11
+ # rubocop:disable Layout/LineLength
12
+ OPT_PASSES = {
13
+ '0' => 'always-inline,coro-cond(coro-early,cgscc(coro-split),coro-cleanup,globaldce),function(annotation-remarks),verify',
14
+ '1' => 'annotation2metadata,forceattrs,inferattrs,coro-early,function<eager-inv>(lower-expect,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,sroa<modify-cfg>,early-cse<>),openmp-opt,ipsccp,called-value-propagation,globalopt,function<eager-inv>(mem2reg,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>),always-inline,require<globals-aa>,function(invalidate<aa>),require<profile-summary>,cgscc(devirt<4>(inline,function-attrs<skip-non-recursive-function-attrs>,function<eager-inv;no-rerun>(sroa<modify-cfg>,early-cse<memssa>,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,libcalls-shrinkwrap,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,reassociate,loop-mssa(loop-instsimplify,loop-simplifycfg,licm<no-allowspeculation>,loop-rotate<header-duplication;no-prepare-for-lto>,licm<allowspeculation>,simple-loop-unswitch<no-nontrivial;trivial>),simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop(loop-idiom,indvars,loop-deletion,loop-unroll-full),sroa<modify-cfg>,memcpyopt,sccp,bdce,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,coro-elide,adce,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>),function-attrs,function(require<should-not-run-function-passes>),coro-split)),deadargelim,coro-cleanup,globalopt,globaldce,elim-avail-extern,rpo-function-attrs,recompute-globalsaa,function<eager-inv>(float2int,lower-constant-intrinsics,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,vector-combine,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-unroll<O1>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>),globaldce,constmerge,cg-profile,rel-lookup-table-converter,function(annotation-remarks),verify',
15
+ '2' => 'annotation2metadata,forceattrs,inferattrs,coro-early,function<eager-inv>(lower-expect,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,sroa<modify-cfg>,early-cse<>),openmp-opt,ipsccp,called-value-propagation,globalopt,function<eager-inv>(mem2reg,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>),always-inline,require<globals-aa>,function(invalidate<aa>),require<profile-summary>,cgscc(devirt<4>(inline,function-attrs<skip-non-recursive-function-attrs>,openmp-opt-cgscc,function<eager-inv;no-rerun>(sroa<modify-cfg>,early-cse<memssa>,speculative-execution<only-if-divergent-target>,jump-threading,correlated-propagation,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,aggressive-instcombine,libcalls-shrinkwrap,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm<no-allowspeculation>,loop-rotate<header-duplication;no-prepare-for-lto>,licm<allowspeculation>,simple-loop-unswitch<no-nontrivial;trivial>),simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop(loop-idiom,indvars,loop-deletion,loop-unroll-full),sroa<modify-cfg>,vector-combine,mldst-motion<no-split-footer-bb>,gvn<>,sccp,bdce,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm<allowspeculation>),coro-elide,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>),function-attrs,function(require<should-not-run-function-passes>),coro-split)),deadargelim,coro-cleanup,globalopt,globaldce,elim-avail-extern,rpo-function-attrs,recompute-globalsaa,function<eager-inv>(float2int,lower-constant-intrinsics,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-unroll<O2>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>),globaldce,constmerge,cg-profile,rel-lookup-table-converter,function(annotation-remarks),verify',
16
+ '3' => 'annotation2metadata,forceattrs,inferattrs,coro-early,function<eager-inv>(lower-expect,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,sroa<modify-cfg>,early-cse<>,callsite-splitting),openmp-opt,ipsccp,called-value-propagation,globalopt,function<eager-inv>(mem2reg,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>),always-inline,require<globals-aa>,function(invalidate<aa>),require<profile-summary>,cgscc(devirt<4>(inline,function-attrs<skip-non-recursive-function-attrs>,argpromotion,openmp-opt-cgscc,function<eager-inv;no-rerun>(sroa<modify-cfg>,early-cse<memssa>,speculative-execution<only-if-divergent-target>,jump-threading,correlated-propagation,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,aggressive-instcombine,libcalls-shrinkwrap,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm<no-allowspeculation>,loop-rotate<header-duplication;no-prepare-for-lto>,licm<allowspeculation>,simple-loop-unswitch<nontrivial;trivial>),simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop(loop-idiom,indvars,loop-deletion,loop-unroll-full),sroa<modify-cfg>,vector-combine,mldst-motion<no-split-footer-bb>,gvn<>,sccp,bdce,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm<allowspeculation>),coro-elide,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>),function-attrs,function(require<should-not-run-function-passes>),coro-split)),deadargelim,coro-cleanup,globalopt,globaldce,elim-avail-extern,rpo-function-attrs,recompute-globalsaa,function<eager-inv>(float2int,lower-constant-intrinsics,chr,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-unroll<O3>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>),globaldce,constmerge,cg-profile,rel-lookup-table-converter,function(annotation-remarks),verify',
17
+ 's' => 'annotation2metadata,forceattrs,inferattrs,coro-early,function<eager-inv>(lower-expect,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,sroa<modify-cfg>,early-cse<>),openmp-opt,ipsccp,called-value-propagation,globalopt,function<eager-inv>(mem2reg,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>),always-inline,require<globals-aa>,function(invalidate<aa>),require<profile-summary>,cgscc(devirt<4>(inline,function-attrs<skip-non-recursive-function-attrs>,function<eager-inv;no-rerun>(sroa<modify-cfg>,early-cse<memssa>,speculative-execution<only-if-divergent-target>,jump-threading,correlated-propagation,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,aggressive-instcombine,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm<no-allowspeculation>,loop-rotate<header-duplication;no-prepare-for-lto>,licm<allowspeculation>,simple-loop-unswitch<no-nontrivial;trivial>),simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop(loop-idiom,indvars,loop-deletion,loop-unroll-full),sroa<modify-cfg>,vector-combine,mldst-motion<no-split-footer-bb>,gvn<>,sccp,bdce,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm<allowspeculation>),coro-elide,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>),function-attrs,function(require<should-not-run-function-passes>),coro-split)),deadargelim,coro-cleanup,globalopt,globaldce,elim-avail-extern,rpo-function-attrs,recompute-globalsaa,function<eager-inv>(float2int,lower-constant-intrinsics,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-unroll<O2>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>),globaldce,constmerge,cg-profile,rel-lookup-table-converter,function(annotation-remarks),verify',
18
+ 'z' => 'annotation2metadata,forceattrs,inferattrs,coro-early,function<eager-inv>(lower-expect,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,sroa<modify-cfg>,early-cse<>),openmp-opt,ipsccp,called-value-propagation,globalopt,function<eager-inv>(mem2reg,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>),always-inline,require<globals-aa>,function(invalidate<aa>),require<profile-summary>,cgscc(devirt<4>(inline,function-attrs<skip-non-recursive-function-attrs>,function<eager-inv;no-rerun>(sroa<modify-cfg>,early-cse<memssa>,speculative-execution<only-if-divergent-target>,jump-threading,correlated-propagation,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,aggressive-instcombine,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm<no-allowspeculation>,loop-rotate<no-header-duplication;no-prepare-for-lto>,licm<allowspeculation>,simple-loop-unswitch<no-nontrivial;trivial>),simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop(loop-idiom,indvars,loop-deletion,loop-unroll-full),sroa<modify-cfg>,vector-combine,mldst-motion<no-split-footer-bb>,gvn<>,sccp,bdce,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm<allowspeculation>),coro-elide,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>),function-attrs,function(require<should-not-run-function-passes>),coro-split)),deadargelim,coro-cleanup,globalopt,globaldce,elim-avail-extern,rpo-function-attrs,recompute-globalsaa,function<eager-inv>(float2int,lower-constant-intrinsics,loop(loop-rotate<no-header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,vector-combine,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-unroll<O2>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-use-loop-info;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>),globaldce,constmerge,cg-profile,rel-lookup-table-converter,function(annotation-remarks),verify',
19
+ }.freeze
20
+ # rubocop:enable Layout/LineLength
21
+
22
+ def initialize
23
+ @passes = []
24
+ @inliner_threshold = nil
25
+ @merge_functions = nil
26
+ end
27
+
28
+ def add_function_pass
29
+ pb = PassBuilder.new
30
+ if block_given?
31
+ yield pb
32
+ end
33
+
34
+ add_pass("function(#{pb.pass_string})")
35
+ end
36
+
37
+ # --O0 - Optimization level 0. Similar to clang -O0. Use -passes='default<O0>' for the new PM
38
+ # --O1 - Optimization level 1. Similar to clang -O1. Use -passes='default<O1>' for the new PM
39
+ # --O2 - Optimization level 2. Similar to clang -O2. Use -passes='default<O2>' for the new PM
40
+ # --O3 - Optimization level 3. Similar to clang -O3. Use -passes='default<O3>' for the new PM
41
+ # --Os - Like -O2 but size-conscious. Similar to clang -Os. Use -passes='default<Os>' for the new PM
42
+ # --Oz - Like -O2 but optimize for code size above all else. Similar to clang -Oz. Use -passes='default<Oz>' for the new PM
43
+ # @return self
44
+ def o!(opt_level = '0', options = {})
45
+ opt_level = opt_level.to_s
46
+ expanded_pass = OPT_PASSES[opt_level]
47
+
48
+ if expanded_pass.nil?
49
+ return add_pass("default<O#{opt_level}>")
50
+ end
51
+
52
+ if options[:disable_inline]
53
+ expanded_pass = expanded_pass.gsub('devirt<4>(inline,', 'devirt<4>(')
54
+ end
55
+ if options[:disable_always_inline]
56
+ expanded_pass = expanded_pass.gsub('always-inline,', '')
57
+ end
58
+ add_pass(expanded_pass)
59
+ end
60
+
61
+ # @return self
62
+ def add_pass(pass)
63
+ passes << pass
64
+ self
65
+ end
66
+
67
+ # @return self
68
+ def dce!
69
+ add_pass('dce')
70
+ end
71
+
72
+ # @return self
73
+ def licm!
74
+ add_pass('licm')
75
+ end
76
+
77
+ # A pass to simplify and canonicalize the CFG of a function.
78
+ # This pass iteratively simplifies the entire CFG of a function. It may change
79
+ # or remove control flow to put the CFG into a canonical form expected by
80
+ # other passes of the mid-level optimizer. Depending on the specified options,
81
+ # it may further optimize control-flow to create non-canonical form
82
+ # https://llvm.org/doxygen/SimplifyCFG_8h_source.html
83
+ # TODO: takes params
84
+ # Options: simplifycfg<no-forward-switch-cond;forward-switch-cond;no-switch-range-to-icmp;switch-range-to-icmp;no-switch-to-lookup;switch-to-lookup;no-keep-loops;keep-loops;no-hoist-common-insts;hoist-common-insts;no-sink-common-insts;sink-common-insts;bonus-inst-threshold=N>
85
+ # @return self
86
+ def simplifycfg!
87
+ add_pass('simplifycfg')
88
+ end
89
+
90
+ # @return self
91
+ def scalarizer!
92
+ add_pass('scalarizer')
93
+ end
94
+
95
+ # Merged Load Store Motion
96
+ # @return self
97
+ def mldst_motion!
98
+ add_pass('mldst-motion')
99
+ end
100
+
101
+ # Global Value Numbering pass
102
+ # https://llvm.org/doxygen/GVN_8h_source.html
103
+ # TODO: takes params
104
+ # @return self
105
+ def gvn!
106
+ add_pass('gvn')
107
+ end
108
+
109
+ # New Global Value Numbering pass
110
+ # https://llvm.org/doxygen/NewGVN_8cpp.html#details
111
+ # @return self
112
+ def newgvn!
113
+ add_pass('newgvn')
114
+ end
115
+
116
+ # hoists expressions from branches to a common dominator.
117
+ # https://llvm.org/doxygen/GVNHoist_8cpp_source.html
118
+ # @return self
119
+ def gvn_hoist!
120
+ add_pass('gvn-hoist')
121
+ end
122
+
123
+ # sink instructions into successors
124
+ # https://llvm.org/doxygen/GVNSink_8cpp_source.html
125
+ # @return self
126
+ def gvn_sink!
127
+ add_pass('gvn-sink')
128
+ end
129
+
130
+ # @return self
131
+ def jump_threading!
132
+ add_pass('jump-threading')
133
+ end
134
+
135
+ # @return self
136
+ def indvars!
137
+ add_pass('indvars')
138
+ end
139
+
140
+ # @return self
141
+ def alignment_from_assumptions!
142
+ add_pass('alignment-from-assumptions')
143
+ end
144
+
145
+ # @return self
146
+ def loop_deletion!
147
+ add_pass('loop-deletion')
148
+ end
149
+
150
+ # @return self
151
+ def loop_idiom!
152
+ add_pass('loop-idiom')
153
+ end
154
+
155
+ # @return self
156
+ def loop_rotate!
157
+ add_pass('loop-rotate')
158
+ end
159
+
160
+ # @return self
161
+ def loop_reroll!
162
+ add_pass('loop-reroll')
163
+ end
164
+
165
+ # @return self
166
+ def loop_unroll!
167
+ add_pass('loop-unroll')
168
+ end
169
+
170
+ # @return self
171
+ def loop_unroll_and_jam!
172
+ add_pass('loop-unroll-and-jam')
173
+ end
174
+
175
+ # @return self
176
+ def simple_loop_unswitch!
177
+ add_pass('simple-loop-unswitch')
178
+ end
179
+
180
+ # @return self
181
+ def loop_unswitch!
182
+ simple_loop_unswitch!
183
+ end
184
+
185
+ # TODO: takes params
186
+ # @return self
187
+ def loop_vectorize!
188
+ add_pass('loop-vectorize')
189
+ end
190
+
191
+ # @return self
192
+ def memcpyopt!
193
+ add_pass('memcpyopt')
194
+ end
195
+
196
+ # @return self
197
+ def sccp!
198
+ add_pass('sccp')
199
+ end
200
+
201
+ # Combine instructions to form fewer, simple instructions.
202
+ # This pass does not modify the CFG.
203
+ # This pass is where algebraic simplification happens.
204
+ # https://llvm.org/doxygen/InstructionCombining_8cpp_source.html
205
+ # https://llvm.org/doxygen/InstCombineInternal_8h_source.html
206
+ # @return self
207
+ def instcombine!
208
+ add_pass('instcombine')
209
+ end
210
+
211
+ # @return self
212
+ def instsimplify!
213
+ add_pass('instsimplify')
214
+ end
215
+
216
+ # @return self
217
+ def loweratomic!
218
+ add_pass('loweratomic')
219
+ end
220
+
221
+ # @return self
222
+ def partially_inline_libcalls!
223
+ add_pass('partially-inline-libcalls')
224
+ end
225
+
226
+ # @return self
227
+ def reassociate!
228
+ add_pass('reassociate')
229
+ end
230
+
231
+ # @return self
232
+ def tailcallelim!
233
+ add_pass('tailcallelim')
234
+ end
235
+
236
+ # @return self
237
+ def reg2mem!
238
+ add_pass('reg2mem')
239
+ end
240
+
241
+ # @return self
242
+ def mem2reg!
243
+ add_pass('mem2reg')
244
+ end
245
+
246
+ # @return self
247
+ def verify!
248
+ add_pass('verify')
249
+ end
250
+
251
+ # @return self
252
+ def module_summary!
253
+ add_pass('require<module-summary>')
254
+ end
255
+
256
+ # @return self
257
+ def no_op_module!
258
+ add_pass('no-op-module')
259
+ end
260
+
261
+ # @return self
262
+ def no_op_cgscc!
263
+ add_pass('no-op-cgscc')
264
+ end
265
+
266
+ # @return self
267
+ def no_op_function!
268
+ add_pass('no-op-function')
269
+ end
270
+
271
+ # @return self
272
+ def stack_safety!
273
+ add_pass('require<stack-safety>')
274
+ end
275
+
276
+ # A simple and fast domtree-based CSE pass.
277
+ #
278
+ # This pass does a simple depth-first walk over the dominator tree,
279
+ # eliminating trivially redundant instructions and using instsimplify to
280
+ # canonicalize things as it goes. It is intended to be fast and catch obvious
281
+ # cases so that instcombine and other passes are more effective. It is
282
+ # expected that a later pass of GVN will catch the interesting/hard cases.
283
+ # https://llvm.org/doxygen/EarlyCSE_8h_source.html
284
+ # https://llvm.org/doxygen/EarlyCSE_8cpp.html
285
+ # @return self
286
+ def early_cse!
287
+ add_pass('early-cse')
288
+ end
289
+
290
+ # A simple and fast domtree-based CSE pass.
291
+ # https://llvm.org/doxygen/EarlyCSE_8h_source.html
292
+ # https://llvm.org/doxygen/EarlyCSE_8cpp.html
293
+ # @return self
294
+ def early_cse_memssa!
295
+ add_pass('early-cse<memssa>')
296
+ end
297
+
298
+ # @return self
299
+ def lcssa!
300
+ add_pass('lcssa')
301
+ end
302
+
303
+ # @return self
304
+ def memoryssa!
305
+ add_pass('require<memoryssa>')
306
+ end
307
+
308
+ # Scalar Replacement Of Aggregates
309
+ # https://llvm.org/doxygen/SROA_8h_source.html
310
+ # https://llvm.org/doxygen/SROA_8cpp.html
311
+ # @return self
312
+ def sroa!
313
+ add_pass('sroa')
314
+ end
315
+
316
+ # @return self
317
+ def lower_expect!
318
+ add_pass('lower-expect')
319
+ end
320
+
321
+ # @return self
322
+ def cvprop!
323
+ correlated_propagation!
324
+ end
325
+
326
+ # @return self
327
+ def correlated_propagation!
328
+ add_pass('correlated-propagation')
329
+ end
330
+
331
+ # @return self
332
+ def lower_constant_intrinsics!
333
+ add_pass('lower-constant-intrinsics')
334
+ end
335
+
336
+ # @return self
337
+ def slp_vectorize!
338
+ slp_vectorizer!
339
+ end
340
+
341
+ # @return self
342
+ def slp_vectorizer!
343
+ add_pass('slp-vectorizer')
344
+ end
345
+
346
+ # @return self
347
+ def add_discriminators!
348
+ add_pass('add-discriminators')
349
+ end
350
+
351
+ # @return self
352
+ def mergereturn!
353
+ add_pass('mergereturn')
354
+ end
355
+
356
+ # @return self
357
+ def mergeicmps!
358
+ add_pass('mergeicmps')
359
+ end
360
+
361
+ # @return self
362
+ def basic_aa!
363
+ add_pass('require<basic-aa>')
364
+ end
365
+
366
+ alias basicaa! basic_aa!
367
+
368
+ # @return self
369
+ def objc_arc_aa
370
+ add_pass('require<objc-arc-aa>')
371
+ end
372
+
373
+ # @return self
374
+ def scev_aa!
375
+ add_pass('require<scev-aa>')
376
+ end
377
+
378
+ # @return self
379
+ def scoped_noalias_aa!
380
+ add_pass('require<scoped-noalias-aa>')
381
+ end
382
+
383
+ # @return self
384
+ def tbaa!
385
+ add_pass('require<tbaa>')
386
+ end
387
+
388
+ # @return self
389
+ def gobals_aa!
390
+ add_pass('require<globals-aa>')
391
+ end
392
+
393
+ # @return self
394
+ def lowerswitch!
395
+ add_pass('lowerswitch')
396
+ end
397
+
398
+ # Inlines functions marked as "always_inline".
399
+ # https://llvm.org/doxygen/AlwaysInliner_8h_source.html
400
+ # https://llvm.org/doxygen/AlwaysInliner_8cpp_source.html
401
+ # @return self
402
+ def always_inline!
403
+ add_pass('always-inline')
404
+ end
405
+
406
+ # This pass looks for equivalent functions that are mergable and folds them.
407
+ # https://llvm.org/docs/MergeFunctions.html
408
+ # https://llvm.org/doxygen/MergeFunctions_8cpp_source.html
409
+ # https://llvm.org/doxygen/MergeFunctions_8h_source.html
410
+ # @return self
411
+ def mergefunc!
412
+ add_pass('mergefunc')
413
+ end
414
+
415
+ # Propagate called values
416
+ # This file implements a transformation that attaches !callees metadata to
417
+ # indirect call sites. For a given call site, the metadata, if present,
418
+ # indicates the set of functions the call site could possibly target at
419
+ # run-time. This metadata is added to indirect call sites when the set of
420
+ # possible targets can be determined by analysis and is known to be small. The
421
+ # analysis driving the transformation is similar to constant propagation and
422
+ # makes uses of the generic sparse propagation solver.
423
+ # https://llvm.org/doxygen/CalledValuePropagation_8h_source.html
424
+ # @return self
425
+ def called_value_propagation!
426
+ add_pass('called-value-propagation')
427
+ end
428
+
429
+ # @return self
430
+ def deadargelim!
431
+ add_pass('deadargelim')
432
+ end
433
+
434
+ alias dae! deadargelim!
435
+
436
+ # ConstantMerge is designed to build up a map of available constants and eliminate duplicates when it is initialized.
437
+ # https://llvm.org/doxygen/ConstantMerge_8cpp_source.html
438
+ # https://llvm.org/doxygen/ConstantMerge_8h_source.html
439
+ # @return self
440
+ def constmerge!
441
+ add_pass('constmerge')
442
+ end
443
+
444
+ alias const_merge! constmerge!
445
+
446
+ # Aggressive Dead Code Elimination
447
+ # @return self
448
+ def adce!
449
+ add_pass('adce')
450
+ end
451
+
452
+ # @return self
453
+ def function_attrs!
454
+ add_pass('function-attrs')
455
+ end
456
+
457
+ alias fun_attrs! function_attrs!
458
+
459
+ # @return self
460
+ def strip!
461
+ add_pass('strip')
462
+ end
463
+
464
+ # @return self
465
+ def strip_dead_prototypes!
466
+ add_pass('strip-dead-prototypes')
467
+ end
468
+
469
+ alias sdp! strip_dead_prototypes!
470
+
471
+ # @return self
472
+ # TODO: test this
473
+ def internalize!(_all_but_main = true) # rubocop:disable Style/OptionalBooleanParameter
474
+ add_pass('internalize')
475
+ end
476
+
477
+ # This pass implements interprocedural sparse conditional constant propagation and merging.
478
+ # https://llvm.org/doxygen/IPO_2SCCP_8h_source.html
479
+ # https://llvm.org/doxygen/IPO_2SCCP_8cpp_source.html
480
+ # @return self
481
+ # @todo accept parameters ipsccp<no-func-spec;func-spec>
482
+ def ipsccp!
483
+ add_pass('ipsccp')
484
+ end
485
+
486
+ # @return self
487
+ def global_opt!
488
+ add_pass('globalopt')
489
+ end
490
+
491
+ # Global Dead Code Elimination
492
+ # TODO: takes params
493
+ # @return self
494
+ def globaldce!
495
+ add_pass('globaldce')
496
+ end
497
+
498
+ alias gdce! globaldce!
499
+
500
+ # Bit-Tracking Dead Code Elimination pass
501
+ # @return self
502
+ def bdce!
503
+ add_pass('bdce')
504
+ end
505
+
506
+ # Dead Store Elimination
507
+ # his file implements a trivial dead store elimination that only considers basic-block local redundant stores.
508
+ # https://llvm.org/doxygen/DeadStoreElimination_8h_source.html
509
+ # @return self
510
+ def dse!
511
+ add_pass('dse')
512
+ end
513
+
514
+ # @return self
515
+ def argpromotion!
516
+ add_pass('argpromotion')
517
+ end
518
+
519
+ alias arg_promote! argpromotion!
520
+
521
+ # The inliner pass for the new pass manager.
522
+ # https://llvm.org/doxygen/classllvm_1_1InlinerPass.html
523
+ # https://llvm.org/doxygen/Inliner_8h_source.html
524
+ # https://llvm.org/doxygen/Inliner_8cpp_source.html
525
+ # @return self
526
+ def inline!
527
+ add_pass('inline')
528
+ end
529
+
530
+ # Thread Sanitizer
531
+ # https://clang.llvm.org/docs/ThreadSanitizer.html
532
+ # @return self
533
+ def tsan!
534
+ add_pass('tsan')
535
+ end
536
+
537
+ # Thread Sanitiver - Module
538
+ # https://clang.llvm.org/docs/ThreadSanitizer.html
539
+ # @return self
540
+ def tsan_module!
541
+ add_pass('tsan-module')
542
+ end
543
+
544
+ # Hardware Assisted Address Sanitiver
545
+ # TODO: takes params
546
+ # https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
547
+ # https://llvm.org/doxygen/HWAddressSanitizer_8cpp_source.html
548
+ # @return self
549
+ def hwasan!(_options = {})
550
+ add_pass('hwasan')
551
+ end
552
+
553
+ # Address Sanitizer
554
+ # TODO: takes params
555
+ # https://clang.llvm.org/docs/AddressSanitizer.html
556
+ # https://llvm.org/doxygen/AddressSanitizer_8h_source.html
557
+ # https://llvm.org/doxygen/AddressSanitizer_8cpp_source.html
558
+ # @return self
559
+ def asan!(options = {})
560
+ opt_str = options[:kernel] ? '<kernel>' : ''
561
+ add_pass("asan#{opt_str}")
562
+ end
563
+
564
+ # Memory Sanitizer
565
+ # TODO: takes params
566
+ # https://llvm.org/doxygen/MemorySanitizer_8cpp.html
567
+ # https://llvm.org/doxygen/MemorySanitizer_8h_source.html
568
+ # https://clang.llvm.org/docs/MemorySanitizer.html
569
+ # KernelMemorySanitizer only supports X86_64 and SystemZ at the moment.
570
+ # @return self
571
+ def msan!(options = {})
572
+ opt_str = options[:kernel] ? '<kernel>' : ''
573
+ add_pass("msan#{opt_str}")
574
+ end
575
+
576
+ # DataFlow Sanitizer
577
+ # https://clang.llvm.org/docs/DataFlowSanitizer.html
578
+ # @return self
579
+ def dfsan!
580
+ add_pass('dfsan')
581
+ end
582
+
583
+ # https://clang.llvm.org/docs/SanitizerCoverage.html
584
+ # @return self
585
+ def sancov_module!
586
+ add_pass('sancov-module')
587
+ end
588
+
589
+ # https://llvm.org/docs/doxygen/SanitizerBinaryMetadata_8h_source.html
590
+ # @return self
591
+ def sanmd_module!
592
+ add_pass('sanmd-module')
593
+ end
594
+
595
+ def run(mod, target)
596
+ return self if passes.empty?
597
+
598
+ error = with_options { |options| C.run_passes(mod, pass_string, target, options) }
599
+ if !error.null?
600
+ error_msg = C.get_error_message(error)
601
+ # TODO: clone then dispose of error_msg, currently produces "munmap_chunk(): invalid pointer"
602
+ # save_message = error_msg.clone
603
+ # C.dispose_error_message(error_msg)
604
+ raise ArgumentError, error_msg
605
+ end
606
+ self
607
+ end
608
+
609
+ def pass_string
610
+ passes.join(',')
611
+ end
612
+
613
+ def ipcp!
614
+ deprecated('ipcp! / LLVMAddIPConstantPropagationPass was removed from LLVM')
615
+ end
616
+
617
+ def prune_eh!
618
+ deprecated('prune_eh! / LLVMAddPruneEHPass was removed in LLVM 16')
619
+ end
620
+
621
+ def simplify_libcalls!
622
+ deprecated('simplify_libcalls! / LLVMAddSimplifyLibCallsPass was removed from LLVM')
623
+ end
624
+
625
+ def scalarrepl!
626
+ deprecated('TODO: scalarrepl')
627
+ end
628
+
629
+ def scalarrepl_ssa!
630
+ deprecated('TODO: scalarrepl_ssa')
631
+ end
632
+
633
+ def scalarrepl_threshold!(_threshold = 0)
634
+ deprecated('TODO: scalarrepl_threshold')
635
+ end
636
+
637
+ def bb_vectorize!
638
+ warn('bb_vectorize! / LLVMAddBBVectorizePass was removed from LLVM - replace with slp_vectorize!')
639
+ slp_vectorize!
640
+ end
641
+
642
+ def constprop!
643
+ warn('constprop! / LLVMAddConstantPropagationPass was removed from LLVM')
644
+ end
645
+
646
+ private
647
+
648
+ attr_writer :passes
649
+
650
+ def deprecated(message)
651
+ warn message
652
+ self
653
+ end
654
+
655
+ # updates options parameter and returns it
656
+ def build_options!(options)
657
+ if inliner_threshold
658
+ C.set_inliner_threshold(options, inliner_threshold)
659
+ end
660
+
661
+ if merge_functions
662
+ C.set_merge_functions(options, !!merge_functions)
663
+ end
664
+
665
+ options
666
+ end
667
+
668
+ # wraps creation and disposal of options in block
669
+ def with_options
670
+ options = C.create_pass_builder_options
671
+ build_options!(options)
672
+ yield options
673
+ ensure
674
+ C.dispose_pass_builder_options(options)
675
+ end
676
+ end
677
+
678
+ module C
679
+ #
680
+ # @method run_passes(pmb, opt_level)
681
+ # @param [OpaquePassManagerBuilder] pmb
682
+ # @param [Integer] opt_level
683
+ # @return [nil]
684
+ # @scope class
685
+ # /**
686
+ # * Construct and run a set of passes over a module
687
+ # *
688
+ # * This function takes a string with the passes that should be used. The format
689
+ # * of this string is the same as opt's -passes argument for the new pass
690
+ # * manager. Individual passes may be specified, separated by commas. Full
691
+ # * pipelines may also be invoked using `default<O3>` and friends. See opt for
692
+ # * full reference of the Passes format.
693
+ # */
694
+ # LLVMErrorRef LLVMRunPasses(LLVMModuleRef M, const char *Passes,
695
+ # LLVMTargetMachineRef TM,
696
+ # LLVMPassBuilderOptionsRef Options);
697
+
698
+ attach_function :run_passes, :LLVMRunPasses, [:pointer, :string, :pointer, :pointer], :pointer
699
+
700
+ attach_function :create_pass_builder_options, :LLVMCreatePassBuilderOptions, [], :pointer
701
+
702
+ attach_function :dispose_pass_builder_options, :LLVMDisposePassBuilderOptions, [:pointer], :void
703
+
704
+ attach_function(:get_error_message, :LLVMGetErrorMessage, [:pointer], :string)
705
+
706
+ attach_function(:dispose_error_message, :LLVMDisposeErrorMessage, [:string], :void)
707
+
708
+ attach_function(:set_inliner_threshold, :LLVMPassBuilderOptionsSetInlinerThreshold, [:pointer, :int], :void)
709
+
710
+ attach_function(:set_merge_functions, :LLVMPassBuilderOptionsSetMergeFunctions, [:pointer, :bool], :void)
711
+ end
712
+ end