Commit 1fdb24827f

Shawn Landden <shawn@git.icu>
2019-04-03 16:00:39
breaking changes to all bit manipulation intrinsics
* `@clz`, `@ctz`, `@popCount`, `@bswap`, `@bitreverse` now have a type parameter * rename @bitreverse to @bitReverse * rename @bswap to @byteSwap Closes #2119 Closes #2120
1 parent 56a905c
doc/langref.html.in
@@ -6239,8 +6239,8 @@ comptime {
 
       {#header_close#}
 
-      {#header_open|@bswap#}
-      <pre>{#syntax#}@bswap(comptime T: type, value: T) T{#endsyntax#}</pre>
+      {#header_open|@byteSwap#}
+      <pre>{#syntax#}@byteSwap(comptime T: type, integer: T) T{#endsyntax#}</pre>
       <p>{#syntax#}T{#endsyntax#} must be an integer type with bit count evenly divisible by 8.</p>
       <p>
       Swaps the byte order of the integer. This converts a big endian integer to a little endian integer,
@@ -6248,8 +6248,8 @@ comptime {
       </p>
       {#header_close#}
 
-      {#header_open|@bitreverse#}
-      <pre>{#syntax#}@bitreverse(comptime T: type, value: T) T{#endsyntax#}</pre>
+      {#header_open|@bitReverse#}
+      <pre>{#syntax#}@bitReverse(comptime T: type, integer: T) T{#endsyntax#}</pre>
       <p>{#syntax#}T{#endsyntax#} accepts any integer type.</p>
       <p>
       Reverses the bitpattern of an integer value, including the sign bit if applicable.
@@ -6337,14 +6337,15 @@ comptime {
       {#header_close#}
 
       {#header_open|@clz#}
-      <pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre>
+      <pre>{#syntax#}@clz(comptime T: type, integer: T) math.Log2Int(@intType(false, @typeInfo(T).Int.bits + 1)){#endsyntax#}</pre>
       <p>
       This function counts the number of leading zeroes in {#syntax#}x{#endsyntax#} which is an integer
           type {#syntax#}T{#endsyntax#}.
       </p>
       <p>
-      The return type {#syntax#}U{#endsyntax#} is an unsigned integer with the minimum number
-          of bits that can represent the value {#syntax#}T.bit_count{#endsyntax#}.
+      If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#}, the return type is {#syntax#}comptime_int{#endsyntax#}.
+      Otherwise, the return type is an unsigned integer with the minimum number
+      of bits that can represent the bit count of the integer type.
       </p>
       <p>
       If {#syntax#}x{#endsyntax#} is zero, {#syntax#}@clz{#endsyntax#} returns {#syntax#}T.bit_count{#endsyntax#}.
@@ -6477,14 +6478,15 @@ test "main" {
       {#header_close#}
 
       {#header_open|@ctz#}
-      <pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre>
+      <pre>{#syntax#}@ctz(comptime T: type, integer: T) math.Log2Int(@intType(false, @typeInfo(T).Int.bits + 1)){#endsyntax#}</pre>
       <p>
       This function counts the number of trailing zeroes in {#syntax#}x{#endsyntax#} which is an integer
           type {#syntax#}T{#endsyntax#}.
       </p>
       <p>
-      The return type {#syntax#}U{#endsyntax#} is an unsigned integer with the minimum number
-          of bits that can represent the value {#syntax#}T.bit_count{#endsyntax#}.
+      If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#}, the return type is {#syntax#}comptime_int{#endsyntax#}.
+      Otherwise, the return type is an unsigned integer with the minimum number
+      of bits that can represent the bit count of the integer type.
       </p>
       <p>
       If {#syntax#}x{#endsyntax#} is zero, {#syntax#}@ctz{#endsyntax#} returns {#syntax#}T.bit_count{#endsyntax#}.
@@ -7034,7 +7036,7 @@ test "call foo" {
       {#header_close#}
 
       {#header_open|@popCount#}
-      <pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre>
+      <pre>{#syntax#}@popCount(comptime T: type, integer: T) math.Log2Int(@intType(false, @typeInfo(T).Int.bits + 1)){#endsyntax#}</pre>
       <p>Counts the number of bits set in an integer.</p>
       <p>
       If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#}, the return type is {#syntax#}comptime_int{#endsyntax#}.
src/all_types.hpp
@@ -1407,6 +1407,8 @@ enum BuiltinFnId {
     BuiltinFnIdCtz,
     BuiltinFnIdClz,
     BuiltinFnIdPopCount,
+    BuiltinFnIdBswap,
+    BuiltinFnIdBitReverse,
     BuiltinFnIdImport,
     BuiltinFnIdCImport,
     BuiltinFnIdErrName,
@@ -1469,8 +1471,6 @@ enum BuiltinFnId {
     BuiltinFnIdErrorReturnTrace,
     BuiltinFnIdAtomicRmw,
     BuiltinFnIdAtomicLoad,
-    BuiltinFnIdBswap,
-    BuiltinFnIdBitReverse,
 };
 
 struct BuiltinFnEntry {
@@ -2191,6 +2191,8 @@ enum IrInstructionId {
     IrInstructionIdClz,
     IrInstructionIdCtz,
     IrInstructionIdPopCount,
+    IrInstructionIdBswap,
+    IrInstructionIdBitReverse,
     IrInstructionIdImport,
     IrInstructionIdCImport,
     IrInstructionIdCInclude,
@@ -2287,8 +2289,6 @@ enum IrInstructionId {
     IrInstructionIdMergeErrRetTraces,
     IrInstructionIdMarkErrRetTracePtr,
     IrInstructionIdSqrt,
-    IrInstructionIdBswap,
-    IrInstructionIdBitReverse,
     IrInstructionIdErrSetCast,
     IrInstructionIdToBytes,
     IrInstructionIdFromBytes,
@@ -2744,19 +2744,22 @@ struct IrInstructionOptionalUnwrapPtr {
 struct IrInstructionCtz {
     IrInstruction base;
 
-    IrInstruction *value;
+    IrInstruction *type;
+    IrInstruction *op;
 };
 
 struct IrInstructionClz {
     IrInstruction base;
 
-    IrInstruction *value;
+    IrInstruction *type;
+    IrInstruction *op;
 };
 
 struct IrInstructionPopCount {
     IrInstruction base;
 
-    IrInstruction *value;
+    IrInstruction *type;
+    IrInstruction *op;
 };
 
 struct IrInstructionUnionTag {
src/analyze.cpp
@@ -213,15 +213,6 @@ static ZigType *new_container_type_entry(CodeGen *g, ZigTypeId id, AstNode *sour
     return entry;
 }
 
-static uint8_t bits_needed_for_unsigned(uint64_t x) {
-    if (x == 0) {
-        return 0;
-    }
-    uint8_t base = log2_u64(x);
-    uint64_t upper = (((uint64_t)1) << base) - 1;
-    return (upper >= x) ? base : (base + 1);
-}
-
 AstNode *type_decl_node(ZigType *type_entry) {
     switch (type_entry->id) {
         case ZigTypeIdInvalid:
@@ -335,10 +326,33 @@ static bool is_slice(ZigType *type) {
     return type->id == ZigTypeIdStruct && type->data.structure.is_slice;
 }
 
+static uint8_t bits_needed_for_unsigned(uint64_t x) {
+    if (x == 0) {
+        return 0;
+    }
+    uint8_t base = log2_u64(x);
+    uint64_t upper = (((uint64_t)1) << base) - 1;
+    return (upper >= x) ? base : (base + 1);
+}
+
+static uint8_t bits_needed_for_popcount_unsigned(uint64_t x) {
+    uint8_t count = 0;
+    for (uint64_t s = x;s != 0;s >>= 1)
+        count++;
+
+    return count;
+}
+
 ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
     return get_int_type(g, false, bits_needed_for_unsigned(x));
 }
 
+// This is not the same as above, because while shift by bit width is UB, @clz, @popCount, and @ctz
+// can return bit width
+ZigType *get_smallest_popcount_unsigned_int_type(CodeGen *g, uint64_t x) {
+    return get_int_type(g, false, bits_needed_for_popcount_unsigned(x));
+}
+
 ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
     if (result_type != nullptr && result_type->promise_parent != nullptr) {
         return result_type->promise_parent;
src/analyze.hpp
@@ -34,6 +34,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);
 ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
         AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout);
 ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
+ZigType *get_smallest_popcount_unsigned_int_type(CodeGen *g, uint64_t x);
 ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type);
 ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry);
 ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *full_name, Buf *bare_name);
src/codegen.cpp
@@ -4126,11 +4126,19 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI
 
     char llvm_name[64];
     sprintf(llvm_name, "llvm.%s.i%" PRIu32, fn_name, int_type->data.integral.bit_count);
-    LLVMTypeRef param_types[] = {
-        get_llvm_type(g, int_type),
-        LLVMInt1Type(),
-    };
-    LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, int_type), param_types, n_args, false);
+    LLVMTypeRef param_types[3];
+    switch (n_args) {
+    case 1:
+        param_types[0] = get_llvm_type(g, int_type);
+        break;
+    case 2: // clz and ctz
+        param_types[0] = get_llvm_type(g, int_type);
+        param_types[1] = LLVMInt1Type();
+        break;
+    default:
+        zig_unreachable();
+    }
+    LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, int_type), &param_types[0], n_args, false);
     LLVMValueRef fn_val = LLVMAddFunction(g->module, llvm_name, fn_type);
     assert(LLVMGetIntrinsicID(fn_val));
 
@@ -4140,9 +4148,9 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI
 }
 
 static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutable *executable, IrInstructionClz *instruction) {
-    ZigType *int_type = instruction->value->value.type;
+    ZigType *int_type = instruction->op->value.type;
     LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdClz);
-    LLVMValueRef operand = ir_llvm_value(g, instruction->value);
+    LLVMValueRef operand = ir_llvm_value(g, instruction->op);
     LLVMValueRef params[] {
         operand,
         LLVMConstNull(LLVMInt1Type()),
@@ -4152,9 +4160,9 @@ static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutable *executable, IrInstru
 }
 
 static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstructionCtz *instruction) {
-    ZigType *int_type = instruction->value->value.type;
+    ZigType *int_type = instruction->op->value.type;
     LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdCtz);
-    LLVMValueRef operand = ir_llvm_value(g, instruction->value);
+    LLVMValueRef operand = ir_llvm_value(g, instruction->op);
     LLVMValueRef params[] {
         operand,
         LLVMConstNull(LLVMInt1Type()),
@@ -4164,9 +4172,9 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstru
 }
 
 static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) {
-    ZigType *int_type = instruction->value->value.type;
+    ZigType *int_type = instruction->op->value.type;
     LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount);
-    LLVMValueRef operand = ir_llvm_value(g, instruction->value);
+    LLVMValueRef operand = ir_llvm_value(g, instruction->op);
     LLVMValueRef wrong_size_int = LLVMBuildCall(g->builder, fn_val, &operand, 1, "");
     return gen_widen_or_shorten(g, false, int_type, instruction->base.value.type, wrong_size_int);
 }
@@ -5650,6 +5658,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
             return ir_render_pop_count(g, executable, (IrInstructionPopCount *)instruction);
         case IrInstructionIdSwitchBr:
             return ir_render_switch_br(g, executable, (IrInstructionSwitchBr *)instruction);
+        case IrInstructionIdBswap:
+            return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction);
+        case IrInstructionIdBitReverse:
+            return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction);
         case IrInstructionIdPhi:
             return ir_render_phi(g, executable, (IrInstructionPhi *)instruction);
         case IrInstructionIdRef:
@@ -5766,10 +5778,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
             return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);
         case IrInstructionIdSqrt:
             return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);
-        case IrInstructionIdBswap:
-            return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction);
-        case IrInstructionIdBitReverse:
-            return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction);
         case IrInstructionIdArrayToVector:
             return ir_render_array_to_vector(g, executable, (IrInstructionArrayToVector *)instruction);
         case IrInstructionIdVectorToArray:
@@ -7332,9 +7340,11 @@ static void define_builtin_fns(CodeGen *g) {
     create_builtin_fn(g, BuiltinFnIdCInclude, "cInclude", 1);
     create_builtin_fn(g, BuiltinFnIdCDefine, "cDefine", 2);
     create_builtin_fn(g, BuiltinFnIdCUndef, "cUndef", 1);
-    create_builtin_fn(g, BuiltinFnIdCtz, "ctz", 1);
-    create_builtin_fn(g, BuiltinFnIdClz, "clz", 1);
-    create_builtin_fn(g, BuiltinFnIdPopCount, "popCount", 1);
+    create_builtin_fn(g, BuiltinFnIdCtz, "ctz", 2);
+    create_builtin_fn(g, BuiltinFnIdClz, "clz", 2);
+    create_builtin_fn(g, BuiltinFnIdPopCount, "popCount", 2);
+    create_builtin_fn(g, BuiltinFnIdBswap, "byteSwap", 2);
+    create_builtin_fn(g, BuiltinFnIdBitReverse, "bitReverse", 2);
     create_builtin_fn(g, BuiltinFnIdImport, "import", 1);
     create_builtin_fn(g, BuiltinFnIdCImport, "cImport", 1);
     create_builtin_fn(g, BuiltinFnIdErrName, "errorName", 1);
@@ -7395,8 +7405,6 @@ static void define_builtin_fns(CodeGen *g) {
     create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
     create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
     create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
-    create_builtin_fn(g, BuiltinFnIdBswap, "bswap", 2);
-    create_builtin_fn(g, BuiltinFnIdBitReverse, "bitreverse", 2);
 }
 
 static const char *bool_to_str(bool b) {
src/ir.cpp
@@ -575,6 +575,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPopCount *) {
     return IrInstructionIdPopCount;
 }
 
+static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) {
+    return IrInstructionIdBswap;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionBitReverse *) {
+    return IrInstructionIdBitReverse;
+}
+
 static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionTag *) {
     return IrInstructionIdUnionTag;
 }
@@ -983,14 +991,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) {
     return IrInstructionIdSqrt;
 }
 
-static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) {
-    return IrInstructionIdBswap;
-}
-
-static constexpr IrInstructionId ir_instruction_id(IrInstructionBitReverse *) {
-    return IrInstructionIdBitReverse;
-}
-
 static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {
     return IrInstructionIdCheckRuntimeScope;
 }
@@ -1768,29 +1768,57 @@ static IrInstruction *ir_build_err_wrap_code(IrBuilder *irb, Scope *scope, AstNo
     return &instruction->base;
 }
 
-static IrInstruction *ir_build_clz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
+static IrInstruction *ir_build_clz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
     IrInstructionClz *instruction = ir_build_instruction<IrInstructionClz>(irb, scope, source_node);
-    instruction->value = value;
+    instruction->type = type;
+    instruction->op = op;
 
-    ir_ref_instruction(value, irb->current_basic_block);
+    if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
+    ir_ref_instruction(op, irb->current_basic_block);
 
     return &instruction->base;
 }
 
-static IrInstruction *ir_build_ctz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
+static IrInstruction *ir_build_ctz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
     IrInstructionCtz *instruction = ir_build_instruction<IrInstructionCtz>(irb, scope, source_node);
-    instruction->value = value;
+    instruction->type = type;
+    instruction->op = op;
 
-    ir_ref_instruction(value, irb->current_basic_block);
+    if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
+    ir_ref_instruction(op, irb->current_basic_block);
 
     return &instruction->base;
 }
 
-static IrInstruction *ir_build_pop_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
+static IrInstruction *ir_build_pop_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
     IrInstructionPopCount *instruction = ir_build_instruction<IrInstructionPopCount>(irb, scope, source_node);
-    instruction->value = value;
+    instruction->type = type;
+    instruction->op = op;
 
-    ir_ref_instruction(value, irb->current_basic_block);
+    if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
+    ir_ref_instruction(op, irb->current_basic_block);
+
+    return &instruction->base;
+}
+
+static IrInstruction *ir_build_bswap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
+    IrInstructionBswap *instruction = ir_build_instruction<IrInstructionBswap>(irb, scope, source_node);
+    instruction->type = type;
+    instruction->op = op;
+
+    if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
+    ir_ref_instruction(op, irb->current_basic_block);
+
+    return &instruction->base;
+}
+
+static IrInstruction *ir_build_bit_reverse(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
+    IrInstructionBitReverse *instruction = ir_build_instruction<IrInstructionBitReverse>(irb, scope, source_node);
+    instruction->type = type;
+    instruction->op = op;
+
+    if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
+    ir_ref_instruction(op, irb->current_basic_block);
 
     return &instruction->base;
 }
@@ -2986,28 +3014,6 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc
     return &instruction->base;
 }
 
-static IrInstruction *ir_build_bswap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
-    IrInstructionBswap *instruction = ir_build_instruction<IrInstructionBswap>(irb, scope, source_node);
-    instruction->type = type;
-    instruction->op = op;
-
-    if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
-    ir_ref_instruction(op, irb->current_basic_block);
-
-    return &instruction->base;
-}
-
-static IrInstruction *ir_build_bit_reverse(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
-    IrInstructionBitReverse *instruction = ir_build_instruction<IrInstructionBitReverse>(irb, scope, source_node);
-    instruction->type = type;
-    instruction->op = op;
-
-    if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
-    ir_ref_instruction(op, irb->current_basic_block);
-
-    return &instruction->base;
-}
-
 static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) {
     IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node);
     instruction->scope_is_comptime = scope_is_comptime;
@@ -4082,36 +4088,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
                 IrInstruction *size_of = ir_build_size_of(irb, scope, node, arg0_value);
                 return ir_lval_wrap(irb, scope, size_of, lval);
             }
-        case BuiltinFnIdCtz:
-            {
-                AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
-                IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
-                if (arg0_value == irb->codegen->invalid_instruction)
-                    return arg0_value;
-
-                IrInstruction *ctz = ir_build_ctz(irb, scope, node, arg0_value);
-                return ir_lval_wrap(irb, scope, ctz, lval);
-            }
-        case BuiltinFnIdPopCount:
-            {
-                AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
-                IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
-                if (arg0_value == irb->codegen->invalid_instruction)
-                    return arg0_value;
-
-                IrInstruction *instr = ir_build_pop_count(irb, scope, node, arg0_value);
-                return ir_lval_wrap(irb, scope, instr, lval);
-            }
-        case BuiltinFnIdClz:
-            {
-                AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
-                IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
-                if (arg0_value == irb->codegen->invalid_instruction)
-                    return arg0_value;
-
-                IrInstruction *clz = ir_build_clz(irb, scope, node, arg0_value);
-                return ir_lval_wrap(irb, scope, clz, lval);
-            }
         case BuiltinFnIdImport:
             {
                 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -5084,21 +5060,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
                 IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);
                 return ir_lval_wrap(irb, scope, result, lval);
             }
+        case BuiltinFnIdCtz:
+        case BuiltinFnIdPopCount:
+        case BuiltinFnIdClz:
         case BuiltinFnIdBswap:
-            {
-                AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
-                IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
-                if (arg0_value == irb->codegen->invalid_instruction)
-                    return arg0_value;
-
-                AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
-                IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
-                if (arg1_value == irb->codegen->invalid_instruction)
-                    return arg1_value;
-
-                IrInstruction *result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value);
-                return ir_lval_wrap(irb, scope, result, lval);
-            }
         case BuiltinFnIdBitReverse:
             {
                 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -5111,7 +5076,26 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
                 if (arg1_value == irb->codegen->invalid_instruction)
                     return arg1_value;
 
-                IrInstruction *result = ir_build_bit_reverse(irb, scope, node, arg0_value, arg1_value);
+                IrInstruction *result;
+                switch (builtin_fn->id) {
+                case BuiltinFnIdCtz:
+                    result = ir_build_ctz(irb, scope, node, arg0_value, arg1_value);
+                    break;
+                case BuiltinFnIdPopCount:
+                    result = ir_build_pop_count(irb, scope, node, arg0_value, arg1_value);
+                    break;
+                case BuiltinFnIdClz:
+                    result = ir_build_clz(irb, scope, node, arg0_value, arg1_value);
+                    break;
+                case BuiltinFnIdBswap:
+                    result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value);
+                    break;
+                case BuiltinFnIdBitReverse:
+                    result = ir_build_bit_reverse(irb, scope, node, arg0_value, arg1_value);
+                    break;
+                default:
+                    zig_unreachable();
+                }
                 return ir_lval_wrap(irb, scope, result, lval);
             }
     }
@@ -17040,92 +17024,125 @@ static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira,
     return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, instruction->safety_check_on);
 }
 
-static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {
-    IrInstruction *value = ctz_instruction->value->child;
-    if (type_is_invalid(value->value.type)) {
+static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *instruction) {
+    ZigType *int_type = ir_resolve_type(ira, instruction->type->child);
+    if (type_is_invalid(int_type))
         return ira->codegen->invalid_instruction;
-    } else if (value->value.type->id == ZigTypeIdInt) {
-        ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen,
-                value->value.type->data.integral.bit_count);
-        if (value->value.special != ConstValSpecialRuntime) {
-            size_t result_usize = bigint_ctz(&value->value.data.x_bigint,
-                    value->value.type->data.integral.bit_count);
-            IrInstruction *result = ir_const(ira, &ctz_instruction->base, return_type);
-            bigint_init_unsigned(&result->value.data.x_bigint, result_usize);
-            return result;
-        }
 
-        IrInstruction *result = ir_build_ctz(&ira->new_irb,
-            ctz_instruction->base.scope, ctz_instruction->base.source_node, value);
-        result->value.type = return_type;
-        return result;
-    } else {
-        ir_add_error_node(ira, ctz_instruction->base.source_node,
-            buf_sprintf("expected integer type, found '%s'", buf_ptr(&value->value.type->name)));
+    IrInstruction *op = instruction->op->child;
+
+    if (int_type->id != ZigTypeIdInt) {
+        ir_add_error(ira, instruction->type,
+            buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name)));
         return ira->codegen->invalid_instruction;
     }
-}
 
-static IrInstruction *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionClz *clz_instruction) {
-    IrInstruction *value = clz_instruction->value->child;
-    if (type_is_invalid(value->value.type)) {
+    IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type);
+    if (type_is_invalid(casted_op->value.type))
         return ira->codegen->invalid_instruction;
-    } else if (value->value.type->id == ZigTypeIdInt) {
-        ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen,
-                value->value.type->data.integral.bit_count);
-        if (value->value.special != ConstValSpecialRuntime) {
-            size_t result_usize = bigint_clz(&value->value.data.x_bigint,
-                    value->value.type->data.integral.bit_count);
-            IrInstruction *result = ir_const(ira, &clz_instruction->base, return_type);
-            bigint_init_unsigned(&result->value.data.x_bigint, result_usize);
-            return result;
-        }
 
-        IrInstruction *result = ir_build_clz(&ira->new_irb,
-            clz_instruction->base.scope, clz_instruction->base.source_node, value);
-        result->value.type = return_type;
+    ZigType *return_type = get_smallest_popcount_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count);
+
+    if (int_type->data.integral.bit_count == 0) {
+        IrInstruction *result = ir_const(ira, &instruction->base, return_type);
+        bigint_init_unsigned(&result->value.data.x_bigint, 0);
         return result;
-    } else {
-        ir_add_error_node(ira, clz_instruction->base.source_node,
-            buf_sprintf("expected integer type, found '%s'", buf_ptr(&value->value.type->name)));
+    }
+
+    if (instr_is_comptime(casted_op)) {
+        size_t result_usize = bigint_ctz(&op->value.data.x_bigint,
+                op->value.type->data.integral.bit_count);
+        IrInstruction *result = ir_const(ira, &instruction->base, return_type);
+        bigint_init_unsigned(&result->value.data.x_bigint, result_usize);
+        return result;
+    }
+
+    IrInstruction *result = ir_build_ctz(&ira->new_irb, instruction->base.scope,
+            instruction->base.source_node, nullptr, casted_op);
+    result->value.type = return_type;
+    return result;
+}
+
+static IrInstruction *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionClz *instruction) {
+    ZigType *int_type = ir_resolve_type(ira, instruction->type->child);
+    if (type_is_invalid(int_type))
+        return ira->codegen->invalid_instruction;
+
+    IrInstruction *op = instruction->op->child;
+
+    if (int_type->id != ZigTypeIdInt) {
+        ir_add_error(ira, instruction->type,
+            buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name)));
         return ira->codegen->invalid_instruction;
     }
