aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-02-07 18:52:57 -0500
committerGitHub <noreply@github.com>2022-02-07 18:52:57 -0500
commit9bbfbacae0707cf0712e4d6b227b17d097708c7e (patch)
treed61c60e53f167ecb3c5b24235f5fa30f01fd8c23 /src
parentdd49ed1c642d917af40bf4a0e03d013f40b3903b (diff)
parenta028488384c599aa997ba04bbd5ed98f2172630c (diff)
downloadzig-9bbfbacae0707cf0712e4d6b227b17d097708c7e.tar.gz
zig-9bbfbacae0707cf0712e4d6b227b17d097708c7e.zip
Merge pull request #10801 from schmee/stage2-sqrt
stage2: implement @sqrt for f{16,32,64}
Diffstat (limited to 'src')
-rw-r--r--src/Air.zig6
-rw-r--r--src/Liveness.zig1
-rw-r--r--src/Sema.zig53
-rw-r--r--src/arch/aarch64/CodeGen.zig11
-rw-r--r--src/arch/arm/CodeGen.zig11
-rw-r--r--src/arch/riscv64/CodeGen.zig11
-rw-r--r--src/arch/wasm/CodeGen.zig2
-rw-r--r--src/arch/x86_64/CodeGen.zig11
-rw-r--r--src/codegen/c.zig8
-rw-r--r--src/codegen/llvm.zig16
-rw-r--r--src/print_air.zig1
-rw-r--r--src/stage1/codegen.cpp2
-rw-r--r--src/value.zig32
13 files changed, 148 insertions, 17 deletions
diff --git a/src/Air.zig b/src/Air.zig
index 14f8f96d38..6888f51963 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -237,6 +237,10 @@ pub const Inst = struct {
/// Uses the `ty_op` field.
popcount,
+ /// Computes the square root of a floating point number.
+ /// Uses the `un_op` field.
+ sqrt,
+
/// `<`. Result type is always bool.
/// Uses the `bin_op` field.
cmp_lt,
@@ -749,6 +753,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.max,
=> return air.typeOf(datas[inst].bin_op.lhs),
+ .sqrt => return air.typeOf(datas[inst].un_op),
+
.cmp_lt,
.cmp_lte,
.cmp_eq,
diff --git a/src/Liveness.zig b/src/Liveness.zig
index f07e438246..bed7de1507 100644
--- a/src/Liveness.zig
+++ b/src/Liveness.zig
@@ -338,6 +338,7 @@ fn analyzeInst(
.ret_load,
.tag_name,
.error_name,
+ .sqrt,
=> {
const operand = inst_datas[inst].un_op;
return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none });
diff --git a/src/Sema.zig b/src/Sema.zig
index 1dba136a48..72dfb4420b 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -745,19 +745,19 @@ fn analyzeBodyInner(
.clz => try sema.zirClzCtz(block, inst, .clz, Value.clz),
.ctz => try sema.zirClzCtz(block, inst, .ctz, Value.ctz),
- .sqrt => try sema.zirUnaryMath(block, inst),
- .sin => try sema.zirUnaryMath(block, inst),
- .cos => try sema.zirUnaryMath(block, inst),
- .exp => try sema.zirUnaryMath(block, inst),
- .exp2 => try sema.zirUnaryMath(block, inst),
- .log => try sema.zirUnaryMath(block, inst),
- .log2 => try sema.zirUnaryMath(block, inst),
- .log10 => try sema.zirUnaryMath(block, inst),
- .fabs => try sema.zirUnaryMath(block, inst),
- .floor => try sema.zirUnaryMath(block, inst),
- .ceil => try sema.zirUnaryMath(block, inst),
- .trunc => try sema.zirUnaryMath(block, inst),
- .round => try sema.zirUnaryMath(block, inst),
+ .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt),
+ .sin => @panic("TODO"),
+ .cos => @panic("TODO"),
+ .exp => @panic("TODO"),
+ .exp2 => @panic("TODO"),
+ .log => @panic("TODO"),
+ .log2 => @panic("TODO"),
+ .log10 => @panic("TODO"),
+ .fabs => @panic("TODO"),
+ .floor => @panic("TODO"),
+ .ceil => @panic("TODO"),
+ .trunc => @panic("TODO"),
+ .round => @panic("TODO"),
.error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent),
.error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon),
@@ -11010,10 +11010,31 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
return block.addUnOp(.error_name, operand);
}
-fn zirUnaryMath(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
+fn zirUnaryMath(
+ sema: *Sema,
+ block: *Block,
+ inst: Zir.Inst.Index,
+ air_tag: Air.Inst.Tag,
+ eval: fn (Value, Type, Allocator, std.Target) Allocator.Error!Value,
+) CompileError!Air.Inst.Ref {
+ const tracy = trace(@src());
+ defer tracy.end();
+
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
- const src = inst_data.src();
- return sema.fail(block, src, "TODO: Sema.zirUnaryMath", .{});
+ const operand = sema.resolveInst(inst_data.operand);
+ const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
+ const operand_ty = sema.typeOf(operand);
+ try sema.checkFloatType(block, operand_src, operand_ty);
+
+ if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| {
+ if (operand_val.isUndef()) return sema.addConstUndef(operand_ty);
+ const target = sema.mod.getTarget();
+ const result_val = try eval(operand_val, operand_ty, sema.arena, target);
+ return sema.addConstant(operand_ty, result_val);
+ }
+
+ try sema.requireRuntimeBlock(block, operand_src);
+ return block.addUnOp(air_tag, operand);
}
fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig
index 6e8f88a2a7..d0413af02f 100644
--- a/src/arch/aarch64/CodeGen.zig
+++ b/src/arch/aarch64/CodeGen.zig
@@ -528,6 +528,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.max => try self.airMax(inst),
.slice => try self.airSlice(inst),
+ .sqrt => try self.airUnaryMath(inst),
+
.add_with_overflow => try self.airAddWithOverflow(inst),
.sub_with_overflow => try self.airSubWithOverflow(inst),
.mul_with_overflow => try self.airMulWithOverflow(inst),
@@ -1223,6 +1225,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
+fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {
+ const un_op = self.air.instructions.items(.data)[inst].un_op;
+ const result: MCValue = if (self.liveness.isUnused(inst))
+ .dead
+ else
+ return self.fail("TODO implement airUnaryMath for {}", .{self.target.cpu.arch});
+ return self.finishAir(inst, result, .{ un_op, .none, .none });
+}
+
fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
if (!self.liveness.operandDies(inst, op_index))
return false;
diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig
index 1859ce874f..fb473ef412 100644
--- a/src/arch/arm/CodeGen.zig
+++ b/src/arch/arm/CodeGen.zig
@@ -520,6 +520,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.max => try self.airMax(inst),
.slice => try self.airSlice(inst),
+ .sqrt => try self.airUnaryMath(inst),
+
.add_with_overflow => try self.airAddWithOverflow(inst),
.sub_with_overflow => try self.airSubWithOverflow(inst),
.mul_with_overflow => try self.airMulWithOverflow(inst),
@@ -1377,6 +1379,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
// return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
+fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {
+ const un_op = self.air.instructions.items(.data)[inst].un_op;
+ const result: MCValue = if (self.liveness.isUnused(inst))
+ .dead
+ else
+ return self.fail("TODO implement airUnaryMath for {}", .{self.target.cpu.arch});
+ return self.finishAir(inst, result, .{ un_op, .none, .none });
+}
+
fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
if (!self.liveness.operandDies(inst, op_index))
return false;
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig
index 612ff78bd6..ce5dc39bf8 100644
--- a/src/arch/riscv64/CodeGen.zig
+++ b/src/arch/riscv64/CodeGen.zig
@@ -507,6 +507,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.max => try self.airMax(inst),
.slice => try self.airSlice(inst),
+ .sqrt => try self.airUnaryMath(inst),
+
.add_with_overflow => try self.airAddWithOverflow(inst),
.sub_with_overflow => try self.airSubWithOverflow(inst),
.mul_with_overflow => try self.airMulWithOverflow(inst),
@@ -1166,6 +1168,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
+fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {
+ const un_op = self.air.instructions.items(.data)[inst].un_op;
+ const result: MCValue = if (self.liveness.isUnused(inst))
+ .dead
+ else
+ return self.fail("TODO implement airUnaryMath for {}", .{self.target.cpu.arch});
+ return self.finishAir(inst, result, .{ un_op, .none, .none });
+}
+
fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
if (!self.liveness.operandDies(inst, op_index))
return false;
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index 8e0ffac76b..b1e7a0d3a1 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -1681,6 +1681,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.unwrap_errunion_payload_ptr,
.unwrap_errunion_err_ptr,
+ .sqrt,
+
.ptr_slice_len_ptr,
.ptr_slice_ptr_ptr,
.int_to_float,
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index a60b8c78f0..10a6120556 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -599,6 +599,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.max => try self.airMax(inst),
.slice => try self.airSlice(inst),
+ .sqrt => try self.airUnaryMath(inst),
+
.add_with_overflow => try self.airAddWithOverflow(inst),
.sub_with_overflow => try self.airSubWithOverflow(inst),
.mul_with_overflow => try self.airMulWithOverflow(inst),
@@ -1578,6 +1580,15 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
+fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {
+ const un_op = self.air.instructions.items(.data)[inst].un_op;
+ const result: MCValue = if (self.liveness.isUnused(inst))
+ .dead
+ else
+ return self.fail("TODO implement airUnaryMath for {}", .{self.target.cpu.arch});
+ return self.finishAir(inst, result, .{ un_op, .none, .none });
+}
+
fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
if (!self.liveness.operandDies(inst, op_index))
return false;
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 44b904f031..fc3848df21 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1446,6 +1446,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.mul_sat => try airSatOp(f, inst, "muls_"),
.shl_sat => try airSatOp(f, inst, "shls_"),
+ .sqrt => try airSqrt(f, inst),
+
.add_with_overflow => try airAddWithOverflow(f, inst),
.sub_with_overflow => try airSubWithOverflow(f, inst),
.mul_with_overflow => try airMulWithOverflow(f, inst),
@@ -3393,6 +3395,12 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
return CValue.none;
}
+fn airSqrt(f: *Function, inst: Air.Inst.Index) !CValue {
+ _ = f;
+ _ = inst;
+ return f.fail("TODO: C backend: implement sqrt", .{});
+}
+
fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
return switch (order) {
.Unordered => "memory_order_relaxed",
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index abf371c85b..5a2c21eece 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -2050,6 +2050,8 @@ pub const FuncGen = struct {
.shr => try self.airShr(inst, false),
.shr_exact => try self.airShr(inst, true),
+ .sqrt => try self.airSqrt(inst),
+
.cmp_eq => try self.airCmp(inst, .eq),
.cmp_gt => try self.airCmp(inst, .gt),
.cmp_gte => try self.airCmp(inst, .gte),
@@ -4211,6 +4213,20 @@ pub const FuncGen = struct {
}
}
+ fn airSqrt(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst)) return null;
+
+ 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);
+
+ const operand_llvm_ty = try self.dg.llvmType(operand_ty);
+ const fn_val = self.getIntrinsic("llvm.sqrt", &.{operand_llvm_ty});
+ const params = [_]*const llvm.Value{operand};
+
+ return self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
+ }
+
fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, prefix: [*:0]const u8) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
diff --git a/src/print_air.zig b/src/print_air.zig
index 6e1ed3f3d7..341e736b91 100644
--- a/src/print_air.zig
+++ b/src/print_air.zig
@@ -158,6 +158,7 @@ const Writer = struct {
.ret_load,
.tag_name,
.error_name,
+ .sqrt,
=> try w.writeUnOp(s, inst),
.breakpoint,
diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp
index 02f84beeab..c06f71e834 100644
--- a/src/stage1/codegen.cpp
+++ b/src/stage1/codegen.cpp
@@ -6996,7 +6996,7 @@ static LLVMValueRef ir_render_soft_f80_float_op(CodeGen *g, Stage1Air *executabl
const char *func_name;
switch (instruction->fn_id) {
case BuiltinFnIdSqrt:
- func_name = "__sqrt";
+ func_name = "__sqrtx";
break;
case BuiltinFnIdSin:
func_name = "__sinx";
diff --git a/src/value.zig b/src/value.zig
index cc6827b0cc..23a04f2e5a 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -3265,6 +3265,38 @@ pub const Value = extern union {
}
}
+ pub fn sqrt(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @sqrt(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @sqrt(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @sqrt(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt __sqrtx");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @sqrt(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt sqrtq");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @sqrt(f));
+ },
+ else => unreachable,
+ }
+ }
+
/// This type is not copyable since it may contain pointers to its inner data.
pub const Payload = struct {
tag: Tag,