@@ -454,16 +454,6 @@ impl Step for Llvm {
454454 enabled_llvm_runtimes. push ( "compiler-rt" ) ;
455455 }
456456
457- // This is an experimental flag, which likely builds more than necessary.
458- // We will optimize it when we get closer to releasing it on nightly.
459- if builder. config . llvm_offload {
460- enabled_llvm_runtimes. push ( "offload" ) ;
461- //FIXME(ZuseZ4): LLVM intends to drop the offload dependency on openmp.
462- //Remove this line once they achieved it.
463- enabled_llvm_runtimes. push ( "openmp" ) ;
464- enabled_llvm_projects. push ( "compiler-rt" ) ;
465- }
466-
467457 if !enabled_llvm_projects. is_empty ( ) {
468458 enabled_llvm_projects. sort ( ) ;
469459 enabled_llvm_projects. dedup ( ) ;
@@ -896,6 +886,128 @@ fn get_var(var_base: &str, host: &str, target: &str) -> Option<OsString> {
896886 . or_else ( || env:: var_os ( var_base) )
897887}
898888
889+ #[ derive( Debug , Copy , Clone , Hash , PartialEq , Eq ) ]
890+ pub struct OmpOffload {
891+ pub target : TargetSelection ,
892+ }
893+
894+ impl Step for OmpOffload {
895+ type Output = PathBuf ;
896+ const IS_HOST : bool = true ;
897+
898+ fn should_run ( run : ShouldRun < ' _ > ) -> ShouldRun < ' _ > {
899+ run. path ( "src/llvm-project/offload" )
900+ }
901+
902+ fn make_run ( run : RunConfig < ' _ > ) {
903+ run. builder . ensure ( OmpOffload { target : run. target } ) ;
904+ }
905+
906+ /// Compile OpenMP offload runtimes for `target`.
907+ #[ allow( unused) ]
908+ fn run ( self , builder : & Builder < ' _ > ) -> PathBuf {
909+ if builder. config . dry_run ( ) {
910+ return PathBuf :: from ( "/" ) ;
911+ }
912+ let target = self . target ;
913+
914+ let LlvmResult { host_llvm_config, .. } = builder. ensure ( Llvm { target : self . target } ) ;
915+
916+ let out_dir = builder. llvm_out ( target) ;
917+ static STAMP_HASH_MEMO : OnceLock < String > = OnceLock :: new ( ) ;
918+ let smart_stamp_hash = STAMP_HASH_MEMO . get_or_init ( || {
919+ generate_smart_stamp_hash (
920+ builder,
921+ & builder. config . src . join ( "src/llvm-project/offload" ) ,
922+ builder. offload_info . sha ( ) . unwrap_or_default ( ) ,
923+ )
924+ } ) ;
925+ let stamp = BuildStamp :: new ( & out_dir) . with_prefix ( "offload" ) . add_stamp ( smart_stamp_hash) ;
926+
927+ trace ! ( "checking build stamp to see if we need to rebuild offload/openmp artifacts" ) ;
928+ if stamp. is_up_to_date ( ) {
929+ trace ! ( ?out_dir, "offload/openmp build artifacts are up to date" ) ;
930+ if stamp. stamp ( ) . is_empty ( ) {
931+ builder. info (
932+ "Could not determine the Offload submodule commit hash. \
933+ Assuming that an Offload rebuild is not necessary.",
934+ ) ;
935+ builder. info ( & format ! (
936+ "To force Offload/OpenMP to rebuild, remove the file `{}`" ,
937+ stamp. path( ) . display( )
938+ ) ) ;
939+ }
940+ return out_dir;
941+ }
942+
943+ trace ! ( ?target, "(re)building offload/openmp artifacts" ) ;
944+ builder. info ( & format ! ( "Building OpenMP/Offload for {target}" ) ) ;
945+ t ! ( stamp. remove( ) ) ;
946+ let _time = helpers:: timeit ( builder) ;
947+ t ! ( fs:: create_dir_all( & out_dir) ) ;
948+
949+ builder. config . update_submodule ( Path :: new ( "src" ) . join ( "llvm-project" ) . to_str ( ) . unwrap ( ) ) ;
950+ let mut cfg = cmake:: Config :: new ( builder. src . join ( "src/llvm-project/runtimes/" ) ) ;
951+ configure_cmake ( builder, target, & mut cfg, true , LdFlags :: default ( ) , & [ ] ) ;
952+
953+ // Re-use the same flags as llvm to control the level of debug information
954+ // generated by Enzyme.
955+ // FIXME(ZuseZ4): Find a nicer way to use Enzyme Debug builds.
956+ let profile = match ( builder. config . llvm_optimize , builder. config . llvm_release_debuginfo ) {
957+ ( false , _) => "Debug" ,
958+ ( true , false ) => "Release" ,
959+ ( true , true ) => "RelWithDebInfo" ,
960+ } ;
961+ trace ! ( ?profile) ;
962+
963+ //let cc = if let Some(p) = &builder.build.config.llvm_offload_cc {
964+ // //p.clone()
965+ // builder.cc(target)
966+ //} else {
967+ // builder.cc(target)
968+ //};
969+ //let cxx = if let Some(p) = &builder.build.config.llvm_offload_cxx {
970+ // //p.clone()
971+ // builder.cxx(target).unwrap()
972+ //} else {
973+ // builder.cxx(target).unwrap()
974+ //};
975+ let root = if let Some ( p) = & builder. build . config . llvm_root_offload {
976+ p. clone ( )
977+ } else {
978+ builder. llvm_out ( target) . join ( "build" )
979+ } ;
980+ let clang_dir = if !builder. config . llvm_clang {
981+ // We must have an external clang to use.
982+ assert ! ( & builder. build. config. llvm_clang_dir. is_some( ) ) ;
983+ builder. build . config . llvm_clang_dir . clone ( )
984+ } else {
985+ // No need to specify it, since we use the in-tree clang
986+ None
987+ } ;
988+
989+ cfg. out_dir ( & out_dir)
990+ . profile ( profile)
991+ . env ( "LLVM_CONFIG_REAL" , & host_llvm_config)
992+ . define ( "LLVM_ENABLE_ASSERTIONS" , "ON" )
993+ . define ( "LLVM_ENABLE_RUNTIMES" , "openmp;offload" )
994+ . define ( "LLVM_INCLUDE_TESTS" , "OFF" )
995+ . define ( "OFFLOAD_INCLUDE_TESTS" , "OFF" )
996+ //.define("CMAKE_C_COMPILER", cc)
997+ //.define("CMAKE_CXX_COMPILER", cxx)
998+ . define ( "OPENMP_STANDALONE_BUILD" , "ON" )
999+ . define ( "LLVM_ROOT" , root)
1000+ . define ( "LLVM_DIR" , builder. llvm_out ( target) . join ( "lib" ) . join ( "cmake" ) . join ( "llvm" ) ) ;
1001+ if let Some ( p) = clang_dir {
1002+ cfg. define ( "Clang_DIR" , p) ;
1003+ }
1004+ cfg. build ( ) ;
1005+
1006+ t ! ( stamp. write( ) ) ;
1007+ out_dir
1008+ }
1009+ }
1010+
8991011#[ derive( Debug , Copy , Clone , Hash , PartialEq , Eq ) ]
9001012pub struct Enzyme {
9011013 pub target : TargetSelection ,
0 commit comments