| ... | @@ -1071,68 +1071,61 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1071,68 +1071,61 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void { |
| 1071 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1071 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1072 | } | 1072 | } |
| 1073 | | 1073 | |
| 1074 | fn airPtrAdd(self: *Self, inst: Air.Inst.Index) !void { | 1074 | fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue { |
| 1075 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | | |
| 1076 | if (self.liveness.isUnused(inst)) { | | |
| 1077 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); | | |
| 1078 | } | | |
| 1079 | | | |
| 1080 | const mcvs = try self.mcvsForBinMathOp(inst, bin_op.lhs, bin_op.rhs); | | |
| 1081 | var dst_mcv = mcvs.dst; | | |
| 1082 | const src_mcv = mcvs.src; | | |
| 1083 | | | |
| 1084 | // TODO clean this up | | |
| 1085 | // TODO take into account alignment | | |
| 1086 | const dst_ty = self.air.typeOfIndex(inst); | 1075 | const dst_ty = self.air.typeOfIndex(inst); |
| 1087 | const elem_size = dst_ty.elemType2().abiSize(self.target.*); | 1076 | const elem_size = dst_ty.elemType2().abiSize(self.target.*); |
| 1088 | const dst_reg = blk: { | 1077 | const ptr = try self.resolveInst(op_lhs); |
| 1089 | switch (dst_mcv) { | 1078 | const offset = try self.resolveInst(op_rhs); |
| 1090 | .register => |reg| break :blk reg, | 1079 | const offset_ty = self.air.typeOf(op_rhs); |
| 1091 | else => { | 1080 | |
| 1092 | src_mcv.freezeIfRegister(&self.register_manager); | 1081 | ptr.freezeIfRegister(&self.register_manager); |
| 1093 | defer src_mcv.freezeIfRegister(&self.register_manager); | 1082 | defer ptr.unfreezeIfRegister(&self.register_manager); |
| 1094 | const reg = try self.copyToTmpRegister(dst_ty, dst_mcv); | 1083 | |
| 1095 | break :blk reg; | 1084 | offset.freezeIfRegister(&self.register_manager); |
| 1096 | }, | 1085 | defer offset.unfreezeIfRegister(&self.register_manager); |
| | 1086 | |
| | 1087 | const dst_mcv = blk: { |
| | 1088 | if (self.reuseOperand(inst, op_lhs, 0, ptr)) { |
| | 1089 | if (ptr.isMemory() or ptr.isRegister()) break :blk ptr; |
| 1097 | } | 1090 | } |
| | 1091 | break :blk try self.copyToNewRegister(inst, dst_ty, ptr); |
| 1098 | }; | 1092 | }; |
| 1099 | try self.genIMulOpMir(dst_ty, .{ .register = dst_reg }, .{ .immediate = elem_size }); | | |
| 1100 | dst_mcv = .{ .register = dst_reg }; | | |
| 1101 | try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv); | | |
| 1102 | | 1093 | |
| 1103 | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); | 1094 | const offset_mcv = blk: { |
| 1104 | } | 1095 | if (self.reuseOperand(inst, op_rhs, 1, offset)) { |
| | 1096 | if (offset.isRegister()) break :blk offset; |
| | 1097 | } |
| | 1098 | break :blk MCValue{ .register = try self.copyToTmpRegister(offset_ty, offset) }; |
| | 1099 | }; |
| 1105 | | 1100 | |
| 1106 | fn airPtrSub(self: *Self, inst: Air.Inst.Index) !void { | 1101 | try self.genIMulOpMir(offset_ty, offset_mcv, .{ .immediate = elem_size }); |
| 1107 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1102 | |
| 1108 | if (self.liveness.isUnused(inst)) { | 1103 | const tag = self.air.instructions.items(.tag)[inst]; |
| 1109 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); | 1104 | switch (tag) { |
| | 1105 | .ptr_add => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, offset_mcv), |
| | 1106 | .ptr_sub => try self.genBinMathOpMir(.sub, dst_ty, dst_mcv, offset_mcv), |
| | 1107 | else => unreachable, |
| 1110 | } | 1108 | } |
| 1111 | | 1109 | |
| 1112 | const mcvs = try self.mcvsForBinMathOp(inst, bin_op.lhs, bin_op.rhs); | 1110 | return dst_mcv; |
| 1113 | var dst_mcv = mcvs.dst; | 1111 | } |
| 1114 | const src_mcv = mcvs.src; | | |
| 1115 | | 1112 | |
| 1116 | // TODO clean this up | 1113 | fn airPtrAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 1117 | // TODO take into account alignment | 1114 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1118 | const dst_ty = self.air.typeOfIndex(inst); | 1115 | const result = if (self.liveness.isUnused(inst)) |
| 1119 | const elem_size = dst_ty.elemType2().abiSize(self.target.*); | 1116 | .dead |
| 1120 | const dst_reg = blk: { | 1117 | else |
| 1121 | switch (dst_mcv) { | 1118 | try self.genPtrBinMathOp(inst, bin_op.lhs, bin_op.rhs); |
| 1122 | .register => |reg| break :blk reg, | 1119 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1123 | else => { | 1120 | } |
| 1124 | src_mcv.freezeIfRegister(&self.register_manager); | | |
| 1125 | defer src_mcv.freezeIfRegister(&self.register_manager); | | |
| 1126 | const reg = try self.copyToTmpRegister(dst_ty, dst_mcv); | | |
| 1127 | break :blk reg; | | |
| 1128 | }, | | |
| 1129 | } | | |
| 1130 | }; | | |
| 1131 | try self.genIMulOpMir(dst_ty, .{ .register = dst_reg }, .{ .immediate = elem_size }); | | |
| 1132 | dst_mcv = .{ .register = dst_reg }; | | |
| 1133 | try self.genBinMathOpMir(.sub, dst_ty, dst_mcv, src_mcv); | | |
| 1134 | | 1121 | |
| 1135 | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); | 1122 | fn airPtrSub(self: *Self, inst: Air.Inst.Index) !void { |
| | 1123 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 1124 | const result = if (self.liveness.isUnused(inst)) |
| | 1125 | .dead |
| | 1126 | else |
| | 1127 | try self.genPtrBinMathOp(inst, bin_op.lhs, bin_op.rhs); |
| | 1128 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1136 | } | 1129 | } |
| 1137 | | 1130 | |
| 1138 | fn airSlice(self: *Self, inst: Air.Inst.Index) !void { | 1131 | fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| ... | @@ -2178,17 +2171,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2178,17 +2171,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2178 | return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); | 2171 | return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); |
| 2179 | } | 2172 | } |
| 2180 | | 2173 | |
| 2181 | const BinMathOpMCValuePair = struct { | 2174 | /// Perform "binary" operators, excluding comparisons. |
| 2182 | dst: MCValue, | 2175 | /// Currently, the following ops are supported: |
| 2183 | src: MCValue, | 2176 | /// ADD, SUB, XOR, OR, AND |
| 2184 | }; | 2177 | fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue { |
| 2185 | | | |
| 2186 | fn mcvsForBinMathOp( | | |
| 2187 | self: *Self, | | |
| 2188 | inst: Air.Inst.Index, | | |
| 2189 | op_lhs: Air.Inst.Ref, | | |
| 2190 | op_rhs: Air.Inst.Ref, | | |
| 2191 | ) !BinMathOpMCValuePair { | | |
| 2192 | // TODO: make this algorithm less bad | 2178 | // TODO: make this algorithm less bad |
| 2193 | const lhs = try self.resolveInst(op_lhs); | 2179 | const lhs = try self.resolveInst(op_lhs); |
| 2194 | const rhs = try self.resolveInst(op_rhs); | 2180 | const rhs = try self.resolveInst(op_rhs); |
| ... | @@ -2201,6 +2187,7 @@ fn mcvsForBinMathOp( | ... | @@ -2201,6 +2187,7 @@ fn mcvsForBinMathOp( |
| 2201 | const dst_ty = self.air.typeOfIndex(inst); | 2187 | const dst_ty = self.air.typeOfIndex(inst); |
| 2202 | var dst_mcv: MCValue = undefined; | 2188 | var dst_mcv: MCValue = undefined; |
| 2203 | var src_mcv: MCValue = undefined; | 2189 | var src_mcv: MCValue = undefined; |
| | 2190 | |
| 2204 | if (self.reuseOperand(inst, op_lhs, 0, lhs)) { | 2191 | if (self.reuseOperand(inst, op_lhs, 0, lhs)) { |
| 2205 | // LHS dies; use it as the destination. | 2192 | // LHS dies; use it as the destination. |
| 2206 | // Both operands cannot be memory. | 2193 | // Both operands cannot be memory. |
| ... | @@ -2253,17 +2240,6 @@ fn mcvsForBinMathOp( | ... | @@ -2253,17 +2240,6 @@ fn mcvsForBinMathOp( |
| 2253 | else => {}, | 2240 | else => {}, |
| 2254 | } | 2241 | } |
| 2255 | | 2242 | |
| 2256 | return BinMathOpMCValuePair{ .dst = dst_mcv, .src = src_mcv }; | | |
| 2257 | } | | |
| 2258 | | | |
| 2259 | /// Perform "binary" operators, excluding comparisons. | | |
| 2260 | /// Currently, the following ops are supported: | | |
| 2261 | /// ADD, SUB, XOR, OR, AND | | |
| 2262 | fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue { | | |
| 2263 | const dst_ty = self.air.typeOfIndex(inst); | | |
| 2264 | const mcvs = try self.mcvsForBinMathOp(inst, op_lhs, op_rhs); | | |
| 2265 | const dst_mcv = mcvs.dst; | | |
| 2266 | const src_mcv = mcvs.src; | | |
| 2267 | const tag = self.air.instructions.items(.tag)[inst]; | 2243 | const tag = self.air.instructions.items(.tag)[inst]; |
| 2268 | switch (tag) { | 2244 | switch (tag) { |
| 2269 | .add, .addwrap => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv), | 2245 | .add, .addwrap => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv), |