const Object = struct {
// At least two 64-bit fields are required to trigger this.
a: u64,
b: u64,
// First function lets compiler to decide passing self by copy or pointer.
fn func1(self: Object) void {
// Just to make use of all fields on self.
const sum = self.a + self.b;
// !!!!! Assembly before calling func2 uses fp register q0.
_ = self.func2(sum);
}
// Second function specifies passing self by pointer.
fn func2(self: *const Object, val: u64) u64 {
// Make use of self and the input val.
const result = val + self.a + self.b;
return result;
}
};
// Export to make linker discover it as bare metal entry point.
export fn main() void {
const obj = Object{
.a = 1,
.b = 2,
};
obj.func1();
}
Expected ARM FP registers Qn, Dn, Sn, Hn, Bn to be avoided when FP&SIMD features are excluded from the target CPU.
However I cannot claim that the presence of FP registers is defined by these features. For example in #16957, a neon instruction is used regardless of the feature specification. In my case only FP registers are used, not instructions. It could be the intended behavior after all, that excluding these features don't forbit the use of FP registers in non-FP instructions.
Zig Version
0.13.0
Steps to Reproduce and Observed Behavior
Code generated for aarch64-freestanding-none uses the FP register Q0 when neon, fullfp16 and fp_armv8 are disabled.
Build command:
Example code:
Assembly before the call to func2 uses q0:
The use of FP register might have originated from llvm memcpy
Expected Behavior
Expected ARM FP registers Qn, Dn, Sn, Hn, Bn to be avoided when FP&SIMD features are excluded from the target CPU.
However I cannot claim that the presence of FP registers is defined by these features. For example in #16957, a neon instruction is used regardless of the feature specification. In my case only FP registers are used, not instructions. It could be the intended behavior after all, that excluding these features don't forbit the use of FP registers in non-FP instructions.