+
+    IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type);
+    if (type_is_invalid(casted_op->value.type))
+        return ira->codegen->invalid_instruction;
+
+    ZigType *return_type = get_smallest_popcount_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count);
+
+    if (int_type->data.integral.bit_count == 0) {
+        IrInstruction *result = ir_const(ira, &instruction->base, return_type);
+        bigint_init_unsigned(&result->value.data.x_bigint, 0);
+        return result;
+    }
+
+    if (instr_is_comptime(casted_op)) {
+        size_t result_usize = bigint_clz(&op->value.data.x_bigint,
+                op->value.type->data.integral.bit_count);
+        IrInstruction *result = ir_const(ira, &instruction->base, return_type);
+        bigint_init_unsigned(&result->value.data.x_bigint, result_usize);
+        return result;
+    }
+
+    IrInstruction *result = ir_build_clz(&ira->new_irb, instruction->base.scope,
+            instruction->base.source_node, nullptr, casted_op);
+    result->value.type = return_type;
+    return result;
 }
 
 static IrInstruction *ir_analyze_instruction_pop_count(IrAnalyze *ira, IrInstructionPopCount *instruction) {
-    IrInstruction *value = instruction->value->child;
-    if (type_is_invalid(value->value.type))
+    ZigType *int_type = ir_resolve_type(ira, instruction->type->child);
+    if (type_is_invalid(int_type))
         return ira->codegen->invalid_instruction;
 
-    if (value->value.type->id != ZigTypeIdInt && value->value.type->id != ZigTypeIdComptimeInt) {
-        ir_add_error(ira, value,
-            buf_sprintf("expected integer type, found '%s'", buf_ptr(&value->value.type->name)));
+    IrInstruction *op = instruction->op->child;
+
+    if (int_type->id != ZigTypeIdInt) {
+        ir_add_error(ira, instruction->type,
+            buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name)));
         return ira->codegen->invalid_instruction;
     }
 
