ruby-llvm 16.0.1 → 18.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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