authorgravatar for xtex@astrafall.orgxtex <xtex@astrafall.org> 2026-08-30 20:43:21+08:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-08-30 22:54:04+02:00
logc772fef715c2faec422fb68b69b912780d68762e
treeb75a2d6b9eb855c2e9c5ddfeeeab110e71370803
parent14bac1ffcf044c01362776cceb9ff8d381285fd4

loongarch: use movfr2gr for bit_cast only if values are stored in FPR

For f80 (and f64/f32 on platforms without FP support), values should be stored in GPRs or stacks. Therefore, movfr2gr and movgr2fr should not be used.

2 files changed, 31 insertions(+), 5 deletions(-)

src/codegen/loongarch/Select.zig+30-4
......@@ -3758,12 +3758,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
37583758 } else if (dst_tag == .float and src_tag == .float) {
37593759 assert(dst_ty.floatBits(isel.target) == src_ty.floatBits(isel.target));
37603760 try dst_vi.value.defMove(isel, ty_op.operand);
3761 } else if (dst_ty.isAbiInt(zcu) and src_tag == .float) {
3761 } else if (dst_ty.isAbiInt(zcu) and src_tag == .float and isel.canUseFprForFloat(src_ty)) {
37623762 const dst_int_info = dst_ty.intInfo(zcu);
37633763 assert(dst_int_info.bits == src_ty.floatBits(isel.target));
37643764
37653765 try dst_vi.value.reextendToGarbage(isel);
3766 const dst_reg = try dst_vi.value.defRegMod(isel, .fromFloating(dst_int_info.bits)) orelse break :unused;
3766 const dst_reg = try dst_vi.value.defRegMod(isel, .fromFloatBits(dst_int_info.bits)) orelse break :unused;
37673767 const src_vi = try isel.use(ty_op.operand);
37683768 const src_mat = try src_vi.matReg(isel);
37693769 const src_reg = src_mat.reg();
......@@ -3773,12 +3773,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
37733773 64 => .@"movfr2gr.d"(dst_reg, src_reg),
37743774 });
37753775 try src_mat.finish(isel);
3776 } else if (dst_tag == .float and src_ty.isAbiInt(zcu)) {
3776 } else if (dst_tag == .float and src_ty.isAbiInt(zcu) and isel.canUseFprForFloat(dst_ty)) {
37773777 const src_int_info = src_ty.intInfo(zcu);
37783778 assert(dst_ty.floatBits(isel.target) == src_int_info.bits);
37793779
37803780 try dst_vi.value.reextendToGarbage(isel);
3781 const dst_reg = try dst_vi.value.defRegMod(isel, .fromFloating(src_int_info.bits)) orelse break :unused;
3781 const dst_reg = try dst_vi.value.defRegMod(isel, .fromFloatBits(src_int_info.bits)) orelse break :unused;
37823782 const src_vi = try isel.use(ty_op.operand);
37833783 const src_mat = try src_vi.matReg(isel);
37843784 const src_reg = src_mat.reg();
......@@ -7258,6 +7258,32 @@ fn gprAlignment(isel: *Select) std.mem.Alignment {
72587258 };
72597259}
72607260
7261fn fprBits(isel: *Select) u7 {
7262 const cpu = &isel.target.cpu;
7263 if (cpu.has(.loongarch, .d)) {
7264 return 64;
7265 } else if (cpu.has(.loongarch, .f)) {
7266 return 32;
7267 } else {
7268 return 0;
7269 }
7270}
7271
7272fn vectorBits(isel: *Select) u7 {
7273 const cpu = &isel.target.cpu;
7274 if (cpu.has(.loongarch, .lasx)) {
7275 return 256;
7276 } else if (cpu.has(.loongarch, .lsx)) {
7277 return 128;
7278 } else {
7279 return isel.fprBits();
7280 }
7281}
7282
7283fn canUseFprForFloat(isel: *Select, ty: ZigType) bool {
7284 return ty.floatBits(isel.target) <= isel.fprBits();
7285}
7286
72617287fn typeOfField(isel: *Select, ty: ZigType, offset: u64) ?ZigType {
72627288 const zcu = isel.pt.zcu;
72637289 const ip = &zcu.intern_pool;
src/codegen/loongarch/bits.zig+1-1
......@@ -85,7 +85,7 @@ pub const Register = enum(u7) {
8585 };
8686 }
8787
88 pub fn fromFloating(bits: u16) Modifier {
88 pub fn fromFloatBits(bits: u16) Modifier {
8989 return switch (bits) {
9090 else => unreachable,
9191 32 => .floating32,