-    if (instr_is_comptime(value)) {
-        ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
+    IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type);
+    if (type_is_invalid(casted_op->value.type))
+        return ira->codegen->invalid_instruction;
+
+    ZigType *return_type = get_smallest_popcount_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count);
+
+    if (int_type->data.integral.bit_count == 0) {
+        IrInstruction *result = ir_const(ira, &instruction->base, return_type);
+        bigint_init_unsigned(&result->value.data.x_bigint, 0);
+        return result;
+    }
+
+    if (instr_is_comptime(casted_op)) {
+        ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad);
         if (!val)
             return ira->codegen->invalid_instruction;
+
         if (bigint_cmp_zero(&val->data.x_bigint) != CmpLT) {
             size_t result = bigint_popcount_unsigned(&val->data.x_bigint);
             return ir_const_unsigned(ira, &instruction->base, result);
         }
-        if (value->value.type->id == ZigTypeIdComptimeInt) {
-            Buf *val_buf = buf_alloc();
-            bigint_append_buf(val_buf, &val->data.x_bigint, 10);
-            ir_add_error(ira, &instruction->base,
-                buf_sprintf("@popCount on negative %s value %s",
-                    buf_ptr(&value->value.type->name), buf_ptr(val_buf)));
-            return ira->codegen->invalid_instruction;
-        }
-        size_t result = bigint_popcount_signed(&val->data.x_bigint, value->value.type->data.integral.bit_count);
+        size_t result = bigint_popcount_signed(&val->data.x_bigint, op->value.type->data.integral.bit_count);
         return ir_const_unsigned(ira, &instruction->base, result);
     }
 
     IrInstruction *result = ir_build_pop_count(&ira->new_irb, instruction->base.scope,
-            instruction->base.source_node, value);
-    result->value.type = get_smallest_unsigned_int_type(ira->codegen, value->value.type->data.integral.bit_count);
+            instruction->base.source_node, nullptr, casted_op);
+    result->value.type = return_type;
     return result;
 }
 
