aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-07-21 14:40:00 +0300
committerVeikka Tuominen <git@vexu.eu>2022-07-23 15:40:12 +0300
commitd75fa86d7084bd41f68d1cd03763bd7cf2a87052 (patch)
treeb454c3e13d627220cdff9a9245849a6ffd57aaa5 /src/codegen
parent585c160c2022d71197a3ce1399818372371c23a4 (diff)
downloadzig-d75fa86d7084bd41f68d1cd03763bd7cf2a87052.tar.gz
zig-d75fa86d7084bd41f68d1cd03763bd7cf2a87052.zip
stage2: implement `@setFloatMode`
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig24
-rw-r--r--src/codegen/llvm.zig135
-rw-r--r--src/codegen/llvm/bindings.zig3
3 files changed, 122 insertions, 40 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 98f7792a76..280b7604bf 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1928,6 +1928,30 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.wasm_memory_size => try airWasmMemorySize(f, inst),
.wasm_memory_grow => try airWasmMemoryGrow(f, inst),
+
+ .add_optimized,
+ .addwrap_optimized,
+ .sub_optimized,
+ .subwrap_optimized,
+ .mul_optimized,
+ .mulwrap_optimized,
+ .div_float_optimized,
+ .div_trunc_optimized,
+ .div_floor_optimized,
+ .div_exact_optimized,
+ .rem_optimized,
+ .mod_optimized,
+ .neg_optimized,
+ .cmp_lt_optimized,
+ .cmp_lte_optimized,
+ .cmp_eq_optimized,
+ .cmp_gte_optimized,
+ .cmp_gt_optimized,
+ .cmp_neq_optimized,
+ .cmp_vector_optimized,
+ .reduce_optimized,
+ .float_to_int_optimized,
+ => return f.fail("TODO implement optimized float mode", .{}),
// zig fmt: on
};
switch (result_value) {
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 063e2ee0a2..de132132b0 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -3984,21 +3984,21 @@ pub const FuncGen = struct {
for (body) |inst, i| {
const opt_value: ?*const llvm.Value = switch (air_tags[inst]) {
// zig fmt: off
- .add => try self.airAdd(inst),
- .addwrap => try self.airAddWrap(inst),
+ .add => try self.airAdd(inst, false),
+ .addwrap => try self.airAddWrap(inst, false),
.add_sat => try self.airAddSat(inst),
- .sub => try self.airSub(inst),
- .subwrap => try self.airSubWrap(inst),
+ .sub => try self.airSub(inst, false),
+ .subwrap => try self.airSubWrap(inst, false),
.sub_sat => try self.airSubSat(inst),
- .mul => try self.airMul(inst),
- .mulwrap => try self.airMulWrap(inst),
+ .mul => try self.airMul(inst, false),
+ .mulwrap => try self.airMulWrap(inst, false),
.mul_sat => try self.airMulSat(inst),
- .div_float => try self.airDivFloat(inst),
- .div_trunc => try self.airDivTrunc(inst),
- .div_floor => try self.airDivFloor(inst),
- .div_exact => try self.airDivExact(inst),
- .rem => try self.airRem(inst),
- .mod => try self.airMod(inst),
+ .div_float => try self.airDivFloat(inst, false),
+ .div_trunc => try self.airDivTrunc(inst, false),
+ .div_floor => try self.airDivFloor(inst, false),
+ .div_exact => try self.airDivExact(inst, false),
+ .rem => try self.airRem(inst, false),
+ .mod => try self.airMod(inst, false),
.ptr_add => try self.airPtrAdd(inst),
.ptr_sub => try self.airPtrSub(inst),
.shl => try self.airShl(inst),
@@ -4009,6 +4009,19 @@ pub const FuncGen = struct {
.slice => try self.airSlice(inst),
.mul_add => try self.airMulAdd(inst),
+ .add_optimized => try self.airAdd(inst, true),
+ .addwrap_optimized => try self.airAddWrap(inst, true),
+ .sub_optimized => try self.airSub(inst, true),
+ .subwrap_optimized => try self.airSubWrap(inst, true),
+ .mul_optimized => try self.airMul(inst, true),
+ .mulwrap_optimized => try self.airMulWrap(inst, true),
+ .div_float_optimized => try self.airDivFloat(inst, true),
+ .div_trunc_optimized => try self.airDivTrunc(inst, true),
+ .div_floor_optimized => try self.airDivFloor(inst, true),
+ .div_exact_optimized => try self.airDivExact(inst, true),
+ .rem_optimized => try self.airRem(inst, true),
+ .mod_optimized => try self.airMod(inst, true),
+
.add_with_overflow => try self.airOverflow(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"),
.sub_with_overflow => try self.airOverflow(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"),
.mul_with_overflow => try self.airOverflow(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"),
@@ -4034,17 +4047,27 @@ pub const FuncGen = struct {
.ceil => try self.airUnaryOp(inst, .ceil),
.round => try self.airUnaryOp(inst, .round),
.trunc_float => try self.airUnaryOp(inst, .trunc),
- .neg => try self.airUnaryOp(inst, .neg),
-
- .cmp_eq => try self.airCmp(inst, .eq),
- .cmp_gt => try self.airCmp(inst, .gt),
- .cmp_gte => try self.airCmp(inst, .gte),
- .cmp_lt => try self.airCmp(inst, .lt),
- .cmp_lte => try self.airCmp(inst, .lte),
- .cmp_neq => try self.airCmp(inst, .neq),
- .cmp_vector => try self.airCmpVector(inst),
- .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
+ .neg => try self.airNeg(inst, false),
+ .neg_optimized => try self.airNeg(inst, true),
+
+ .cmp_eq => try self.airCmp(inst, .eq, false),
+ .cmp_gt => try self.airCmp(inst, .gt, false),
+ .cmp_gte => try self.airCmp(inst, .gte, false),
+ .cmp_lt => try self.airCmp(inst, .lt, false),
+ .cmp_lte => try self.airCmp(inst, .lte, false),
+ .cmp_neq => try self.airCmp(inst, .neq, false),
+
+ .cmp_eq_optimized => try self.airCmp(inst, .eq, true),
+ .cmp_gt_optimized => try self.airCmp(inst, .gt, true),
+ .cmp_gte_optimized => try self.airCmp(inst, .gte, true),
+ .cmp_lt_optimized => try self.airCmp(inst, .lt, true),
+ .cmp_lte_optimized => try self.airCmp(inst, .lte, true),
+ .cmp_neq_optimized => try self.airCmp(inst, .neq, true),
+
+ .cmp_vector => try self.airCmpVector(inst, false),
+ .cmp_vector_optimized => try self.airCmpVector(inst, true),
+ .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
.is_non_null => try self.airIsNonNull(inst, false, .NE),
.is_non_null_ptr => try self.airIsNonNull(inst, true , .NE),
@@ -4093,8 +4116,10 @@ pub const FuncGen = struct {
.ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),
.ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1),
+ .float_to_int => try self.airFloatToInt(inst, false),
+ .float_to_int_optimized => try self.airFloatToInt(inst, true),
+
.array_to_slice => try self.airArrayToSlice(inst),
- .float_to_int => try self.airFloatToInt(inst),
.int_to_float => try self.airIntToFloat(inst),
.cmpxchg_weak => try self.airCmpxchg(inst, true),
.cmpxchg_strong => try self.airCmpxchg(inst, false),
@@ -4115,11 +4140,13 @@ pub const FuncGen = struct {
.splat => try self.airSplat(inst),
.select => try self.airSelect(inst),
.shuffle => try self.airShuffle(inst),
- .reduce => try self.airReduce(inst),
.aggregate_init => try self.airAggregateInit(inst),
.union_init => try self.airUnionInit(inst),
.prefetch => try self.airPrefetch(inst),
+ .reduce => try self.airReduce(inst, false),
+ .reduce_optimized => try self.airReduce(inst, true),
+
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
.atomic_store_release => try self.airAtomicStore(inst, .Release),
@@ -4485,8 +4512,9 @@ pub const FuncGen = struct {
return null;
}
- fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator) !?*const llvm.Value {
+ fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
@@ -4496,8 +4524,9 @@ pub const FuncGen = struct {
return self.cmp(lhs, rhs, operand_ty, op);
}
- fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
@@ -4943,10 +4972,12 @@ pub const FuncGen = struct {
return self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");
}
- fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst))
return null;
+ self.builder.setFastMath(want_fast_math);
+
const target = self.dg.module.getTarget();
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
@@ -6095,8 +6126,9 @@ pub const FuncGen = struct {
return self.builder.buildInsertValue(partial, len, 1, "");
}
- fn airAdd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
@@ -6109,8 +6141,9 @@ pub const FuncGen = struct {
return self.builder.buildNUWAdd(lhs, rhs, "");
}
- fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
@@ -6134,8 +6167,9 @@ pub const FuncGen = struct {
return self.builder.buildUAddSat(lhs, rhs, "");
}
- fn airSub(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
@@ -6148,8 +6182,9 @@ pub const FuncGen = struct {
return self.builder.buildNUWSub(lhs, rhs, "");
}
- fn airSubWrap(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airSubWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
@@ -6172,8 +6207,9 @@ pub const FuncGen = struct {
return self.builder.buildUSubSat(lhs, rhs, "");
}
- fn airMul(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
@@ -6186,8 +6222,9 @@ pub const FuncGen = struct {
return self.builder.buildNUWMul(lhs, rhs, "");
}
- fn airMulWrap(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airMulWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
@@ -6210,8 +6247,9 @@ pub const FuncGen = struct {
return self.builder.buildUMulFixSat(lhs, rhs, "");
}
- fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
@@ -6221,8 +6259,9 @@ pub const FuncGen = struct {
return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
}
- fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
@@ -6238,8 +6277,9 @@ pub const FuncGen = struct {
return self.builder.buildUDiv(lhs, rhs, "");
}
- fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
@@ -6270,8 +6310,9 @@ pub const FuncGen = struct {
return self.builder.buildUDiv(lhs, rhs, "");
}
- fn airDivExact(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
@@ -6284,8 +6325,9 @@ pub const FuncGen = struct {
return self.builder.buildExactUDiv(lhs, rhs, "");
}
- fn airRem(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
@@ -6298,8 +6340,9 @@ pub const FuncGen = struct {
return self.builder.buildURem(lhs, rhs, "");
}
- fn airMod(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const lhs = try self.resolveInst(bin_op.lhs);
@@ -7613,6 +7656,17 @@ pub const FuncGen = struct {
return self.buildFloatOp(op, operand_ty, 1, .{operand});
}
+ fn airNeg(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
+
+ const un_op = self.air.instructions.items(.data)[inst].un_op;
+ const operand = try self.resolveInst(un_op);
+ const operand_ty = self.air.typeOf(un_op);
+
+ return self.buildFloatOp(.neg, operand_ty, 1, .{operand});
+ }
+
fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
@@ -7927,8 +7981,9 @@ pub const FuncGen = struct {
return self.builder.buildShuffleVector(a, b, llvm_mask_value, "");
}
- fn airReduce(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
+ self.builder.setFastMath(want_fast_math);
const reduce = self.air.instructions.items(.data)[inst].reduce;
const operand = try self.resolveInst(reduce.operand);
diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig
index 6cd5e41b10..07408f12b9 100644
--- a/src/codegen/llvm/bindings.zig
+++ b/src/codegen/llvm/bindings.zig
@@ -941,6 +941,9 @@ pub const Builder = opaque {
pub const buildFPMulReduce = ZigLLVMBuildFPMulReduce;
extern fn ZigLLVMBuildFPMulReduce(B: *const Builder, Acc: *const Value, Val: *const Value) *const Value;
+
+ pub const setFastMath = ZigLLVMSetFastMath;
+ extern fn ZigLLVMSetFastMath(B: *const Builder, on_state: bool) void;
};
pub const MDString = opaque {