| ... | @@ -4670,38 +4670,38 @@ fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! | ... | @@ -4670,38 +4670,38 @@ fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! |
| 4670 | // We have the following `Air.Legalize` features enabled: | 4670 | // We have the following `Air.Legalize` features enabled: |
| 4671 | // | 4671 | // |
| 4672 | // * `.scalarize_bit_cast_array` | 4672 | // * `.scalarize_bit_cast_array` |
| 4673 | // * `.scalarize_bit_cast_vector_non_elementwise` | 4673 | // * `.scalarize_bit_cast_vector_non_elementwise` (big-endian only) |
| 4674 | // | 4674 | // |
| 4675 | // That means the `bit_cast` instructions we might see are limited to the following: | 4675 | // That means that on big-endian, the `bit_cast` instructions we might see are limited to the following: |
| 4676 | // | 4676 | // |
| 4677 | // * bool/int/float <-> bool/int/float | 4677 | // * bool/int/float <-> bool/int/float |
| 4678 | // * `@Vector(n, A)` <-> `@Vector(n, B)` | 4678 | // * `@Vector(n, A)` <-> `@Vector(n, B)` |
| 4679 | // | 4679 | // |
| 4680 | // Most of these cases can be handled by LLVM's `bitcast` instruction, except when | 4680 | // While on little-endian, the `bit_cast` instructions we might see can be any of the following: |
| 4681 | // a non-native type like `f80` is used. | 4681 | // |
| | 4682 | // * bool/int/float/`@Vector(n, A)` <-> bool/int/float/`@Vector(m, B)` |
| 4682 | | 4683 | |
| 4683 | if (isByRef(operand_ty, zcu)) { | 4684 | if (isByRef(operand_ty, zcu)) { |
| 4684 | const operand_scalar_ty = operand_ty.scalarType(zcu); | 4685 | const operand_scalar_ty = operand_ty.scalarType(zcu); |
| 4685 | const target = zcu.getTarget(); | 4686 | const target = zcu.getTarget(); |
| 4686 | const bits = operand_scalar_ty.floatBits(target); | 4687 | const scalar_bits = operand_scalar_ty.floatBits(target); |
| 4687 | const dest_scalar_ty = dest_ty.scalarType(zcu); | | |
| 4688 | if (isByRef(dest_ty, zcu)) { | 4688 | if (isByRef(dest_ty, zcu)) { |
| 4689 | assert(dest_scalar_ty.floatBits(target) == bits); | 4689 | const dest_scalar_ty = dest_ty.scalarType(zcu); |
| 4690 | return operand; | 4690 | // Converting between equivalent floats with the same repr. |
| | 4691 | if (dest_scalar_ty.floatBits(target) == scalar_bits) return operand; |
| 4691 | } | 4692 | } |
| 4692 | assert(dest_scalar_ty.intInfo(zcu).bits == bits); | | |
| 4693 | | 4693 | |
| 4694 | const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern()) | 4694 | const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern()) |
| 4695 | operand_ty.vectorLen(zcu) | 4695 | operand_ty.vectorLen(zcu) |
| 4696 | else | 4696 | else |
| 4697 | null; | 4697 | null; |
| 4698 | const operand_scalar_size = operand_scalar_ty.abiSize(zcu); | 4698 | const operand_scalar_size = operand_scalar_ty.abiSize(zcu); |
| 4699 | var result = if (len) |_| | 4699 | var result = if (len) |l| |
| 4700 | try o.builder.poisonValue(try o.lowerType(dest_ty, .as_value)) | 4700 | try o.builder.poisonValue(try o.builder.vectorType(.normal, l, try o.intType(scalar_bits, .as_value))) |
| 4701 | else | 4701 | else |
| 4702 | undefined; | 4702 | undefined; |
| 4703 | for (0..len orelse 1) |index| { | 4703 | for (0..len orelse 1) |index| { |
| 4704 | const result_elem = result_elem: switch (bits) { | 4704 | const result_elem = result_elem: switch (scalar_bits) { |
| 4705 | else => unreachable, | 4705 | else => unreachable, |
| 4706 | 80 => { | 4706 | 80 => { |
| 4707 | const f80_layout = o.softF80Layout(.{}) catch unreachable; | 4707 | const f80_layout = o.softF80Layout(.{}) catch unreachable; |
| ... | @@ -4747,28 +4747,30 @@ fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! | ... | @@ -4747,28 +4747,30 @@ fn airBitCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! |
| 4747 | else | 4747 | else |
| 4748 | result_elem; | 4748 | result_elem; |
| 4749 | } | 4749 | } |
| 4750 | return result; | 4750 | return fg.wip.cast(.bitcast, result, try o.lowerType(dest_ty, .as_value), ""); |
| 4751 | } | 4751 | } |
| 4752 | | 4752 | |
| 4753 | if (isByRef(dest_ty, zcu)) { | 4753 | if (isByRef(dest_ty, zcu)) { |
| 4754 | const dest_scalar_ty = dest_ty.scalarType(zcu); | 4754 | const dest_scalar_ty = dest_ty.scalarType(zcu); |
| 4755 | const bits = dest_scalar_ty.floatBits(zcu.getTarget()); | 4755 | const scalar_bits = dest_scalar_ty.floatBits(zcu.getTarget()); |
| 4756 | assert(dest_scalar_ty.isRuntimeFloat()); | | |
| 4757 | const operand_scalar_ty = operand_ty.scalarType(zcu); | | |
| 4758 | assert(operand_scalar_ty.intInfo(zcu).bits == bits); | | |
| 4759 | | 4756 | |
| 4760 | const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern()) | 4757 | const len = if (dest_ty.toIntern() != dest_scalar_ty.toIntern()) |
| 4761 | operand_ty.vectorLen(zcu) | 4758 | operand_ty.vectorLen(zcu) |
| 4762 | else | 4759 | else |
| 4763 | null; | 4760 | null; |
| 4764 | const operand_scalar_size = operand_scalar_ty.abiSize(zcu); | 4761 | const operand_scalar_int_ty = try o.intType(scalar_bits, .as_value); |
| | 4762 | const bitcasted_operand = try fg.wip.cast(.bitcast, operand, if (len) |l| |
| | 4763 | try o.builder.vectorType(.normal, l, operand_scalar_int_ty) |
| | 4764 | else |
| | 4765 | operand_scalar_int_ty, ""); |
| | 4766 | const operand_scalar_size = operand_ty.scalarType(zcu).abiSize(zcu); |
| 4765 | const result_ptr = try fg.buildZigAlloca(dest_ty, .none); | 4767 | const result_ptr = try fg.buildZigAlloca(dest_ty, .none); |
| 4766 | for (0..len orelse 1) |index| { | 4768 | for (0..len orelse 1) |index| { |
| 4767 | const operand_elem = if (len) |_| | 4769 | const operand_elem = if (len) |_| |
| 4768 | try fg.wip.extractElement(operand, try o.builder.intValue(.i32, index), "elementwise.operand_elem") | 4770 | try fg.wip.extractElement(bitcasted_operand, try o.builder.intValue(.i32, index), "elementwise.operand_elem") |
| 4769 | else | 4771 | else |
| 4770 | operand; | 4772 | bitcasted_operand; |
| 4771 | switch (bits) { | 4773 | switch (scalar_bits) { |
| 4772 | else => unreachable, | 4774 | else => unreachable, |
| 4773 | 80 => { | 4775 | 80 => { |
| 4774 | const f80_layout = o.softF80Layout(.{}) catch unreachable; | 4776 | const f80_layout = o.softF80Layout(.{}) catch unreachable; |