@@ -22990,8 +23007,6 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction
         return ira->codegen->invalid_instruction;
 
     IrInstruction *op = instruction->op->child;
-    if (type_is_invalid(op->value.type))
-        return ira->codegen->invalid_instruction;
 
     if (int_type->id != ZigTypeIdInt) {
         ir_add_error(ira, instruction->type,
@@ -22999,17 +23014,17 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction
         return ira->codegen->invalid_instruction;
     }
 
+    IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type);
+    if (type_is_invalid(casted_op->value.type))
+        return ira->codegen->invalid_instruction;
+
     if (int_type->data.integral.bit_count % 8 != 0) {
-        ir_add_error(ira, instruction->type,
-            buf_sprintf("@bswap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8",
+        ir_add_error(ira, instruction->op,
+            buf_sprintf("@byteSwap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8",
                 buf_ptr(&int_type->name), int_type->data.integral.bit_count));
         return ira->codegen->invalid_instruction;
     }
 
-    IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type);
-    if (type_is_invalid(casted_op->value.type))
-        return ira->codegen->invalid_instruction;
-
     if (int_type->data.integral.bit_count == 0) {
         IrInstruction *result = ir_const(ira, &instruction->base, int_type);
         bigint_init_unsigned(&result->value.data.x_bigint, 0);
@@ -23017,7 +23032,7 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction
     }
 
     if (int_type->data.integral.bit_count == 8) {
-        return casted_op;
+        return op;
     }
 
     if (instr_is_comptime(casted_op)) {
@@ -23046,8 +23061,6 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr
         return ira->codegen->invalid_instruction;
 
     IrInstruction *op = instruction->op->child;
-    if (type_is_invalid(op->value.type))
-        return ira->codegen->invalid_instruction;
 
     if (int_type->id != ZigTypeIdInt) {
         ir_add_error(ira, instruction->type,
@@ -23251,6 +23264,10 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
             return ir_analyze_instruction_ctz(ira, (IrInstructionCtz *)instruction);
         case IrInstructionIdPopCount:
             return ir_analyze_instruction_pop_count(ira, (IrInstructionPopCount *)instruction);
+        case IrInstructionIdBswap:
+            return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction);
+        case IrInstructionIdBitReverse:
+            return ir_analyze_instruction_bit_reverse(ira, (IrInstructionBitReverse *)instruction);
         case IrInstructionIdSwitchBr:
             return ir_analyze_instruction_switch_br(ira, (IrInstructionSwitchBr *)instruction);
         case IrInstructionIdSwitchTarget:
@@ -23443,10 +23460,6 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
             return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
         case IrInstructionIdSqrt:
             return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);
-        case IrInstructionIdBswap:
-            return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction);
-        case IrInstructionIdBitReverse:
-            return ir_analyze_instruction_bit_reverse(ira, (IrInstructionBitReverse *)instruction);
         case IrInstructionIdIntToErr:
             return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
         case IrInstructionIdErrToInt:
@@ -23621,6 +23634,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
         case IrInstructionIdClz:
         case IrInstructionIdCtz:
         case IrInstructionIdPopCount:
+        case IrInstructionIdBswap:
+        case IrInstructionIdBitReverse:
         case IrInstructionIdSwitchVar:
         case IrInstructionIdSwitchElseVar:
         case IrInstructionIdSwitchTarget:
@@ -23679,8 +23694,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
         case IrInstructionIdCoroPromise:
         case IrInstructionIdPromiseResultType:
         case IrInstructionIdSqrt:
-        case IrInstructionIdBswap:
-        case IrInstructionIdBitReverse:
         case IrInstructionIdAtomicLoad:
         case IrInstructionIdIntCast:
         case IrInstructionIdFloatCast:
src/ir_print.cpp
@@ -504,19 +504,61 @@ static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwr
 
 static void ir_print_clz(IrPrint *irp, IrInstructionClz *instruction) {
     fprintf(irp->f, "@clz(");
-    ir_print_other_instruction(irp, instruction->value);
+    if (instruction->type != nullptr) {
+        ir_print_other_instruction(irp, instruction->type);
+    } else {
+        fprintf(irp->f, "null");
+    }
+    fprintf(irp->f, ",");
+    ir_print_other_instruction(irp, instruction->op);
     fprintf(irp->f, ")");
 }
 
 static void ir_print_ctz(IrPrint *irp, IrInstructionCtz *instruction) {
     fprintf(irp->f, "@ctz(");
-    ir_print_other_instruction(irp, instruction->value);
+    if (instruction->type != nullptr) {
+        ir_print_other_instruction(irp, instruction->type);
+    } else {
+        fprintf(irp->f, "null");
+    }
+    fprintf(irp->f, ",");
+    ir_print_other_instruction(irp, instruction->op);
     fprintf(irp->f, ")");
 }
 
 static void ir_print_pop_count(IrPrint *irp, IrInstructionPopCount *instruction) {
     fprintf(irp->f, "@popCount(");
-    ir_print_other_instruction(irp, instruction->value);
+    if (instruction->type != nullptr) {
+        ir_print_other_instruction(irp, instruction->type);
+    } else {
+        fprintf(irp->f, "null");
+    }
+    fprintf(irp->f, ",");
+    ir_print_other_instruction(irp, instruction->op);
+    fprintf(irp->f, ")");
+}
+
+static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {
+    fprintf(irp->f, "@byteSwap(");
+    if (instruction->type != nullptr) {
+        ir_print_other_instruction(irp, instruction->type);
+    } else {
+        fprintf(irp->f, "null");
+    }
+    fprintf(irp->f, ",");
+    ir_print_other_instruction(irp, instruction->op);
+    fprintf(irp->f, ")");
+}
+
+static void ir_print_bit_reverse(IrPrint *irp, IrInstructionBitReverse *instruction) {
+    fprintf(irp->f, "@bitReverse(");
+    if (instruction->type != nullptr) {
+        ir_print_other_instruction(irp, instruction->type);
+    } else {
+        fprintf(irp->f, "null");
+    }
+    fprintf(irp->f, ",");
+    ir_print_other_instruction(irp, instruction->op);
     fprintf(irp->f, ")");
 }
 
@@ -1411,30 +1453,6 @@ static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_va
     }
 }
 
-static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {
-    fprintf(irp->f, "@bswap(");
-    if (instruction->type != nullptr) {
-        ir_print_other_instruction(irp, instruction->type);
-    } else {
-        fprintf(irp->f, "null");
-    }
-    fprintf(irp->f, ",");
-    ir_print_other_instruction(irp, instruction->op);
-    fprintf(irp->f, ")");
-}
-
-static void ir_print_bit_reverse(IrPrint *irp, IrInstructionBitReverse *instruction) {
-    fprintf(irp->f, "@bitreverse(");
-    if (instruction->type != nullptr) {
-        ir_print_other_instruction(irp, instruction->type);
-    } else {
-        fprintf(irp->f, "null");
-    }
-    fprintf(irp->f, ",");
-    ir_print_other_instruction(irp, instruction->op);
-    fprintf(irp->f, ")");
-}
-
 static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
     ir_print_prefix(irp, instruction);
     switch (instruction->id) {
@@ -1551,15 +1569,21 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
         case IrInstructionIdOptionalUnwrapPtr:
             ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction);
             break;
