-
-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Open
Labels
A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchCategory: An issue highlighting optimization opportunities or PRs implementing suchI-prioritizeIssue: Indicates that prioritization has been requested for this issue.Issue: Indicates that prioritization has been requested for this issue.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
Description
Code
I tried this code:
#![crate_type = "lib"]
use std::hint::unreachable_unchecked;
use std::collections::HashMap;
type Map = HashMap<String, Vec<u32>>;
pub struct Stack {
stack: Vec<Map>,
depth: usize,
}
// ============================================================================
// BEFORE: Using iterator with nth() and next()
// - Generates unwrap panic path even with assert_unchecked hints
// - More instructions, conditional branch
// ============================================================================
#[no_mangle]
pub fn use_iter(s: &mut Stack) -> (&mut Map, &mut Map) {
// Assert invariants
if s.depth == 0 {
unsafe { unreachable_unchecked() };
}
if s.stack.len() <= s.depth {
unsafe { unreachable_unchecked() };
}
let mut iter = s.stack.iter_mut();
let parent = iter.nth(s.depth - 1).unwrap();
let current = iter.next().unwrap();
(current, parent)
}
// ============================================================================
// AFTER: Using split_at_mut
// - No panic path, fully inlined
// - Fewer instructions, no branches
// ============================================================================
#[no_mangle]
pub fn use_split(s: &mut Stack) -> (&mut Map, &mut Map) {
// Assert invariants
if s.depth == 0 {
unsafe { unreachable_unchecked() };
}
if s.stack.len() <= s.depth {
unsafe { unreachable_unchecked() };
}
let (head, tail) = s.stack.split_at_mut(s.depth);
let parent = &mut head[s.depth - 1];
let current = &mut tail[0];
(current, parent)
}I expected to see this happen:
use_iter:
mov rcx, qword ptr [rdi + 8]
mov rax, qword ptr [rdi + 24]
lea rdx, [rax + 2*rax]
shl rdx, 4
lea rax, [rcx + rdx]
add rdx, rcx
add rdx, -48
ret
use_split:
mov rcx, qword ptr [rdi + 8]
mov rax, qword ptr [rdi + 24]
lea rdx, [rax + 2*rax]
shl rdx, 4
lea rax, [rcx + rdx]
add rdx, rcx
add rdx, -48
ret
Instead, this happened:
use_iter:
mov rax, qword ptr [rdi + 24]
movabs rcx, 1152921504606846975
and rcx, rax
cmp rcx, qword ptr [rdi + 16]
je .LBB0_2
lea rcx, [rax + 2*rax]
shl rcx, 4
mov rdx, qword ptr [rdi + 8]
lea rax, [rdx + rcx]
add rdx, rcx
add rdx, -48
ret
.LBB0_2:
push rax
lea rdi, [rip + .Lanon.621aa17d7ebd209918a0c2e574629b83.1]
call qword ptr [rip + core::option::unwrap_failed::he1a8284b5a1e2496@GOTPCREL]
use_split:
mov rcx, qword ptr [rdi + 8]
mov rax, qword ptr [rdi + 24]
lea rdx, [rax + 2*rax]
shl rdx, 4
lea rax, [rcx + rdx]
add rdx, rcx
add rdx, -48
ret
.Lanon.621aa17d7ebd209918a0c2e574629b83.0:
.asciz "/app/example.rs"
.Lanon.621aa17d7ebd209918a0c2e574629b83.1:
.quad .Lanon.621aa17d7ebd209918a0c2e574629b83.0
.asciz "\017\000\000\000\000\000\000\000 \000\000\000\037\000\000"
Version it worked on
It most recently worked on: Rust 1.81
It broke in 1.82
Metadata
Metadata
Assignees
Labels
A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchCategory: An issue highlighting optimization opportunities or PRs implementing suchI-prioritizeIssue: Indicates that prioritization has been requested for this issue.Issue: Indicates that prioritization has been requested for this issue.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.