@@ -70,6 +70,12 @@ fn process_typetree_recursive(
7070 extra_ints
7171}
7272
73+ enum TTLocation {
74+ Definition ,
75+ Callsite ,
76+ Intrinsic ,
77+ }
78+
7379#[ cfg_attr( not( feature = "llvm_enzyme" ) , allow( unused) ) ]
7480pub ( crate ) fn add_tt < ' tcx , ' ll > (
7581 llmod : & ' ll llvm:: Module ,
@@ -104,11 +110,19 @@ pub(crate) fn add_tt<'tcx, 'll>(
104110 let attr_name = "enzyme_type" ;
105111 let c_attr_name = CString :: new ( attr_name) . unwrap ( ) ;
106112
113+ let tt_location: TTLocation = if llvm:: LLVMRustIsIntrinsicCall ( fn_def) {
114+ TTLocation :: Callsite
115+ } else if llvm:: LLVMRustSupportsEnzymeMD ( fn_def) {
116+ TTLocation :: Intrinsic
117+ } else {
118+ TTLocation :: Definition
119+ } ;
120+
107121 let mut offset = 0 ;
108122 for ( i, input) in inputs. iter ( ) . enumerate ( ) {
109123 let ( enzyme_tt, extra_ints) = to_enzyme_typetree ( & input, llvm_data_layout, llcx) ;
110124
111- // This scope is just a visual reminder that we *must* drop the enzyme_wrapper before
125+ // This scope is a simple solution since we *must* drop the enzyme_wrapper before
112126 // we drop any typetrees (mainly enzyme_tt and extra_ints). Drop calls can not accept
113127 // arguments like an enzyme_wrapper, so the typetree drop impl has to call get_instance
114128 // on the static enzyme instance, which is behind a Mutex. Therefore we'd deadlock if we
@@ -118,74 +132,59 @@ pub(crate) fn add_tt<'tcx, 'll>(
118132 let c_str = enzyme_wrapper. tree_to_cstr ( enzyme_tt. inner ) ;
119133
120134 let attr = llvm:: CreateAttrStringValueFromCStr ( llcx, & c_attr_name, & c_str) ;
121- dbg ! ( & fn_def) ;
122- if llvm:: LLVMRustSupportsEnzymeMD ( fn_def) {
123- dbg ! ( "extractvalue md" ) ;
124- let md = enzyme_wrapper. tree_to_md ( enzyme_tt. inner , llcx) ;
125- unsafe {
126- llvm:: LLVMRustSetEnzymeTypeMD ( fn_def, md. unwrap ( ) ) ;
135+ let arg_pos = llvm:: AttributePlace :: Argument ( i as u32 + offset) ;
136+ match tt_location {
137+ TTLocation :: Definition => {
138+ attributes:: apply_to_llfn ( fn_def, arg_pos, & [ attr] ) ;
139+ }
140+ TTLocation :: Callsite => {
141+ attributes:: apply_to_callsite ( fn_def, arg_pos, & [ attr] ) ;
142+ }
143+ TTLocation :: Intrinsic => {
144+ let md = enzyme_wrapper. tree_to_md ( enzyme_tt. inner , llcx) ;
145+ unsafe {
146+ llvm:: LLVMRustSetEnzymeTypeMD ( fn_def, md. unwrap ( ) ) ;
147+ }
127148 }
128- } else if unsafe { llvm:: LLVMRustIsIntrinsicCall ( fn_def) } {
129- dbg ! ( "callsite" ) ;
130- attributes:: apply_to_callsite (
131- fn_def,
132- llvm:: AttributePlace :: Argument ( i as u32 + offset) ,
133- & [ attr] ,
134- ) ;
135- } else {
136- dbg ! ( "llfn" ) ;
137- attributes:: apply_to_llfn (
138- fn_def,
139- llvm:: AttributePlace :: Argument ( i as u32 + offset) ,
140- & [ attr] ,
141- ) ;
142149 }
143150 enzyme_wrapper. tree_to_string_free ( c_str. as_ptr ( ) ) ;
144151 for v in & extra_ints {
145152 offset += 1 ;
146153 let c_str = enzyme_wrapper. tree_to_cstr ( v. inner ) ;
147154 let int_attr = llvm:: CreateAttrStringValueFromCStr ( llcx, & c_attr_name, & c_str) ;
148- dbg ! ( & fn_def) ;
149- if llvm:: LLVMRustSupportsEnzymeMD ( fn_def) {
150- dbg ! ( "extractvalue input(?)" ) ;
151- let md = enzyme_wrapper. tree_to_md ( enzyme_tt. inner , llcx) ;
152- unsafe {
153- llvm:: LLVMRustSetEnzymeTypeMD ( fn_def, md. unwrap ( ) ) ;
155+ let arg_pos = llvm:: AttributePlace :: Argument ( i as u32 + offset) ;
156+ match tt_location {
157+ TTLocation :: Intrinsic => {
158+ let md = enzyme_wrapper. tree_to_md ( enzyme_tt. inner , llcx) ;
159+ unsafe {
160+ llvm:: LLVMRustSetEnzymeTypeMD ( fn_def, md. unwrap ( ) ) ;
161+ }
162+ }
163+ TTLocation :: Definition => {
164+ attributes:: apply_to_llfn ( fn_def, arg_pos, & [ int_attr] ) ;
165+ }
166+ TTLocation :: Callsite => {
167+ attributes:: apply_to_callsite ( fn_def, arg_pos, & [ int_attr] ) ;
154168 }
155- } else if unsafe { llvm:: LLVMRustIsIntrinsicCall ( fn_def) } {
156- dbg ! ( "callsite input" ) ;
157- attributes:: apply_to_callsite (
158- fn_def,
159- llvm:: AttributePlace :: Argument ( i as u32 + offset) ,
160- & [ int_attr] ,
161- ) ;
162- } else {
163- dbg ! ( "llfn" ) ;
164- attributes:: apply_to_llfn (
165- fn_def,
166- llvm:: AttributePlace :: Argument ( i as u32 + offset) ,
167- & [ int_attr] ,
168- ) ;
169169 }
170170 enzyme_wrapper. tree_to_string_free ( c_str. as_ptr ( ) ) ;
171171 }
172172 }
173173 }
174- // We will only fail this if Rust types got lowered to LLVM in a way that we didn't predict.
175- // Error, so we can learn from our mistakes.
176- //if unsafe { !llvm::LLVMRustIsIntrinsicCall(fn_def) } {
177- // dbg!("checking parameter count");
178- // let expected = offset as usize + inputs.len();
179- // let actual = llvm::count_params(fn_def) as usize;
180- // if expected != actual {
181- // tcx.dcx().warn(format!(
182- // "autodiff type-tree failure. We expected {expected} LLVM argument(s), \
183- // but the generated LLVM function has {actual} parameter(s)"
184- // ));
185- // }
186- //}
187-
188- let ( enzyme_tt, extra_ints) = to_enzyme_typetree ( & ret_tt, llvm_data_layout, llcx) ;
174+ // We will fail here if Rust types got lowered to LLVM in a way that we didn't predict.
175+ // We Error, so we can learn from our mistakes.
176+ if matches ! ( tt_location, TTLocation :: Definition ) {
177+ let expected = offset as usize + inputs. len ( ) ;
178+ let actual = llvm:: count_params ( fn_def) as usize ;
179+ if expected != actual {
180+ tcx. dcx ( ) . warn ( format ! (
181+ "autodiff type-tree failure. We expected {expected} LLVM argument(s), \
182+ but the generated LLVM function has {actual} parameter(s)"
183+ ) ) ;
184+ }
185+ }
186+
187+ let ( enzyme_tt, _extra_ints) = to_enzyme_typetree ( & ret_tt, llvm_data_layout, llcx) ;
189188 if ret_tt != RustTypeTree :: new ( ) {
190189 let enzyme_wrapper = EnzymeWrapper :: get_instance ( ) ;
191190 //if !extra_ints.is_empty() {
@@ -195,21 +194,20 @@ pub(crate) fn add_tt<'tcx, 'll>(
195194
196195 let ret_attr = llvm:: CreateAttrStringValueFromCStr ( llcx, & c_attr_name, & c_str) ;
197196
198- if llvm:: LLVMRustSupportsEnzymeMD ( fn_def) {
199- dbg ! ( "extractvalue md" ) ;
200- let md = enzyme_wrapper. tree_to_md ( enzyme_tt. inner , llcx) ;
201- unsafe {
202- llvm:: LLVMRustSetEnzymeTypeMD ( fn_def, md. unwrap ( ) ) ;
197+ let arg_pos = llvm:: AttributePlace :: ReturnValue ;
198+ match tt_location {
199+ TTLocation :: Definition => {
200+ attributes:: apply_to_llfn ( fn_def, arg_pos, & [ ret_attr] ) ;
201+ }
202+ TTLocation :: Callsite => {
203+ attributes:: apply_to_callsite ( fn_def, arg_pos, & [ ret_attr] ) ;
204+ }
205+ TTLocation :: Intrinsic => {
206+ let md = enzyme_wrapper. tree_to_md ( enzyme_tt. inner , llcx) ;
207+ unsafe {
208+ llvm:: LLVMRustSetEnzymeTypeMD ( fn_def, md. unwrap ( ) ) ;
209+ }
203210 }
204- } else if unsafe { llvm:: LLVMRustIsIntrinsicCall ( fn_def) } {
205- dbg ! ( "intrinsiccall" ) ;
206- attributes:: apply_to_callsite (
207- fn_def,
208- llvm:: AttributePlace :: ReturnValue ,
209- & [ ret_attr] ,
210- ) ;
211- } else {
212- attributes:: apply_to_llfn ( fn_def, llvm:: AttributePlace :: ReturnValue , & [ ret_attr] ) ;
213211 }
214212 enzyme_wrapper. tree_to_string_free ( c_str. as_ptr ( ) ) ;
215213 }
0 commit comments