-        case IrInstructionIdCtz:
-            ir_print_ctz(irp, (IrInstructionCtz *)instruction);
-            break;
         case IrInstructionIdPopCount:
             ir_print_pop_count(irp, (IrInstructionPopCount *)instruction);
             break;
         case IrInstructionIdClz:
             ir_print_clz(irp, (IrInstructionClz *)instruction);
             break;
+        case IrInstructionIdCtz:
+            ir_print_ctz(irp, (IrInstructionCtz *)instruction);
+            break;
+        case IrInstructionIdBswap:
+            ir_print_bswap(irp, (IrInstructionBswap *)instruction);
+            break;
+        case IrInstructionIdBitReverse:
+            ir_print_bit_reverse(irp, (IrInstructionBitReverse *)instruction);
+            break;
         case IrInstructionIdSwitchBr:
             ir_print_switch_br(irp, (IrInstructionSwitchBr *)instruction);
             break;
@@ -1869,12 +1893,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
         case IrInstructionIdSqrt:
             ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);
             break;
-        case IrInstructionIdBswap:
-            ir_print_bswap(irp, (IrInstructionBswap *)instruction);
-            break;
-        case IrInstructionIdBitReverse:
-            ir_print_bit_reverse(irp, (IrInstructionBitReverse *)instruction);
-            break;
         case IrInstructionIdAtomicLoad:
             ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
             break;
std/math/big/int.zig
@@ -207,7 +207,7 @@ pub const Int = struct {
 
     /// Returns the number of bits required to represent the absolute value an Int.
     fn bitCountAbs(self: Int) usize {
-        return (self.len() - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len() - 1]));
+        return (self.len() - 1) * Limb.bit_count + (Limb.bit_count - @clz(Limb, self.limbs[self.len() - 1]));
     }
 
     /// Returns the number of bits required to represent the integer in twos-complement form.
