stage2: lower float negation explicitly

Rather than lowering float negation as `0.0 - x`.

 * Add AIR instruction for float negation.
 * Add compiler-rt functions for f128, f80 negation

closes #11853
This commit is contained in:
Andrew Kelley
2022-06-30 00:02:00 -07:00
parent 54454fd010
commit 6bc6e47b15
25 changed files with 237 additions and 57 deletions

View File

@@ -1755,6 +1755,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_"),
.neg => try airNeg(f, inst),
.sqrt,
.sin,
.cos,
@@ -4098,6 +4100,20 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
return local;
}
fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.liveness.isUnused(inst)) return CValue.none;
const un_op = f.air.instructions.items(.data)[inst].un_op;
const writer = f.object.writer();
const inst_ty = f.air.typeOfIndex(inst);
const operand = try f.resolveInst(un_op);
const local = try f.allocLocal(inst_ty, .Const);
try writer.writeAll("-");
try f.writeCValue(writer, operand);
try writer.writeAll(";\n");
return local;
}
fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.liveness.isUnused(inst)) return CValue.none;
const pl_op = f.air.instructions.items(.data)[inst].pl_op;

View File

@@ -4019,6 +4019,7 @@ 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),
@@ -6545,13 +6546,14 @@ pub const FuncGen = struct {
fabs,
floor,
fma,
fmax,
fmin,
fmod,
log,
log10,
log2,
fmax,
fmin,
mul,
fmod,
neg,
round,
sin,
sqrt,
@@ -6584,6 +6586,7 @@ pub const FuncGen = struct {
var fn_name_buf: [64]u8 = undefined;
const strat: FloatOpStrat = if (intrinsics_allowed) switch (op) {
// Some operations are dedicated LLVM instructions, not available as intrinsics
.neg => return self.builder.buildFNeg(params[0], ""),
.add => return self.builder.buildFAdd(params[0], params[1], ""),
.sub => return self.builder.buildFSub(params[0], params[1], ""),
.mul => return self.builder.buildFMul(params[0], params[1], ""),
@@ -6595,6 +6598,11 @@ pub const FuncGen = struct {
} else b: {
const float_bits = scalar_ty.floatBits(target);
break :b switch (op) {
.neg => FloatOpStrat{
.libc = std.fmt.bufPrintZ(&fn_name_buf, "__neg{s}f2", .{
compilerRtFloatAbbrev(float_bits),
}) catch unreachable,
},
.add, .sub, .div, .mul => FloatOpStrat{
.libc = std.fmt.bufPrintZ(&fn_name_buf, "__{s}{s}f3", .{
@tagName(op), compilerRtFloatAbbrev(float_bits),

View File

@@ -549,6 +549,9 @@ pub const Builder = opaque {
pub const buildFSub = LLVMBuildFSub;
extern fn LLVMBuildFSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
pub const buildFNeg = LLVMBuildFNeg;
extern fn LLVMBuildFNeg(*const Builder, V: *const Value, Name: [*:0]const u8) *const Value;
pub const buildSub = LLVMBuildSub;
extern fn LLVMBuildSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;