Skip to content

Small discriminants are causing bad code generation #10613

Closed
@alexcrichton

Description

@alexcrichton

This code

enum Test<T> {                    
    A(T), B                       
}                                 
struct Node {                     
    value: Test<int>,             
}                                 

#[inline(never)]                  
pub fn foo(n: &mut Node, v: int) {
  n.value = A(v);                 
}                                 

Will generate this IR under -O

define void @_ZN3foo19hbd6078a6918ab2b9as4v0.0E({ i64, %tydesc*, i8*, i8*, i8 }* nocapture readnone, %struct.Node* nocapture, i64) unnamed_addr #1 {
"function top level":                                                                                                                               
  %.sroa.2 = alloca [7 x i8], align 1                                                                                                               
  %.sroa.0.0.idx = getelementptr inbounds %struct.Node* %1, i64 0, i32 0, i32 0                                                                     
  store i8 0, i8* %.sroa.0.0.idx, align 8                                                                                                           
  %.sroa.2.0.idx = getelementptr inbounds %struct.Node* %1, i64 0, i32 0, i32 1, i64 0                                                              
  %.sroa.2.0.idx2 = getelementptr inbounds [7 x i8]* %.sroa.2, i64 0, i64 0                                                                         
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %.sroa.2.0.idx, i8* %.sroa.2.0.idx2, i64 7, i32 1, i1 false)                                             
  %.sroa.23.0.idx = getelementptr inbounds %struct.Node* %1, i64 0, i32 0, i32 2, i64 0                                                             
  store i64 %2, i64* %.sroa.23.0.idx, align 8                                                                                                       
  ret void                                                                                                                                          
}                                                                                                                                                   

Yes, that is a memcpy of length 7. I have no idea why this is getting generated, I'm trying to narrow down which pass is generating this, but that is absolutely awful code to generate for such a simple operation. I would expect this function to generate two stores, one of the discriminant and one of the value.

Now change the program to have #[repr(uint)] in front of the enum, and we get this code:

define void @_ZN3foo19hbd6078a6918ab2b9as4v0.0E({ i64, %tydesc*, i8*, i8*, i8 }* nocapture readnone, %struct.Node* nocapture, i64) unnamed_addr #0 {
"function top level":                                                                                                                               
  %.sroa.0.0.idx = getelementptr inbounds %struct.Node* %1, i64 0, i32 0, i32 0                                                                     
  store i64 0, i64* %.sroa.0.0.idx, align 8                                                                                                         
  %.sroa.2.0.idx2 = getelementptr inbounds %struct.Node* %1, i64 0, i32 0, i32 2, i64 0                                                             
  store i64 %2, i64* %.sroa.2.0.idx2, align 8                                                                                                       
  ret void                                                                                                                                          
}                                                                                                                                                   

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-codegenArea: Code generation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions