| ... | ... | @@ -1970,6 +1970,9 @@ const DeclGen = struct { |
| 1970 | 1970 | |
| 1971 | 1971 | .shl => try self.airShift(inst, .OpShiftLeftLogical), |
| 1972 | 1972 | |
| 1973 | .min => try self.airMinMax(inst, .lt), |
| 1974 | .max => try self.airMinMax(inst, .gt), |
| 1975 | |
| 1973 | 1976 | .bitcast => try self.airBitCast(inst), |
| 1974 | 1977 | .intcast, .trunc => try self.airIntCast(inst), |
| 1975 | 1978 | .int_from_ptr => try self.airIntFromPtr(inst), |
| ... | ... | @@ -2103,6 +2106,54 @@ const DeclGen = struct { |
| 2103 | 2106 | return result_id; |
| 2104 | 2107 | } |
| 2105 | 2108 | |
| 2109 | fn airMinMax(self: *DeclGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !?IdRef { |
| 2110 | if (self.liveness.isUnused(inst)) return null; |
| 2111 | |
| 2112 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2113 | const lhs_id = try self.resolve(bin_op.lhs); |
| 2114 | const rhs_id = try self.resolve(bin_op.rhs); |
| 2115 | const result_ty = self.typeOfIndex(inst); |
| 2116 | const result_ty_ref = try self.resolveType(result_ty, .direct); |
| 2117 | |
| 2118 | const info = try self.arithmeticTypeInfo(result_ty); |
| 2119 | // TODO: Use fmin for OpenCL |
| 2120 | const cmp_id = try self.cmp(op, result_ty, lhs_id, rhs_id); |
| 2121 | const selection_id = switch (info.class) { |
| 2122 | .float => blk: { |
| 2123 | // cmp uses OpFOrd. When we have 0 [<>] nan this returns false, |
| 2124 | // but we want it to pick lhs. Therefore we also have to check if |
| 2125 | // rhs is nan. We don't need to care about the result when both |
| 2126 | // are nan. |
| 2127 | const rhs_is_nan_id = self.spv.allocId(); |
| 2128 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); |
| 2129 | try self.func.body.emit(self.spv.gpa, .OpIsNan, .{ |
| 2130 | .id_result_type = self.typeId(bool_ty_ref), |
| 2131 | .id_result = rhs_is_nan_id, |
| 2132 | .x = rhs_id, |
| 2133 | }); |
| 2134 | const float_cmp_id = self.spv.allocId(); |
| 2135 | try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{ |
| 2136 | .id_result_type = self.typeId(bool_ty_ref), |
| 2137 | .id_result = float_cmp_id, |
| 2138 | .operand_1 = cmp_id, |
| 2139 | .operand_2 = rhs_is_nan_id, |
| 2140 | }); |
| 2141 | break :blk float_cmp_id; |
| 2142 | }, |
| 2143 | else => cmp_id, |
| 2144 | }; |
| 2145 | |
| 2146 | const result_id = self.spv.allocId(); |
| 2147 | try self.func.body.emit(self.spv.gpa, .OpSelect, .{ |
| 2148 | .id_result_type = self.typeId(result_ty_ref), |
| 2149 | .id_result = result_id, |
| 2150 | .condition = selection_id, |
| 2151 | .object_1 = lhs_id, |
| 2152 | .object_2 = rhs_id, |
| 2153 | }); |
| 2154 | return result_id; |
| 2155 | } |
| 2156 | |
| 2106 | 2157 | fn maskStrangeInt(self: *DeclGen, ty_ref: CacheRef, value_id: IdRef, bits: u16) !IdRef { |
| 2107 | 2158 | const mask_value = if (bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(bits))) - 1; |
| 2108 | 2159 | const result_id = self.spv.allocId(); |