Closed
Description
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
}