Skip to content

Commit d7ea436

Browse files
committed
Auto merge of rust-lang#140256 - matthiaskrgr:rollup-8if58zf, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#136083 (Suggest {to,from}_ne_bytes for transmutations between arrays and integers, etc) - rust-lang#138282 (Add `#[repr(u128)]`/`#[repr(i128)]` enums to `improper_ctypes_definitions`) - rust-lang#139700 (Autodiff flags) - rust-lang#140139 (rustc_target: Adjust RISC-V feature implication) - rust-lang#140141 (Move zkVM constants into `sys::env_consts`) - rust-lang#140150 (fix MAX_EXP and MIN_EXP docs) - rust-lang#140172 (Make algebraic functions into `const fn` items.) - rust-lang#140191 (Remove git repository from git config) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 3c877f6 + a016552 commit d7ea436

File tree

81 files changed

+1031
-261
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+1031
-261
lines changed

compiler/rustc_codegen_cranelift/example/example.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![feature(no_core, unboxed_closures)]
22
#![no_core]
3-
#![allow(dead_code)]
3+
#![allow(dead_code, unnecessary_transmutes)]
44

55
extern crate mini_core;
66

compiler/rustc_codegen_gcc/example/example.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![feature(no_core, unboxed_closures)]
22
#![no_core]
3-
#![allow(dead_code)]
3+
#![allow(dead_code, unnecessary_transmutes)]
44

55
extern crate mini_core;
66

@@ -11,11 +11,7 @@ fn abc(a: u8) -> u8 {
1111
}
1212

1313
fn bcd(b: bool, a: u8) -> u8 {
14-
if b {
15-
a * 2
16-
} else {
17-
a * 3
18-
}
14+
if b { a * 2 } else { a * 3 }
1915
}
2016

2117
fn call() {

compiler/rustc_codegen_llvm/src/back/lto.rs

+22-18
Original file line numberDiff line numberDiff line change
@@ -584,12 +584,10 @@ fn thin_lto(
584584
}
585585
}
586586