@@ -226,9 +226,9 @@ pub const Int = struct {
         if (!self.isPositive()) block: {
             bits += 1;
 
-            if (@popCount(self.limbs[self.len() - 1]) == 1) {
+            if (@popCount(Limb, self.limbs[self.len() - 1]) == 1) {
                 for (self.limbs[0 .. self.len() - 1]) |limb| {
-                    if (@popCount(limb) != 0) {
+                    if (@popCount(Limb, limb) != 0) {
                         break :block;
                     }
                 }
@@ -962,7 +962,7 @@ pub const Int = struct {
         defer tmp.deinit();
 
         // Normalize so y > Limb.bit_count / 2 (i.e. leading bit is set) and even
-        var norm_shift = @clz(y.limbs[y.len() - 1]);
+        var norm_shift = @clz(Limb, y.limbs[y.len() - 1]);
         if (norm_shift == 0 and y.isOdd()) {
             norm_shift = Limb.bit_count;
         }
std/special/compiler_rt/addXf3.zig
@@ -36,11 +36,11 @@ pub extern fn __subtf3(a: f128, b: f128) f128 {
 // TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154
 fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 {
     const Z = @IntType(false, T.bit_count);
-    const S = @IntType(false, T.bit_count - @clz(Z(T.bit_count) - 1));
+    const S = @IntType(false, T.bit_count - @clz(Z, Z(T.bit_count) - 1));
     const significandBits = std.math.floatMantissaBits(T);
     const implicitBit = Z(1) << significandBits;
 
-    const shift = @clz(significand.*) - @clz(implicitBit);
+    const shift = @clz(@IntType(false, T.bit_count), significand.*) - @clz(Z, implicitBit);
     significand.* <<= @intCast(S, shift);
     return 1 - shift;
 }
@@ -48,7 +48,7 @@ fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 {
 // TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154
 fn addXf3(comptime T: type, a: T, b: T) T {
     const Z = @IntType(false, T.bit_count);
-    const S = @IntType(false, T.bit_count - @clz(Z(T.bit_count) - 1));
+    const S = @IntType(false, T.bit_count - @clz(Z, Z(T.bit_count) - 1));
 
     const typeWidth = T.bit_count;
     const significandBits = std.math.floatMantissaBits(T);
@@ -162,7 +162,7 @@ fn addXf3(comptime T: type, a: T, b: T) T {
         // If partial cancellation occured, we need to left-shift the result
         // and adjust the exponent:
         if (aSignificand < implicitBit << 3) {
-            const shift = @intCast(i32, @clz(aSignificand)) - @intCast(i32, @clz(implicitBit << 3));
+            const shift = @intCast(i32, @clz(Z, aSignificand)) - @intCast(i32, @clz(@IntType(false, T.bit_count), implicitBit << 3));
             aSignificand <<= @intCast(S, shift);
             aExponent -= shift;
         }
std/special/compiler_rt/divdf3.zig
@@ -318,7 +318,7 @@ fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 {
     const significandBits = std.math.floatMantissaBits(T);
     const implicitBit = Z(1) << significandBits;
 
-    const shift = @clz(significand.*) - @clz(implicitBit);
+    const shift = @clz(Z, significand.*) - @clz(Z, implicitBit);
     significand.* <<= @intCast(std.math.Log2Int(Z), shift);
     return 1 - shift;
 }
std/special/compiler_rt/divsf3.zig
@@ -191,7 +191,7 @@ fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 {
     const significandBits = std.math.floatMantissaBits(T);
     const implicitBit = Z(1) << significandBits;
 
-    const shift = @clz(significand.*) - @clz(implicitBit);
+    const shift = @clz(Z, significand.*) - @clz(Z, implicitBit);
     significand.* <<= @intCast(std.math.Log2Int(Z), shift);
     return 1 - shift;
 }
std/special/compiler_rt/extendXfYf2.zig
@@ -75,7 +75,8 @@ fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: @IntType(false, @t
         // a is denormal.
         // renormalize the significand and clear the leading bit, then insert
         // the correct adjusted exponent in the destination type.
-        const scale: u32 = @clz(aAbs) - @clz(src_rep_t(srcMinNormal));
+        const scale: u32 = @clz(src_rep_t, aAbs) -
+                           @clz(src_rep_t, src_rep_t(srcMinNormal));
         absResult = dst_rep_t(aAbs) << @intCast(DstShift, dstSigBits - srcSigBits + scale);
         absResult ^= dstMinNormal;
         const resultExponent: u32 = dstExpBias - srcExpBias - scale + 1;
std/special/compiler_rt/floatsiXf.zig
@@ -6,7 +6,7 @@ fn floatsiXf(comptime T: type, a: i32) T {
     @setRuntimeSafety(builtin.is_test);
 
     const Z = @IntType(false, T.bit_count);
-    const S = @IntType(false, T.bit_count - @clz(Z(T.bit_count) - 1));
+    const S = @IntType(false, T.bit_count - @clz(Z, Z(T.bit_count) - 1));
 
     if (a == 0) {
         return T(0.0);
@@ -23,7 +23,7 @@ fn floatsiXf(comptime T: type, a: i32) T {
     // Take absolute value of a via abs(x) = (x^(x >> 31)) - (x >> 31).
     const abs_a = (a ^ sign) -% sign;
     // The exponent is the width of abs(a)
-    const exp = Z(31 - @clz(abs_a));
+    const exp = Z(31 - @clz(i32, abs_a));
 
     const sign_bit = if (sign < 0) signBit else 0;
 
std/special/compiler_rt/floattidf.zig
@@ -17,7 +17,7 @@ pub extern fn __floattidf(arg: i128) f64 {
     ai = ((ai ^ si) -% si);
     var a = @bitCast(u128, ai);
 
-    const sd = @bitCast(i32, N - @clz(a)); // number of significant digits
+    const sd = @bitCast(i32, N - @clz(u128, a)); // number of significant digits
     var e: i32 = sd - 1; // exponent
     if (sd > DBL_MANT_DIG) {
         //  start:  0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
std/special/compiler_rt/floattisf.zig
@@ -17,7 +17,7 @@ pub extern fn __floattisf(arg: i128) f32 {
     ai = ((ai ^ si) -% si);
     var a = @bitCast(u128, ai);
 
-    const sd = @bitCast(i32, N - @clz(a)); // number of significant digits
+    const sd = @bitCast(i32, N - @clz(u128, a)); // number of significant digits
     var e: i32 = sd - 1; // exponent
 
     if (sd > FLT_MANT_DIG) {
std/special/compiler_rt/floattitf.zig
@@ -17,7 +17,7 @@ pub extern fn __floattitf(arg: i128) f128 {
     ai = ((ai ^ si) -% si);
     var a = @bitCast(u128, ai);
 
-    const sd = @bitCast(i32, N - @clz(a)); // number of significant digits
+    const sd = @bitCast(i32, N - @clz(u128, a)); // number of significant digits
     var e: i32 = sd - 1; // exponent
     if (sd > LDBL_MANT_DIG) {
         //  start:  0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
std/special/compiler_rt/floatunditf.zig
@@ -14,7 +14,7 @@ pub extern fn __floatunditf(a: u128) f128 {
     const exponent_bias = (1 << (exponent_bits - 1)) - 1;
     const implicit_bit = 1 << mantissa_bits;
 
-    const exp = (u128.bit_count - 1) - @clz(a);
+    const exp = (u128.bit_count - 1) - @clz(u128, a);
     const shift = mantissa_bits - @intCast(u7, exp);
 
     var result: u128 align(16) = (a << shift) ^ implicit_bit;
std/special/compiler_rt/floatunsidf.zig
@@ -10,7 +10,7 @@ pub extern fn __floatunsidf(arg: u32) f64 {
     if (arg == 0) return 0.0;
 
     // The exponent is the width of abs(a)
-    const exp = u64(31) - @clz(arg);
+    const exp = u64(31) - @clz(u32, arg);
     // Shift a into the significand field and clear the implicit bit
     const shift = @intCast(u6, 52 - exp);
     const mant = u64(arg) << shift ^ implicitBit;
std/special/compiler_rt/floatunsitf.zig
@@ -14,7 +14,7 @@ pub extern fn __floatunsitf(a: u64) f128 {
     const exponent_bias = (1 << (exponent_bits - 1)) - 1;
     const implicit_bit = 1 << mantissa_bits;
 
-    const exp = (u64.bit_count - 1) - @clz(a);
+    const exp = (u64.bit_count - 1) - @clz(u64, a);
     const shift = mantissa_bits - @intCast(u7, exp);
 
     // TODO(#1148): @bitCast alignment error
std/special/compiler_rt/floatuntidf.zig
@@ -13,7 +13,7 @@ pub extern fn __floatuntidf(arg: u128) f64 {
 
     var a = arg;
     const N: u32 = @sizeOf(u128) * 8;
-    const sd = @bitCast(i32, N - @clz(a)); // number of significant digits
+    const sd = @bitCast(i32, N - @clz(u128, a)); // number of significant digits
     var e: i32 = sd - 1; // exponent
     if (sd > DBL_MANT_DIG) {
         //  start:  0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
std/special/compiler_rt/floatuntisf.zig
@@ -13,7 +13,7 @@ pub extern fn __floatuntisf(arg: u128) f32 {
 
     var a = arg;
     const N: u32 = @sizeOf(u128) * 8;
-    const sd = @bitCast(i32, N - @clz(a)); // number of significant digits
+    const sd = @bitCast(i32, N - @clz(u128, a)); // number of significant digits
     var e: i32 = sd - 1; // exponent
     if (sd > FLT_MANT_DIG) {
         //  start:  0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
std/special/compiler_rt/floatuntitf.zig
@@ -13,7 +13,7 @@ pub extern fn __floatuntitf(arg: u128) f128 {
 
     var a = arg;
     const N: u32 = @sizeOf(u128) * 8;
-    const sd = @bitCast(i32, N - @clz(a)); // number of significant digits
+    const sd = @bitCast(i32, N - @clz(u128, a)); // number of significant digits
     var e: i32 = sd - 1; // exponent
     if (sd > LDBL_MANT_DIG) {
         //  start:  0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
std/special/compiler_rt/mulXf3.zig
@@ -260,7 +260,7 @@ fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 {
     const significandBits = std.math.floatMantissaBits(T);
     const implicitBit = Z(1) << significandBits;
 
-    const shift = @clz(significand.*) - @clz(implicitBit);
+    const shift = @clz(Z, significand.*) - @clz(Z, implicitBit);
     significand.* <<= @intCast(std.math.Log2Int(Z), shift);
     return 1 - shift;
 }
std/special/compiler_rt/udivmod.zig
@@ -71,12 +71,12 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
                 r[high] = n[high] & (d[high] - 1);
                 rem.* = @ptrCast(*align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421
             }
-            return n[high] >> @intCast(Log2SingleInt, @ctz(d[high]));
+            return n[high] >> @intCast(Log2SingleInt, @ctz(SingleInt, d[high]));
         }
         // K K
         // ---
         // K 0
-        sr = @bitCast(c_uint, c_int(@clz(d[high])) - c_int(@clz(n[high])));
+        sr = @bitCast(c_uint, c_int(@clz(SingleInt, d[high])) - c_int(@clz(SingleInt, n[high])));
         // 0 <= sr <= SingleInt.bit_count - 2 or sr large
         if (sr > SingleInt.bit_count - 2) {
             if (maybe_rem) |rem| {
@@ -106,7 +106,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
                 if (d[low] == 1) {
                     return a;
                 }
-                sr = @ctz(d[low]);
+                sr = @ctz(SingleInt, d[low]);
                 q[high] = n[high] >> @intCast(Log2SingleInt, sr);
                 q[low] = (n[high] << @intCast(Log2SingleInt, SingleInt.bit_count - sr)) | (n[low] >> @intCast(Log2SingleInt, sr));
                 return @ptrCast(*align(@alignOf(SingleInt)) DoubleInt, &q[0]).*; // TODO issue #421
@@ -114,7 +114,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
             // K X
             // ---
             // 0 K
-            sr = 1 + SingleInt.bit_count + c_uint(@clz(d[low])) - c_uint(@clz(n[high]));
+            sr = 1 + SingleInt.bit_count + c_uint(@clz(SingleInt, d[low])) - c_uint(@clz(SingleInt, n[high]));
             // 2 <= sr <= DoubleInt.bit_count - 1
             // q.all = a << (DoubleInt.bit_count - sr);
             // r.all = a >> sr;
@@ -140,7 +140,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
             // K X
             // ---
             // K K
-            sr = @bitCast(c_uint, c_int(@clz(d[high])) - c_int(@clz(n[high])));
+            sr = @bitCast(c_uint, c_int(@clz(SingleInt, d[high])) - c_int(@clz(SingleInt, n[high])));
             // 0 <= sr <= SingleInt.bit_count - 1 or sr large
             if (sr > SingleInt.bit_count - 1) {
                 if (maybe_rem) |rem| {
std/special/compiler_rt.zig
@@ -19,7 +19,6 @@ comptime {
     @export("__getf2", @import("compiler_rt/comparetf2.zig").__getf2, linkage);
 
     if (!is_test) {
-        // only create these aliases when not testing
         @export("__cmpsf2", @import("compiler_rt/comparesf2.zig").__lesf2, linkage);
         @export("__cmpdf2", @import("compiler_rt/comparedf2.zig").__ledf2, linkage);
         @export("__cmptf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage);
@@ -599,7 +598,7 @@ extern fn __udivsi3(n: u32, d: u32) u32 {
     // special cases
     if (d == 0) return 0; // ?!
     if (n == 0) return 0;
-    var sr = @bitCast(c_uint, c_int(@clz(d)) - c_int(@clz(n)));
+    var sr = @bitCast(c_uint, c_int(@clz(u32, d)) - c_int(@clz(u32, n)));
     // 0 <= sr <= n_uword_bits - 1 or sr large
     if (sr > n_uword_bits - 1) {
         // d > r
std/heap.zig
@@ -894,7 +894,7 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo
     const large_align = u29(os.page_size << 2);
 
     var align_mask: usize = undefined;
-    _ = @shlWithOverflow(usize, ~usize(0), USizeShift(@ctz(large_align)), &align_mask);
+    _ = @shlWithOverflow(usize, ~usize(0), USizeShift(@ctz(u29, large_align)), &align_mask);
 
     var slice = try allocator.alignedAlloc(u8, large_align, 500);
     testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
std/math.zig
@@ -698,7 +698,7 @@ test "math.floorPowerOfTwo" {
 
 pub fn log2_int(comptime T: type, x: T) Log2Int(T) {
     assert(x != 0);
-    return @intCast(Log2Int(T), T.bit_count - 1 - @clz(x));
+    return @intCast(Log2Int(T), T.bit_count - 1 - @clz(T, x));
 }
 
 pub fn log2_int_ceil(comptime T: type, x: T) Log2Int(T) {
std/mem.zig
@@ -513,7 +513,7 @@ pub fn readIntNative(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]
 /// This function cannot fail and cannot cause undefined behavior.
 /// Assumes the endianness of memory is foreign, so it must byte-swap.
 pub fn readIntForeign(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T {
-    return @bswap(T, readIntNative(T, bytes));
+    return @byteSwap(T, readIntNative(T, bytes));
 }
 
 pub const readIntLittle = switch (builtin.endian) {
@@ -543,7 +543,7 @@ pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {
 /// The bit count of T must be evenly divisible by 8.
 /// Assumes the endianness of memory is foreign, so it must byte-swap.
 pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T {
-    return @bswap(T, readIntSliceNative(T, bytes));
+    return @byteSwap(T, readIntSliceNative(T, bytes));
 }
 
 pub const readIntSliceLittle = switch (builtin.endian) {
@@ -624,9 +624,9 @@ pub fn writeIntNative(comptime T: type, buf: *[(T.bit_count + 7) / 8]u8, value:
 /// Writes an integer to memory, storing it in twos-complement.
 /// This function always succeeds, has defined behavior for all inputs, but
 /// the integer bit width must be divisible by 8.
-/// This function stores in foreign endian, which means it does a @bswap first.
+/// This function stores in foreign endian, which means it does a @byteSwap first.
 pub fn writeIntForeign(comptime T: type, buf: *[@divExact(T.bit_count, 8)]u8, value: T) void {
-    writeIntNative(T, buf, @bswap(T, value));
+    writeIntNative(T, buf, @byteSwap(T, value));
 }
 
 pub const writeIntLittle = switch (builtin.endian) {
@@ -1229,14 +1229,14 @@ test "std.mem.rotate" {
 pub fn littleToNative(comptime T: type, x: T) T {
     return switch (builtin.endian) {
         builtin.Endian.Little => x,
-        builtin.Endian.Big => @bswap(T, x),
+        builtin.Endian.Big => @byteSwap(T, x),
     };
 }
 
 /// Converts a big-endian integer to host endianness.
 pub fn bigToNative(comptime T: type, x: T) T {
     return switch (builtin.endian) {
-        builtin.Endian.Little => @bswap(T, x),
+        builtin.Endian.Little => @byteSwap(T, x),
         builtin.Endian.Big => x,
     };
 }
@@ -1261,14 +1261,14 @@ pub fn nativeTo(comptime T: type, x: T, desired_endianness: builtin.Endian) T {
 pub fn nativeToLittle(comptime T: type, x: T) T {
     return switch (builtin.endian) {
         builtin.Endian.Little => x,
-        builtin.Endian.Big => @bswap(T, x),
+        builtin.Endian.Big => @byteSwap(T, x),
     };
 }
 
 /// Converts an integer which has host endianness to big endian.
 pub fn nativeToBig(comptime T: type, x: T) T {
     return switch (builtin.endian) {
-        builtin.Endian.Little => @bswap(T, x),
+        builtin.Endian.Little => @byteSwap(T, x),
         builtin.Endian.Big => x,
     };
 }
std/os.zig
@@ -3377,7 +3377,7 @@ pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize {
                             const result = set[0 .. rc / @sizeOf(usize)];
                             var sum: usize = 0;
                             for (result) |x| {
-                                sum += @popCount(x);
+                                sum += @popCount(usize, x);
                             }
                             return sum;
                         } else {
std/packed_int_array.zig
@@ -66,7 +66,7 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {
             const value_ptr = @ptrCast(*align(1) const Container, &bytes[start_byte]);
             var value = value_ptr.*;
 
-            if (endian != builtin.endian) value = @bswap(Container, value);
+            if (endian != builtin.endian) value = @byteSwap(Container, value);
 
             switch (endian) {
                 .Big => {
@@ -114,7 +114,7 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {
             const target_ptr = @ptrCast(*align(1) Container, &bytes[start_byte]);
             var target = target_ptr.*;
 
-            if (endian != builtin.endian) target = @bswap(Container, target);
+            if (endian != builtin.endian) target = @byteSwap(Container, target);
 
             //zero the bits we want to replace in the existing bytes
             const inv_mask = @intCast(Container, std.math.maxInt(UnInt)) << keep_shift;
@@ -124,7 +124,7 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {
             //merge the new value
             target |= value;
 
-            if (endian != builtin.endian) target = @bswap(Container, target);
+            if (endian != builtin.endian) target = @byteSwap(Container, target);
 
             //save it back
             target_ptr.* = target;
test/stage1/behavior/bugs/2114.zig
@@ -3,7 +3,7 @@ const expect = std.testing.expect;
 const math = std.math;
 
 fn ctz(x: var) usize {
-    return @ctz(x);
+    return @ctz(u128, x);
 }
 
 test "fixed" {
test/stage1/behavior/bitreverse.zig
@@ -2,80 +2,68 @@ const std = @import("std");
 const expect = std.testing.expect;
 const minInt = std.math.minInt;
 
-test "@bitreverse" {
+test "@bitReverse" {
     comptime testBitReverse();
     testBitReverse();
 }
 
 fn testBitReverse() void {
     // using comptime_ints, unsigned
-    expect(@bitreverse(u0, 0) == 0);
-    expect(@bitreverse(u5, 0x12) == 0x9);
-    expect(@bitreverse(u8, 0x12) == 0x48);
-    expect(@bitreverse(u16, 0x1234) == 0x2c48);
-    expect(@bitreverse(u24, 0x123456) == 0x6a2c48);
-    expect(@bitreverse(u32, 0x12345678) == 0x1e6a2c48);
-    expect(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48);
-    expect(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
-    expect(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
-    expect(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
-    expect(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
+    expect(@bitReverse(u0, u0(0)) == 0);
+    expect(@bitReverse(u5, u5(0x12)) == 0x9);
+    expect(@bitReverse(u8, u8(0x12)) == 0x48);
+    expect(@bitReverse(u16, u16(0x1234)) == 0x2c48);
+    expect(@bitReverse(u24, u24(0x123456)) == 0x6a2c48);
+    expect(@bitReverse(u32, u32(0x12345678)) == 0x1e6a2c48);
+    expect(@bitReverse(u40, u40(0x123456789a)) == 0x591e6a2c48);
+    expect(@bitReverse(u48, u48(0x123456789abc)) == 0x3d591e6a2c48);
+    expect(@bitReverse(u56, u56(0x123456789abcde)) == 0x7b3d591e6a2c48);
+    expect(@bitReverse(u64, u64(0x123456789abcdef1)) == 0x8f7b3d591e6a2c48);
+    expect(@bitReverse(u128, u128(0x123456789abcdef11121314151617181)) == 0x818e868a828c84888f7b3d591e6a2c48);
 
     // using runtime uints, unsigned
     var num0: u0 = 0;
-    expect(@bitreverse(u0, num0) == 0);
+    expect(@bitReverse(u0, num0) == 0);
     var num5: u5 = 0x12;
-    expect(@bitreverse(u5, num5) == 0x9);
+    expect(@bitReverse(u5, num5) == 0x9);
     var num8: u8 = 0x12;
-    expect(@bitreverse(u8, num8) == 0x48);
+    expect(@bitReverse(u8, num8) == 0x48);
     var num16: u16 = 0x1234;
-    expect(@bitreverse(u16, num16) == 0x2c48);
+    expect(@bitReverse(u16, num16) == 0x2c48);
     var num24: u24 = 0x123456;
-    expect(@bitreverse(u24, num24) == 0x6a2c48);
+    expect(@bitReverse(u24, num24) == 0x6a2c48);
     var num32: u32 = 0x12345678;
-    expect(@bitreverse(u32, num32) == 0x1e6a2c48);
+    expect(@bitReverse(u32, num32) == 0x1e6a2c48);
     var num40: u40 = 0x123456789a;
-    expect(@bitreverse(u40, num40) == 0x591e6a2c48);
+    expect(@bitReverse(u40, num40) == 0x591e6a2c48);
     var num48: u48 = 0x123456789abc;
-    expect(@bitreverse(u48, num48) == 0x3d591e6a2c48);
+    expect(@bitReverse(u48, num48) == 0x3d591e6a2c48);
     var num56: u56 = 0x123456789abcde;
-    expect(@bitreverse(u56, num56) == 0x7b3d591e6a2c48);
+    expect(@bitReverse(u56, num56) == 0x7b3d591e6a2c48);
     var num64: u64 = 0x123456789abcdef1;
-    expect(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48);
+    expect(@bitReverse(u64, num64) == 0x8f7b3d591e6a2c48);
     var num128: u128 = 0x123456789abcdef11121314151617181;
-    expect(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
+    expect(@bitReverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
 
     // using comptime_ints, signed, positive
-    expect(@bitreverse(i0, 0) == 0);
-    expect(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8(0x49)));
-    expect(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x2c48)));
-    expect(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x6a2c48)));
-    expect(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x1e6a2c48)));
-    expect(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x591e6a2c48)));
-    expect(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0x3d591e6a2c48)));
-    expect(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0x7b3d591e6a2c48)));
-    expect(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0x8f7b3d591e6a2c48)));
-    expect(@bitreverse(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == @bitCast(i128, u128(0x818e868a828c84888f7b3d591e6a2c48)));
+    expect(@bitReverse(u8, u8(0)) == 0);
+    expect(@bitReverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8(0x49)));
+    expect(@bitReverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x2c48)));
+    expect(@bitReverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x6a2c48)));
+    expect(@bitReverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x1e6a2c48)));
+    expect(@bitReverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x591e6a2c48)));
+    expect(@bitReverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0x3d591e6a2c48)));
+    expect(@bitReverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0x7b3d591e6a2c48)));
+    expect(@bitReverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0x8f7b3d591e6a2c48)));
+    expect(@bitReverse(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == @bitCast(i128, u128(0x818e868a828c84888f7b3d591e6a2c48)));
 
-    // using comptime_ints, signed, negative. Compare to runtime ints returned from llvm.
-    var neg5: i5 = minInt(i5) + 1;
-    expect(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5));
+    // using signed, negative. Compare to runtime ints returned from llvm.
     var neg8: i8 = -18;
-    expect(@bitreverse(i8, -18) == @bitreverse(i8, neg8));
+    expect(@bitReverse(i8, i8(-18)) == @bitReverse(i8, neg8));
     var neg16: i16 = -32694;
-    expect(@bitreverse(i16, -32694) == @bitreverse(i16, neg16));
+    expect(@bitReverse(i16, i16(-32694)) == @bitReverse(i16, neg16));
     var neg24: i24 = -6773785;
-    expect(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24));
+    expect(@bitReverse(i24, i24(-6773785)) == @bitReverse(i24, neg24));
     var neg32: i32 = -16773785;
-    expect(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32));
-    var neg40: i40 = minInt(i40) + 12345;
-    expect(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40));
-    var neg48: i48 = minInt(i48) + 12345;
-    expect(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48));
-    var neg56: i56 = minInt(i56) + 12345;
-    expect(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56));
-    var neg64: i64 = minInt(i64) + 12345;
-    expect(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64));
-    var neg128: i128 = minInt(i128) + 12345;
-    expect(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128));
+    expect(@bitReverse(i32, i32(-16773785)) == @bitReverse(i32, neg32));
 }
test/stage1/behavior/bswap.zig
@@ -1,32 +0,0 @@
-const std = @import("std");
-const expect = std.testing.expect;
-
-test "@bswap" {
-    comptime testByteSwap();
-    testByteSwap();
-}
-
-fn testByteSwap() void {
-    expect(@bswap(u0, 0) == 0);
-    expect(@bswap(u8, 0x12) == 0x12);
-    expect(@bswap(u16, 0x1234) == 0x3412);
-    expect(@bswap(u24, 0x123456) == 0x563412);
-    expect(@bswap(u32, 0x12345678) == 0x78563412);
-    expect(@bswap(u40, 0x123456789a) == 0x9a78563412);
-    expect(@bswap(u48, 0x123456789abc) == 0xbc9a78563412);
-    expect(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412);
-    expect(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
-    expect(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
-
-    expect(@bswap(i0, 0) == 0);
-    expect(@bswap(i8, -50) == -50);
-    expect(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
-    expect(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
-    expect(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
-    expect(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412)));
-    expect(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
-    expect(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
-    expect(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
-    expect(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
-        @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
-}
test/stage1/behavior/byteswap.zig
@@ -0,0 +1,32 @@
+const std = @import("std");
+const expect = std.testing.expect;
+
+test "@byteSwap" {
+    comptime testByteSwap();
+    testByteSwap();
+}
+
+fn testByteSwap() void {
+    expect(@byteSwap(u0, u0(0)) == 0);
+    expect(@byteSwap(u8, u8(0x12)) == 0x12);
+    expect(@byteSwap(u16, u16(0x1234)) == 0x3412);
+    expect(@byteSwap(u24, u24(0x123456)) == 0x563412);
+    expect(@byteSwap(u32, u32(0x12345678)) == 0x78563412);
+    expect(@byteSwap(u40, u40(0x123456789a)) == 0x9a78563412);
+    expect(@byteSwap(i48, u48(0x123456789abc)) == @bitCast(i48, u48(0xbc9a78563412)));
+    expect(@byteSwap(u56, u56(0x123456789abcde)) == 0xdebc9a78563412);
+    expect(@byteSwap(u64, u64(0x123456789abcdef1)) == 0xf1debc9a78563412);
+    expect(@byteSwap(u128, u128(0x123456789abcdef11121314151617181)) == 0x8171615141312111f1debc9a78563412);
+
+    expect(@byteSwap(u0, u0(0)) == 0);
+    expect(@byteSwap(i8, i8(-50)) == -50);
+    expect(@byteSwap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
+    expect(@byteSwap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
+    expect(@byteSwap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
+    expect(@byteSwap(u40, @bitCast(i40, u40(0x123456789a))) == u40(0x9a78563412));
+    expect(@byteSwap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
+    expect(@byteSwap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
+    expect(@byteSwap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
+    expect(@byteSwap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
+        @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
+}
test/stage1/behavior/math.zig
@@ -114,15 +114,16 @@ test "@clz" {
 }
 
 fn testClz() void {
-    expect(clz(u8(0b00001010)) == 4);
-    expect(clz(u8(0b10001010)) == 0);
-    expect(clz(u8(0b00000000)) == 8);
-    expect(clz(u128(0xffffffffffffffff)) == 64);
-    expect(clz(u128(0x10000000000000000)) == 63);
+    expect(clz(u8, u8(0b10001010)) == 0);
+    expect(clz(u8, u8(0b00001010)) == 4);
+    expect(clz(u8, u8(0b00011010)) == 3);
+    expect(clz(u8, u8(0b00000000)) == 8);
+    expect(clz(u128, u128(0xffffffffffffffff)) == 64);
+    expect(clz(u128, u128(0x10000000000000000)) == 63);
 }
 
-fn clz(x: var) usize {
-    return @clz(x);
+fn clz(comptime T: type, x: T) usize {
+    return @clz(T, x);
 }
 
 test "@ctz" {
@@ -131,13 +132,25 @@ test "@ctz" {
 }
 
 fn testCtz() void {
-    expect(ctz(u8(0b10100000)) == 5);
-    expect(ctz(u8(0b10001010)) == 1);
-    expect(ctz(u8(0b00000000)) == 8);
+    expect(ctz(u8, u8(0b10100000)) == 5);
+    expect(ctz(u8, u8(0b10001010)) == 1);
+    expect(ctz(u8, u8(0b00000000)) == 8);
+    expect(ctz(u16, u16(0b00000000)) == 16);
 }
 
-fn ctz(x: var) usize {
-    return @ctz(x);
+fn ctz(comptime T: type, x: T) usize {
+    return @ctz(T, x);
+}
+
+pub fn Log2Int(comptime T: type) type {
+    // comptime ceil log2
+    comptime var count = 0;
+    comptime var s = T.bit_count - 1;
+    inline while (s != 0) : (s >>= 1) {
+        count += 1;
+    }
+
+    return @IntType(false, count);
 }
 
 test "assignment operators" {
test/stage1/behavior/popcount.zig
@@ -6,20 +6,39 @@ test "@popCount" {
 }
 
 fn testPopCount() void {
+    {
+        var x: u32 = 0xffffffff;
+        expect(@popCount(u32, x) == 32);
+    }
+    {
+        var x: u5 = 0x1f;
+        expect(@popCount(u5, x) == 5);
+    }
     {
         var x: u32 = 0xaa;
-        expect(@popCount(x) == 4);
+        expect(@popCount(u32, x) == 4);
     }
     {
         var x: u32 = 0xaaaaaaaa;
-        expect(@popCount(x) == 16);
+        expect(@popCount(u32, x) == 16);
+    }
+    {
+        var x: u32 = 0xaaaaaaaa;
+        expect(@popCount(u32, x) == 16);
     }
     {
         var x: i16 = -1;
-        expect(@popCount(x) == 16);
+        expect(@popCount(i16, x) == 16);
+    }
+    {
+        var x: i8 = -120;
+        expect(@popCount(i8, x) == 2);
+    }
+    comptime {
+        expect(@popCount(u8, @bitCast(u8, i8(-120))) == 2);
     }
     comptime {
-        expect(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24);
+        expect(@popCount(i128, u128(0b11111111000110001100010000100001000011000011100101010001)) == 24);
     }
 }
 
test/stage1/behavior.zig
@@ -8,7 +8,7 @@ comptime {
     _ = @import("behavior/bitcast.zig");
     _ = @import("behavior/bitreverse.zig");
     _ = @import("behavior/bool.zig");
-    _ = @import("behavior/bswap.zig");
+    _ = @import("behavior/byteswap.zig");
     _ = @import("behavior/bugs/1025.zig");
     _ = @import("behavior/bugs/1076.zig");
     _ = @import("behavior/bugs/1111.zig");
test/compile_errors.zig
@@ -1363,21 +1363,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
     cases.add(
         "@popCount - non-integer",
         \\export fn entry(x: f32) u32 {
-        \\    return @popCount(x);
+        \\    return @popCount(f32, x);
         \\}
     ,
         "tmp.zig:2:22: error: expected integer type, found 'f32'",
     );
 
-    cases.add(
-        "@popCount - negative comptime_int",
-        \\comptime {
-        \\    _ = @popCount(-1);
-        \\}
-    ,
-        "tmp.zig:2:9: error: @popCount on negative comptime_int value -1",
-    );
-
     cases.addCase(x: {
         const tc = cases.create(
             "wrong same named struct",