Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Packed struct operations are not emitted as operations on their backing integer #21891

Open
Validark opened this issue Nov 3, 2024 · 2 comments
Labels
backend-llvm The LLVM backend outputs an LLVM IR Module. optimization
Milestone

Comments

@Validark
Copy link
Contributor

Validark commented Nov 3, 2024

Zig Version

0.14.0-dev.2097+d30e28754

Steps to Reproduce and Observed Behavior

This code: Godbolt link

const Pack = packed struct
{
    field1: bool,
    field2: bool,
    field3: bool,
};

export fn init(pack: *Pack) void {
    pack.field1 = true;
    pack.field2 = false;
    pack.field3 = true;
}

export fn init2(pack: *Pack) void {
    pack.* = .{
        .field1 = true,
        .field2 = false,
        .field3 = true,
    };
}

Results in this assembly for x86-64:

init:
        movzx   eax, byte ptr [rdi]
        and     al, -8
        or      al, 5
        mov     byte ptr [rdi], al
        ret

init2:
        mov     byte ptr [rdi], 5
        ret

Running this command: zig build-obj ./src/llvm_code.zig -O ReleaseFast -target x86_64-linux -mcpu znver4 --verbose-llvm-ir -fstrip >llvm_code.ll 2>&1 sheds a little light on the situation:

define dso_local void @init(ptr align 1 nonnull %0) #0 {
1:
  %2 = alloca [8 x i8], align 8
  %3 = alloca [8 x i8], align 8
  %4 = alloca [8 x i8], align 8
  store ptr %0, ptr %4, align 8
  %5 = load ptr, ptr %4, align 8
  %6 = load i8, ptr %5, align 1
  %7 = zext i1 true to i8
  %8 = shl i8 %7, 0
  %9 = xor i8 %8, -1
  %10 = and i8 %6, %9
  %11 = zext i1 true to i8
  %12 = shl i8 %11, 0
  %13 = or i8 %12, %10
  store i8 %13, ptr %5, align 1
  store ptr %0, ptr %3, align 8
  %14 = load ptr, ptr %3, align 8
  %15 = load i8, ptr %14, align 1
  %16 = zext i1 true to i8
  %17 = shl i8 %16, 1
  %18 = xor i8 %17, -1
  %19 = and i8 %15, %18
  %20 = zext i1 false to i8
  %21 = shl i8 %20, 1
  %22 = or i8 %21, %19
  store i8 %22, ptr %14, align 1
  store ptr %0, ptr %2, align 8
  %23 = load ptr, ptr %2, align 8
  %24 = load i8, ptr %23, align 1
  %25 = zext i1 true to i8
  %26 = shl i8 %25, 2
  %27 = xor i8 %26, -1
  %28 = and i8 %24, %27
  %29 = zext i1 true to i8
  %30 = shl i8 %29, 2
  %31 = or i8 %30, %28
  store i8 %31, ptr %23, align 1
  ret void
}

; Function Attrs: nounwind uwtable nosanitize_coverage skipprofile
define dso_local void @init2(ptr align 1 nonnull %0) #0 {
1:
  store i3 -3, ptr %0, align 1
  ret void
}

This Godbolt link shows that if we change the i8's to i3's in the LLVM IR of @init we can get the optimization we want out of LLVM. I did not verify that this makes 100% sense to do, but potentially this issue can be solved by using operations on i3's rather than i8's.

Expected Behavior

Both functions should compile down to mov byte ptr [rdi], 5

@Validark Validark added the bug Observed behavior contradicts documented or intended behavior label Nov 3, 2024
@Validark
Copy link
Contributor Author

Validark commented Nov 3, 2024

Potentially relevant considerations:

#14200
#17391

"When loading a value of a type like i20 with a size that is not an integral number of bytes, the result is undefined if the value was not originally written using a store of the same type."

@scheibo
Copy link
Contributor

scheibo commented Nov 4, 2024

FWIW this is what I suspect is the bulk of the regression reported in #17768

@andrewrk andrewrk added backend-llvm The LLVM backend outputs an LLVM IR Module. optimization and removed bug Observed behavior contradicts documented or intended behavior labels Nov 4, 2024
@andrewrk andrewrk added this to the 0.14.0 milestone Nov 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend-llvm The LLVM backend outputs an LLVM IR Module. optimization
Projects
None yet
Development

No branches or pull requests

3 participants