587-
fn enable_autodiff_settings(ad: &[config::AutoDiff], module: &mut ModuleCodegen<ModuleLlvm>) {
587+
fn enable_autodiff_settings(ad: &[config::AutoDiff]) {
588588
for &val in ad {
589+
// We intentionally don't use a wildcard, to not forget handling anything new.
589590
match val {
590-
config::AutoDiff::PrintModBefore => {
591-
unsafe { llvm::LLVMDumpModule(module.module_llvm.llmod()) };
592-
}
593591
config::AutoDiff::PrintPerf => {
594592
llvm::set_print_perf(true);
595593
}
@@ -603,17 +601,23 @@ fn enable_autodiff_settings(ad: &[config::AutoDiff], module: &mut ModuleCodegen<
603601
llvm::set_inline(true);
604602
}
605603
config::AutoDiff::LooseTypes => {
606-
llvm::set_loose_types(false);
604+
llvm::set_loose_types(true);
607605
}
608606
config::AutoDiff::PrintSteps => {
609607
llvm::set_print(true);
610608
}
611-
// We handle this below
609+
// We handle this in the PassWrapper.cpp
610+
config::AutoDiff::PrintPasses => {}
611+
// We handle this in the PassWrapper.cpp
612+
config::AutoDiff::PrintModBefore => {}
613+
// We handle this in the PassWrapper.cpp
612614
config::AutoDiff::PrintModAfter => {}
613-
// We handle this below
615+
// We handle this in the PassWrapper.cpp
614616
config::AutoDiff::PrintModFinal => {}
615617
// This is required and already checked
616618
config::AutoDiff::Enable => {}
619+
// We handle this below
620+
config::AutoDiff::NoPostopt => {}
617621
}
618622
}
619623
// This helps with handling enums for now.
@@ -647,27 +651,27 @@ pub(crate) fn run_pass_manager(
647651
// We then run the llvm_optimize function a second time, to optimize the code which we generated
648652
// in the enzyme differentiation pass.
649653
let enable_ad = config.autodiff.contains(&config::AutoDiff::Enable);
650-
let stage =
651-
if enable_ad { write::AutodiffStage::DuringAD } else { write::AutodiffStage::PostAD };
654+
let stage = if thin {
655+
write::AutodiffStage::PreAD
656+
} else {
657+
if enable_ad { write::AutodiffStage::DuringAD } else { write::AutodiffStage::PostAD }
658+
};
652659

653660
if enable_ad {
654-
enable_autodiff_settings(&config.autodiff, module);
661+
enable_autodiff_settings(&config.autodiff);
655662
}
656663

657664
unsafe {
658665
write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?;
659666
}
660667

661-
if cfg!(llvm_enzyme) && enable_ad {
662-
// This is the post-autodiff IR, mainly used for testing and educational purposes.
663-
if config.autodiff.contains(&config::AutoDiff::PrintModAfter) {
664-
unsafe { llvm::LLVMDumpModule(module.module_llvm.llmod()) };
665-
}
666-
668+
if cfg!(llvm_enzyme) && enable_ad && !thin {
667669
let opt_stage = llvm::OptStage::FatLTO;
668670
let stage = write::AutodiffStage::PostAD;
669-
unsafe {
670-
write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?;
671+
if !config.autodiff.contains(&config::AutoDiff::NoPostopt) {
672+
unsafe {
673+
write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?;
674+
}
671675
}
672676

673677
// This is the final IR, so people should be able to inspect the optimized autodiff output,

compiler/rustc_codegen_llvm/src/back/write.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -572,20 +572,31 @@ pub(crate) unsafe fn llvm_optimize(
572572

573573
let consider_ad = cfg!(llvm_enzyme) && config.autodiff.contains(&config::AutoDiff::Enable);
574574
let run_enzyme = autodiff_stage == AutodiffStage::DuringAD;
575+
let print_before_enzyme = config.autodiff.contains(&config::AutoDiff::PrintModBefore);
576+
let print_after_enzyme = config.autodiff.contains(&config::AutoDiff::PrintModAfter);
577+
let print_passes = config.autodiff.contains(&config::AutoDiff::PrintPasses);
578+
let merge_functions;
575579
let unroll_loops;
576580
let vectorize_slp;
577581
let vectorize_loop;
578582

579583
// When we build rustc with enzyme/autodiff support, we want to postpone size-increasing
580584
// optimizations until after differentiation. Our pipeline is thus: (opt + enzyme), (full opt).
581585
// We therefore have two calls to llvm_optimize, if autodiff is used.
586+
//
587+
// We also must disable merge_functions, since autodiff placeholder/dummy bodies tend to be
588+
// identical. We run opts before AD, so there is a chance that LLVM will merge our dummies.
589+
// In that case, we lack some dummy bodies and can't replace them with the real AD code anymore.
590+
// We then would need to abort compilation. This was especially common in test cases.
582591
if consider_ad && autodiff_stage != AutodiffStage::PostAD {
592+
merge_functions = false;
583593
unroll_loops = false;
584594
vectorize_slp = false;
585595
vectorize_loop = false;
586596
} else {
587597
unroll_loops =
588598
opt_level != config::OptLevel::Size && opt_level != config::OptLevel::SizeMin;
599+
merge_functions = config.merge_functions;
589600
vectorize_slp = config.vectorize_slp;
590601
vectorize_loop = config.vectorize_loop;
591602
}
@@ -663,13 +674,16 @@ pub(crate) unsafe fn llvm_optimize(
663674
thin_lto_buffer,
664675
config.emit_thin_lto,
665676
config.emit_thin_lto_summary,
666-
config.merge_functions,
677+
merge_functions,
667678
unroll_loops,
668679
vectorize_slp,
669680
vectorize_loop,
670681
config.no_builtins,
671682
config.emit_lifetime_markers,
672683
run_enzyme,
684+
print_before_enzyme,
685+
print_after_enzyme,
686+
print_passes,
673687
sanitizer_options.as_ref(),
674688
pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
675689
pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),

compiler/rustc_codegen_llvm/src/builder/autodiff.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ pub(crate) fn differentiate<'ll>(
473473
return Err(diag_handler.handle().emit_almost_fatal(AutoDiffWithoutEnable));
474474
}
475475

476-
// Before dumping the module, we want all the TypeTrees to become part of the module.
476+
// Here we replace the placeholder code with the actual autodiff code, which calls Enzyme.
477477
for item in diff_items.iter() {
478478
let name = item.source.clone();
479479
let fn_def: Option<&llvm::Value> = cx.get_function(&name);

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2454,6 +2454,9 @@ unsafe extern "C" {
24542454
DisableSimplifyLibCalls: bool,
24552455
EmitLifetimeMarkers: bool,
24562456
RunEnzyme: bool,
2457+
PrintBeforeEnzyme: bool,
2458+
PrintAfterEnzyme: bool,
2459+
PrintPasses: bool,
24572460
SanitizerOptions: Option<&SanitizerOptions>,
24582461
PGOGenPath: *const c_char,
24592462
PGOUsePath: *const c_char,

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+25
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,31 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
158158
self.copy_op(&val, dest)?;
159159
}
160160

161+
sym::fadd_algebraic
162+
| sym::fsub_algebraic
163+
| sym::fmul_algebraic
164+
| sym::fdiv_algebraic
165+
| sym::frem_algebraic => {
166+
let a = self.read_immediate(&args[0])?;
167+
let b = self.read_immediate(&args[1])?;
168+
169+
let op = match intrinsic_name {
170+
sym::fadd_algebraic => BinOp::Add,
171+
sym::fsub_algebraic => BinOp::Sub,
172+
sym::fmul_algebraic => BinOp::Mul,
173+
sym::fdiv_algebraic => BinOp::Div,
174+
sym::frem_algebraic => BinOp::Rem,
175+
176+
_ => bug!(),
177+
};
178+
179+
let res = self.binary_op(op, &a, &b)?;
180+
// `binary_op` already called `generate_nan` if needed.
181+
182+
// FIXME: Miri should add some non-determinism to the result here to catch any dependences on exact computations. This has previously been done, but the behaviour was removed as part of constification.
183+
self.write_immediate(*res, dest)?;
184+
}
185+
161186
sym::ctpop
162187
| sym::cttz
163188
| sym::cttz_nonzero

compiler/rustc_lint/src/types.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use std::iter;
22
use std::ops::ControlFlow;
33

4-
use rustc_abi::{BackendRepr, TagEncoding, VariantIdx, Variants, WrappingRange};
4+
use rustc_abi::{
5+
BackendRepr, Integer, IntegerType, TagEncoding, VariantIdx, Variants, WrappingRange,
6+
};
57
use rustc_data_structures::fx::FxHashSet;
68
use rustc_errors::DiagMessage;
79
use rustc_hir::intravisit::VisitorExt;
@@ -1243,6 +1245,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
12431245
};
12441246
}
12451247

1248+
if let Some(IntegerType::Fixed(Integer::I128, _)) = def.repr().int {
1249+
return FfiUnsafe {
1250+
ty,
1251+
reason: fluent::lint_improper_ctypes_128bit,
1252+
help: None,
1253+
};
1254+
}
1255+
12461256
use improper_ctypes::check_non_exhaustive_variant;
12471257

12481258
let non_exhaustive = def.variant_list_has_applicable_non_exhaustive();

compiler/rustc_lint_defs/src/builtin.rs

+25
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ declare_lint_pass! {
117117
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
118118
UNNAMEABLE_TEST_ITEMS,
119119
UNNAMEABLE_TYPES,
120+
UNNECESSARY_TRANSMUTES,
120121
UNREACHABLE_CODE,
121122
UNREACHABLE_PATTERNS,
122123
UNSAFE_ATTR_OUTSIDE_UNSAFE,
@@ -4909,6 +4910,30 @@ declare_lint! {
49094910
"detects pointer to integer transmutes in const functions and associated constants",
49104911
}
49114912

4913+
declare_lint! {
4914+
/// The `unnecessary_transmutes` lint detects transmutations that have safer alternatives.
4915+
///
4916+
/// ### Example
4917+
///
4918+
/// ```rust
4919+
/// fn bytes_at_home(x: [u8; 4]) -> u32 {
4920+
/// unsafe { std::mem::transmute(x) }
4921+
/// }
4922+
/// ```
4923+
///
4924+
/// {{produces}}
4925+
///
4926+
/// ### Explanation
4927+
///
4928+
/// Using an explicit method is preferable over calls to
4929+
/// [`transmute`](https://doc.rust-lang.org/std/mem/fn.transmute.html) as
4930+
/// they more clearly communicate the intent, are easier to review, and
4931+
/// are less likely to accidentally result in unsoundness.
4932+
pub UNNECESSARY_TRANSMUTES,
4933+
Warn,
4934+
"detects transmutes that are shadowed by std methods"
4935+
}
4936+
49124937
declare_lint! {
49134938
/// The `tail_expr_drop_order` lint looks for those values generated at the tail expression location,
49144939
/// that runs a custom `Drop` destructor.

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

+28-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "llvm/IR/LegacyPassManager.h"
1515
#include "llvm/IR/PassManager.h"
1616
#include "llvm/IR/Verifier.h"
17+
#include "llvm/IRPrinter/IRPrintingPasses.h"
1718
#include "llvm/LTO/LTO.h"
1819
#include "llvm/MC/MCSubtargetInfo.h"
1920
#include "llvm/MC/TargetRegistry.h"
@@ -703,7 +704,8 @@ extern "C" LLVMRustResult LLVMRustOptimize(
703704
bool LintIR, LLVMRustThinLTOBuffer **ThinLTOBufferRef, bool EmitThinLTO,
704705
bool EmitThinLTOSummary, bool MergeFunctions, bool UnrollLoops,
705706
bool SLPVectorize, bool LoopVectorize, bool DisableSimplifyLibCalls,
706-
bool EmitLifetimeMarkers, bool RunEnzyme,
707+
bool EmitLifetimeMarkers, bool RunEnzyme, bool PrintBeforeEnzyme,
708+
bool PrintAfterEnzyme, bool PrintPasses,
707709
LLVMRustSanitizerOptions *SanitizerOptions, const char *PGOGenPath,
708710
const char *PGOUsePath, bool InstrumentCoverage,
709711
const char *InstrProfileOutput, const char *PGOSampleUsePath,
@@ -1048,14 +1050,38 @@ extern "C" LLVMRustResult LLVMRustOptimize(
10481050
// now load "-enzyme" pass:
10491051
#ifdef ENZYME
10501052
if (RunEnzyme) {
1051-
registerEnzymeAndPassPipeline(PB, true);
1053+
1054+
if (PrintBeforeEnzyme) {
1055+
// Handle the Rust flag `-Zautodiff=PrintModBefore`.
1056+
std::string Banner = "Module before EnzymeNewPM";
1057+
MPM.addPass(PrintModulePass(outs(), Banner, true, false));
1058+
}
1059+
1060+
registerEnzymeAndPassPipeline(PB, false);
10521061
if (auto Err = PB.parsePassPipeline(MPM, "enzyme")) {
10531062
std::string ErrMsg = toString(std::move(Err));
10541063
LLVMRustSetLastError(ErrMsg.c_str());
10551064
return LLVMRustResult::Failure;
10561065
}
1066+
1067+
if (PrintAfterEnzyme) {
1068+
// Handle the Rust flag `-Zautodiff=PrintModAfter`.
1069+
std::string Banner = "Module after EnzymeNewPM";
1070+
MPM.addPass(PrintModulePass(outs(), Banner, true, false));
1071+
}
10571072
}
10581073
#endif
1074+
if (PrintPasses) {
1075+
// Print all passes from the PM:
1076+
std::string Pipeline;
1077+
raw_string_ostream SOS(Pipeline);
1078+
MPM.printPipeline(SOS, [&PIC](StringRef ClassName) {
1079+
auto PassName = PIC.getPassNameForClassName(ClassName);
1080+
return PassName.empty() ? ClassName : PassName;
1081+
});
1082+
outs() << Pipeline;
1083+
outs() << "\n";
1084+
}
10591085

10601086
// Upgrade all calls to old intrinsics first.
10611087
for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E;)

compiler/rustc_mir_transform/messages.ftl

+1
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,4 @@ mir_transform_undefined_transmute = pointers cannot be transmuted to integers du
8484
.help = for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html
8585
8686
mir_transform_unknown_pass_name = MIR pass `{$name}` is unknown and will be ignored
87+
mir_transform_unnecessary_transmute = unnecessary transmute

0 commit comments

Comments
 (0)