about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src/builder.rs
AgeCommit message (Collapse)AuthorLines
2025-10-02Extract helper method `set_metadata_node`Zalathar-38/+16
2025-09-28Rollup merge of #144197 - KMJ-007:type-tree, r=ZuseZ4Matthias Krüger-2/+13
TypeTree support in autodiff # TypeTrees for Autodiff ## What are TypeTrees? Memory layout descriptors for Enzyme. Tell Enzyme exactly how types are structured in memory so it can compute derivatives efficiently. ## Structure ```rust TypeTree(Vec<Type>) Type { offset: isize, // byte offset (-1 = everywhere) size: usize, // size in bytes kind: Kind, // Float, Integer, Pointer, etc. child: TypeTree // nested structure } ``` ## Example: `fn compute(x: &f32, data: &[f32]) -> f32` **Input 0: `x: &f32`** ```rust TypeTree(vec![Type { offset: -1, size: 8, kind: Pointer, child: TypeTree(vec![Type { offset: -1, size: 4, kind: Float, child: TypeTree::new() }]) }]) ``` **Input 1: `data: &[f32]`** ```rust TypeTree(vec![Type { offset: -1, size: 8, kind: Pointer, child: TypeTree(vec![Type { offset: -1, size: 4, kind: Float, // -1 = all elements child: TypeTree::new() }]) }]) ``` **Output: `f32`** ```rust TypeTree(vec![Type { offset: -1, size: 4, kind: Float, child: TypeTree::new() }]) ``` ## Why Needed? - Enzyme can't deduce complex type layouts from LLVM IR - Prevents slow memory pattern analysis - Enables correct derivative computation for nested structures - Tells Enzyme which bytes are differentiable vs metadata ## What Enzyme Does With This Information: Without TypeTrees (current state): ```llvm ; Enzyme sees generic LLVM IR: define float ``@distance(ptr*`` %p1, ptr* %p2) { ; Has to guess what these pointers point to ; Slow analysis of all memory operations ; May miss optimization opportunities } ``` With TypeTrees (our implementation): ```llvm define "enzyme_type"="{[]:Float@float}" float ``@distance(`` ptr "enzyme_type"="{[]:Pointer}" %p1, ptr "enzyme_type"="{[]:Pointer}" %p2 ) { ; Enzyme knows exact type layout ; Can generate efficient derivative code directly } ``` # TypeTrees - Offset and -1 Explained ## Type Structure ```rust Type { offset: isize, // WHERE this type starts size: usize, // HOW BIG this type is kind: Kind, // WHAT KIND of data (Float, Int, Pointer) child: TypeTree // WHAT'S INSIDE (for pointers/containers) } ``` ## Offset Values ### Regular Offset (0, 4, 8, etc.) **Specific byte position within a structure** ```rust struct Point { x: f32, // offset 0, size 4 y: f32, // offset 4, size 4 id: i32, // offset 8, size 4 } ``` TypeTree for `&Point` (internal representation): ```rust TypeTree(vec![ Type { offset: 0, size: 4, kind: Float }, // x at byte 0 Type { offset: 4, size: 4, kind: Float }, // y at byte 4 Type { offset: 8, size: 4, kind: Integer } // id at byte 8 ]) ``` Generates LLVM: ```llvm "enzyme_type"="{[]:Float@float}" ``` ### Offset -1 (Special: "Everywhere") **Means "this pattern repeats for ALL elements"** #### Example 1: Array `[f32; 100]` ```rust TypeTree(vec![Type { offset: -1, // ALL positions size: 4, // each f32 is 4 bytes kind: Float, // every element is float }]) ``` Instead of listing 100 separate Types with offsets `0,4,8,12...396` #### Example 2: Slice `&[i32]` ```rust // Pointer to slice data TypeTree(vec![Type { offset: -1, size: 8, kind: Pointer, child: TypeTree(vec![Type { offset: -1, // ALL slice elements size: 4, // each i32 is 4 bytes kind: Integer }]) }]) ``` #### Example 3: Mixed Structure ```rust struct Container { header: i64, // offset 0 data: [f32; 1000], // offset 8, but elements use -1 } ``` ```rust TypeTree(vec![ Type { offset: 0, size: 8, kind: Integer }, // header Type { offset: 8, size: 4000, kind: Pointer, child: TypeTree(vec![Type { offset: -1, size: 4, kind: Float // ALL array elements }]) } ]) ```
2025-09-25Use standard attribute logic for allocator shimNikita Popov-1/+1
Use llfn_attrs_from_instance() to generate the attributes for the allocator shim. This ensures that we generate all the usual attributes (and don't get to find out one-by-one that a certain attribute is important for a certain target). Additionally this will enable emitting the allocator-specific attributes (not included here). This change is quite awkward because the allocator shim uses SimpleCx, while llfn_attrs_from_instance uses CodegenCx. I've switched it to use SimpleCx plus tcx/sess arguments where necessary. If there's a simpler way to do this, I'd love to know about it...
2025-09-19added typetree support for memcpyKaran Janthe-2/+13
2025-09-16Update the minimum external LLVM to 20Josh Stone-7/+2
2025-08-27inline at the callsite & warn when target features mismatchJames Barford-Evans-3/+26
Co-authored-by: Jamie Cunliffe <Jamie.Cunliffe@arm.com>
2025-08-24Rename `llvm::Bool` aliases to standard const caseZalathar-15/+15
This avoids the need for `#![allow(non_upper_case_globals)]`.
2025-08-24Replace the `llvm::Bool` typedef with a proper newtypeZalathar-14/+7
2025-08-18Rollup merge of #145420 - Zalathar:llvm-c, r=WaffleLapkinStuart Cook-1/+1
cg_llvm: Use LLVM-C bindings for `LLVMSetTailCallKind`, `LLVMGetTypeKind` This PR replaces two existing `LLVMRust` bindings with equivalent calls to the LLVM-C API. For `LLVMGetTypeKind`, we avoid the UB hazard by declaring the foreign function to return `RawEnum<TypeKind>` (which is a wrapper around `u32`), and then perform checked conversion from `u32` to `TypeKind`.
2025-08-15Rollup merge of #145120 - maurer:llvm-time, r=nikicStuart Cook-1/+5
llvm: Accept new LLVM lifetime format In llvm/llvm-project#150248 LLVM removed the size parameter from the lifetime format. Tolerate not having that size parameter.
2025-08-15Use `LLVMSetTailCallKind`Zalathar-1/+1
2025-08-11llvm: Accept new LLVM lifetime formatMatthew Maurer-1/+5
LLVM removed the size parameter from the lifetime format. Tolerate not having that size parameter.
2025-08-08Stop using uadd.with.overflowScott McMurray-7/+19
2025-08-08Rollup merge of #144192 - RalfJung:atomicrmw-ptr, r=nikicTrevor Gross-8/+6
atomicrmw on pointers: move integer-pointer cast hacks into backend Conceptually, we want to have atomic operations on pointers of the form `fn atomic_add(ptr: *mut T, offset: usize, ...)`. However, LLVM does not directly support such operations (https://github.com/llvm/llvm-project/issues/120837), so we have to cast the `offset` to a pointer somewhere. This PR moves that hack into the LLVM backend, so that the standard library, intrinsic, and Miri all work with the conceptual operation we actually want. Hopefully, one day LLVM will gain a way to represent these operations without integer-pointer casts, and then the hack will disappear entirely. Cc ```@nikic``` -- this is the best we can do right now, right? Fixes https://github.com/rust-lang/rust/issues/134617
2025-08-06coverage: Remove all unstable support for MC/DC instrumentationZalathar-44/+0
2025-07-31Rollup merge of #144232 - xacrimon:explicit-tail-call, r=WaffleLapkinStuart Cook-1/+24
Implement support for `become` and explicit tail call codegen for the LLVM backend This PR implements codegen of explicit tail calls via `become` in `rustc_codegen_ssa` and support within the LLVM backend. Completes a task on (https://github.com/rust-lang/rust/issues/112788). This PR implements all the necessary bits to make explicit tail calls usable, other backends have received stubs for now and will ICE if you use `become` on them. I suspect there is some bikeshedding to be done on how we should go about implementing this for other backends, but it should be relatively straightforward for GCC after this is merged. During development I also put together a POC bytecode VM based on tail call dispatch to test these changes out and analyze the codegen to make sure it generates expected assembly. That is available [here](https://github.com/xacrimon/tcvm).
2025-07-28use let chains in ast, borrowck, codegen, const_evalKivooeo-4/+4
2025-07-26Implement support for explicit tail calls in the MIR block builders and the ↵Joel Wejdenstål-1/+24
LLVM codegen backend.
2025-07-23atomicrmw on pointers: move integer-pointer cast hacks into backendRalf Jung-8/+6
2025-07-18add various wrappers for gpu code generationManuel Drehwald-0/+69
2025-07-14Eliminate all direct uses of LLVMMDStringInContext2Oli Scherer-3/+2
2025-07-14Use context methods instead of directly calling FFIOli Scherer-3/+1
2025-07-14Merge `typeid_metadata` and `create_metadata`Oli Scherer-1/+1
2025-07-14Shrink some `unsafe` blocks in cg_llvmOli Scherer-7/+6
2025-07-07Remove support for dynamic allocasmejrs-10/+0
2025-06-22Remove dead instructions in terminate blocksMark Rousskov-2/+1
2025-06-15Correctly account for different address spaces in LLVM intrinsic invocationssayantn-2/+2
2025-06-15Use `LLVMIntrinsicGetDeclaration` to completely remove the hardcoded ↵sayantn-6/+7
intrinsics list
2025-06-12Simplify implementation of Rust intrinsics by using type parameters in the cachesayantn-132/+51
2025-06-03Remove type_test from IntrinsicCallBuilderMethodsbjorn3-2/+5
It is only used within cg_llvm.
2025-05-30Auto merge of #139385 - joboet:threadlocal_address, r=nikicbors-3/+9
rustc_codegen_llvm: use `threadlocal.address` intrinsic to access TLS Fixes #136044 r? `@nikic`
2025-05-29rustc_codegen_llvm: use `threadlocal.address` intrinsic to access TLSjoboet-3/+9
2025-05-28get rid of rustc_codegen_ssa::common::AtomicOrderingRalf Jung-6/+6
2025-05-11Rename `OperandBundleOwned` to `OperandBundleBox`Zalathar-5/+5
As with `DIBuilderBox`, the "Box" suffix does a better job of communicating that this is an owning pointer to some borrowable resource. This also renames the `raw` method to `as_ref`, which is what it would have been named originally if the `Deref` problem had been known at the time.
2025-04-24Rollup merge of #139261 - RalfJung:msvc-align-mitigation, r=oli-obkMatthias Krüger-0/+2
mitigate MSVC alignment issue on x86-32 This implements mitigation for https://github.com/rust-lang/rust/issues/112480 by stopping to emit `align` attributes on loads and function arguments when building for a win32 MSVC target. MSVC is known to not properly align `u64` and similar types, and claiming to LLVM that everything is properly aligned increases the chance that this will cause problems. Of course, the misalignment is still a bug, but we can't fix that bug, only MSVC can. Also add an errata note to the platform support page warning users about this known problem. try-job: `i686-msvc*`
2025-04-16working dupv and dupvonly for fwd modeManuel Drehwald-1/+1
2025-04-07mitigate MSVC unsoundness by not emitting alignment attributes on win32-msvc ↵Ralf Jung-0/+2
targets also mention the MSVC alignment issue in platform-support.md
2025-04-05Update the minimum external LLVM to 19Josh Stone-23/+7
2025-03-24Auto merge of #133984 - DaniPopes:scmp-ucmp, r=scottmcmbors-0/+30
Lower BinOp::Cmp to llvm.{s,u}cmp.* intrinsics Lowers `mir::BinOp::Cmp` (`three_way_compare` intrinsic) to the corresponding LLVM `llvm.{s,u}cmp.i8.*` intrinsics. These are the intrinsics mentioned in https://github.com/rust-lang/rust/pull/118310, which are now available in LLVM 19. I couldn't find any follow-up PRs/discussions about this, please let me know if I missed something. r? `@scottmcm`
2025-03-07Rollup merge of #137549 - oli-obk:llvm-ffi, r=davidtwcoMatthias Krüger-101/+40
Clean up various LLVM FFI things in codegen_llvm cc ```@ZuseZ4``` I touched some autodiff parts The major change of this PR is [bfd88ce](https://github.com/rust-lang/rust/pull/137549/commits/bfd88cead0dd79717f123ad7e9a26ecad88653cb) which makes `CodegenCx` generic just like `GenericBuilder` The other commits mostly took advantage of the new feature of making extern functions safe, but also just used some wrappers that were already there and shrunk unsafe blocks. best reviewed commit-by-commit
2025-03-06Lower BinOp::Cmp to llvm.{s,u}cmp.* intrinsicsDaniPopes-0/+30
Lowers `mir::BinOp::Cmp` (`three_way_compare` intrinsic) to the corresponding LLVM `llvm.{s,u}cmp.i8.*` intrinsics, added in LLVM 19.
2025-02-24Mark more LLVM FFI as safeOli Scherer-2/+2
2025-02-24Deduplicate more functions between `SimpleCx` and `CodegenCx`Oli Scherer-49/+4
2025-02-24Make allocator shim creation mostly use safe codeOli Scherer-4/+4
2025-02-24Generalize `BackendTypes` over `GenericCx`Oli Scherer-11/+11
2025-02-24Avoid some duplication between SimpleCx and CodegenCxOli Scherer-33/+21
2025-02-24Use safe FFI for various functions in codegen_llvmOli Scherer-6/+2
2025-02-24codegen_llvm: avoid `Deref` impls w/ extern typeDavid Wood-3/+3
`rustc_codegen_llvm` relied on `Deref` impls where `Deref::Target` was or contained an extern type - in my experimental implementation of rust-lang/rfcs#3729, this isn't possible as the `Target` associated type's `?Sized` bound cannot be relaxed backwards compatibly (unless we come up with some way of doing this). In later pull requests with the rust-lang/rfcs#3729 implementation, breakage like this could only occur for nightly users relying on the `extern_types` feature. Upstreaming this to avoid needing to keep carrying this patch locally, and I think it'll necessarily need to change eventually.
2025-02-24Auto merge of #137271 - nikic:gep-nuw-2, r=scottmcmbors-3/+26
Emit getelementptr inbounds nuw for pointer::add() Lower pointer::add (via intrinsic::offset with unsigned offset) to getelementptr inbounds nuw on LLVM versions that support it. This lets LLVM make use of the pre-condition that the offset addition does not wrap in an unsigned sense. Together with inbounds, this also implies that the offset is non-negative. Fixes https://github.com/rust-lang/rust/issues/137217.
2025-02-19Rework `OperandRef::extract_field` to stop calling `to_immediate_scalar` on ↵Scott McMurray-2/+8
things which are already immediates That means it stops trying to truncate things that are already `i1`s.