Skip to content

Missed optimization: trunc not de-duplicated #139732

@Mark-Simulacrum

Description

@Mark-Simulacrum

This Rust program:

use std::cell::Cell;

thread_local! {
    pub static FOO: Cell<u32> = Cell::new(0xffff);
}

pub fn bar() -> u32 {
    FOO.get() + FOO.get()
}

results in (at least) a duplicate load + trunc:

First version:

  %0 = load i32, ptr @"_ZN7example3FOO29_$u7b$$u7b$constant$u7d$$u7d$28_$u7b$$u7b$closure$u7d$$u7d$3VAL17h49f9a1072bb59151E", align 4, !range !3, !noalias !4, !noundef !11
  %trunc.i.i.i.i.i = trunc nuw i32 %0 to i1

Second version:

  %self3.val.pre.i.i = load i32, ptr getelementptr inbounds nuw (i8, ptr @"_ZN7example3FOO29_$u7b$$u7b$constant$u7d$$u7d$28_$u7b$$u7b$closure$u7d$$u7d$3VAL17h49f9a1072bb59151E", i64 4), align 4
  %1 = trunc nuw i32 %0 to i1

At minimum it'd be great to eliminate the double trunc, but combining the two loads also seems worthwhile (it should be possible AFAICT to deduplicate those). That would avoid two TLS address lookups in the resulting IR and should allow for further simplification (e.g., dropping some branches).

define noundef i32 @_ZN7example3bar17h6628f733c3c7a49fE() unnamed_addr #0 personality ptr @rust_eh_personality {
start:
  %0 = load i32, ptr @"_ZN7example3FOO29_$u7b$$u7b$constant$u7d$$u7d$28_$u7b$$u7b$closure$u7d$$u7d$3VAL17h49f9a1072bb59151E", align 4, !range !3, !noalias !4, !noundef !11
  %trunc.i.i.i.i.i = trunc nuw i32 %0 to i1
  br i1 %trunc.i.i.i.i.i, label %"_ZN3std6thread5local17LocalKey$LT$T$GT$4with17h35c29327e034454aE.exit", label %"_ZN3std6thread5local17LocalKey$LT$T$GT$4with17h35c29327e034454aE.exit6.sink.split", !prof !12

"_ZN3std6thread5local17LocalKey$LT$T$GT$4with17h35c29327e034454aE.exit": ; preds = %start
  %self3.val.pre.i.i = load i32, ptr getelementptr inbounds nuw (i8, ptr @"_ZN7example3FOO29_$u7b$$u7b$constant$u7d$$u7d$28_$u7b$$u7b$closure$u7d$$u7d$3VAL17h49f9a1072bb59151E", i64 4), align 4
  %1 = trunc nuw i32 %0 to i1
...

Godbolt: https://rust.godbolt.org/z/dPb4bPTTe

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions