From fb7060d3c2e8ce4d7de5560adf8ec4a26fc5f6e8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 30 Jan 2022 16:23:31 -0700 Subject: stage2: implement shl_exact and shr_exact These produce an undefined value when one bits are shifted out. New AIR instruction: shr_exact. --- src/codegen/c.zig | 2 +- src/codegen/llvm.zig | 20 +++++++++++++++----- src/codegen/llvm/bindings.zig | 6 ++++++ 3 files changed, 22 insertions(+), 6 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 5dc1f26a6b..299581cd48 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1470,7 +1470,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .bit_and => try airBinOp(f, inst, " & "), .bit_or => try airBinOp(f, inst, " | "), .xor => try airBinOp(f, inst, " ^ "), - .shr => try airBinOp(f, inst, " >> "), + .shr, .shr_exact => try airBinOp(f, inst, " >> "), .shl, .shl_exact => try airBinOp(f, inst, " << "), .not => try airNot (f, inst), diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index df64c0c912..81742d4866 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2047,7 +2047,8 @@ pub const FuncGen = struct { .bit_and, .bool_and => try self.airAnd(inst), .bit_or, .bool_or => try self.airOr(inst), .xor => try self.airXor(inst), - .shr => try self.airShr(inst), + .shr => try self.airShr(inst, false), + .shr_exact => try self.airShr(inst, true), .cmp_eq => try self.airCmp(inst, .eq), .cmp_gt => try self.airCmp(inst, .gt), @@ -3633,7 +3634,7 @@ pub const FuncGen = struct { return self.builder.buildUShlSat(lhs, casted_rhs, ""); } - fn airShr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !?*const llvm.Value { if (self.liveness.isUnused(inst)) return null; const bin_op = self.air.instructions.items(.data)[inst].bin_op; @@ -3645,11 +3646,20 @@ pub const FuncGen = struct { self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_type), "") else rhs; + const is_signed_int = self.air.typeOfIndex(inst).isSignedInt(); - if (self.air.typeOfIndex(inst).isSignedInt()) { - return self.builder.buildAShr(lhs, casted_rhs, ""); + if (is_exact) { + if (is_signed_int) { + return self.builder.buildAShrExact(lhs, casted_rhs, ""); + } else { + return self.builder.buildLShrExact(lhs, casted_rhs, ""); + } } else { - return self.builder.buildLShr(lhs, casted_rhs, ""); + if (is_signed_int) { + return self.builder.buildAShr(lhs, casted_rhs, ""); + } else { + return self.builder.buildLShr(lhs, casted_rhs, ""); + } } } diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 42c88d1351..fa285bd291 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -548,6 +548,12 @@ pub const Builder = opaque { pub const buildAShr = LLVMBuildAShr; extern fn LLVMBuildAShr(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value; + pub const buildLShrExact = ZigLLVMBuildLShrExact; + extern fn ZigLLVMBuildLShrExact(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value; + + pub const buildAShrExact = ZigLLVMBuildAShrExact; + extern fn ZigLLVMBuildAShrExact(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value; + pub const buildShl = LLVMBuildShl; extern fn LLVMBuildShl(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value; -- cgit v1.2.3