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,...@@ -3758,12 +3758,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
3758 } else if (dst_tag == .float and src_tag == .float) {3758 } else if (dst_tag == .float and src_tag == .float) {
3759 assert(dst_ty.floatBits(isel.target) == src_ty.floatBits(isel.target));3759 assert(dst_ty.floatBits(isel.target) == src_ty.floatBits(isel.target));
3760 try dst_vi.value.defMove(isel, ty_op.operand);3760 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)) {
3762 const dst_int_info = dst_ty.intInfo(zcu);3762 const dst_int_info = dst_ty.intInfo(zcu);
3763 assert(dst_int_info.bits == src_ty.floatBits(isel.target));3763 assert(dst_int_info.bits == src_ty.floatBits(isel.target));
37643764
3765 try dst_vi.value.reextendToGarbage(isel);3765 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;
3767 const src_vi = try isel.use(ty_op.operand);3767 const src_vi = try isel.use(ty_op.operand);
3768 const src_mat = try src_vi.matReg(isel);3768 const src_mat = try src_vi.matReg(isel);
3769 const src_reg = src_mat.reg();3769 const src_reg = src_mat.reg();
...@@ -3773,12 +3773,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,...@@ -3773,12 +3773,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
3773 64 => .@"movfr2gr.d"(dst_reg, src_reg),3773 64 => .@"movfr2gr.d"(dst_reg, src_reg),
3774 });3774 });
3775 try src_mat.finish(isel);3775 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)) {
3777 const src_int_info = src_ty.intInfo(zcu);3777 const src_int_info = src_ty.intInfo(zcu);
3778 assert(dst_ty.floatBits(isel.target) == src_int_info.bits);3778 assert(dst_ty.floatBits(isel.target) == src_int_info.bits);
37793779
3780 try dst_vi.value.reextendToGarbage(isel);3780 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;
3782 const src_vi = try isel.use(ty_op.operand);3782 const src_vi = try isel.use(ty_op.operand);
3783 const src_mat = try src_vi.matReg(isel);3783 const src_mat = try src_vi.matReg(isel);
3784 const src_reg = src_mat.reg();3784 const src_reg = src_mat.reg();
...@@ -7258,6 +7258,32 @@ fn gprAlignment(isel: *Select) std.mem.Alignment {...@@ -7258,6 +7258,32 @@ fn gprAlignment(isel: *Select) std.mem.Alignment {
7258 };7258 };
7259}7259}
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
7261fn typeOfField(isel: *Select, ty: ZigType, offset: u64) ?ZigType {7287fn typeOfField(isel: *Select, ty: ZigType, offset: u64) ?ZigType {
7262 const zcu = isel.pt.zcu;7288 const zcu = isel.pt.zcu;
7263 const ip = &zcu.intern_pool;7289 const ip = &zcu.intern_pool;
src/codegen/loongarch/bits.zig+1-1
...@@ -85,7 +85,7 @@ pub const Register = enum(u7) {...@@ -85,7 +85,7 @@ pub const Register = enum(u7) {
85 };85 };
86 }86 }
8787
88 pub fn fromFloating(bits: u16) Modifier {88 pub fn fromFloatBits(bits: u16) Modifier {
89 return switch (bits) {89 return switch (bits) {
90 else => unreachable,90 else => unreachable,
91 32 => .floating32,91 32 => .floating32,