From 3273fd7763460c39597ad6cd1bb9979f8ba900e3 Mon Sep 17 00:00:00 2001 From: flywind Date: Mon, 8 Mar 2021 20:28:28 +0800 Subject: [PATCH 01/15] improve test coverage for isolation --- tests/stdlib/isolation.nim | 16 ------ tests/stdlib/tisolation.nim | 99 +++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 16 deletions(-) delete mode 100644 tests/stdlib/isolation.nim create mode 100644 tests/stdlib/tisolation.nim diff --git a/tests/stdlib/isolation.nim b/tests/stdlib/isolation.nim deleted file mode 100644 index 6fbadda75c545..0000000000000 --- a/tests/stdlib/isolation.nim +++ /dev/null @@ -1,16 +0,0 @@ -discard """ - targets: "c cpp js" -""" - -import std/[json, isolation] - - -proc main() = - var x: seq[Isolated[JsonNode]] - x.add isolate(newJString("1234")) - - doAssert $x == """@[(value: "1234")]""" - - -static: main() -main() diff --git a/tests/stdlib/tisolation.nim b/tests/stdlib/tisolation.nim new file mode 100644 index 0000000000000..58422426f2ff5 --- /dev/null +++ b/tests/stdlib/tisolation.nim @@ -0,0 +1,99 @@ +discard """ + targets: "c cpp" + matrix: "--gc:refc; --gc:orc" +""" + +import std/[isolation, json] + + +proc main() = + block: # string literals + var data = isolate("string") + doAssert data.extract == "string" + doAssert data.extract == "" + + block: + var src = "string" + var data = isolate(move src) + doAssert data.extract == "string" + doAssert src.len == 0 + + block: # int literals + var data = isolate(1) + doAssert data.extract == 1 + doAssert data.extract == 0 + + block: # float literals + var data = isolate(1.6) + doAssert data.extract == 1.6 + doAssert data.extract == 0.0 + + block: + var data = isolate(@["1", "2"]) + doAssert data.extract == @["1", "2"] + doAssert data.extract == @[] + + block: + var src = @["1", "2"] + var data = isolate(move src) + doAssert data.extract == @["1", "2"] + doAssert src.len == 0 + + block: + var data = isolate(@[1, 2]) + doAssert data.extract == @[1, 2] + doAssert data.extract == @[] + + block: + var data = isolate(["1", "2"]) + doAssert data.extract == ["1", "2"] + doAssert data.extract == ["", ""] + + block: + var data = isolate([1, 2]) + doAssert data.extract == [1, 2] + doAssert data.extract == [0, 0] + + block: + type + Test = object + id: int + + var data = isolate(Test(id: 12)) + doAssert data.extract.id == 12 + + block: + type + Test = object + id: int + + var src = Test(id: 12) + var data = isolate(src) + doAssert data.extract.id == 12 + + block: + type + Test = object + id: int + + var src = Test(id: 12) + var data = isolate(move src) + doAssert data.extract.id == 12 + + block: + type + Test = ref object + id: int + + var data = isolate(Test(id: 12)) + doAssert data.extract.id == 12 + + block: + var x: seq[Isolated[JsonNode]] + x.add isolate(newJString("1234")) + + doAssert $x == """@[(value: "1234")]""" + + +static: main() +main() From b4fa4323df9c123b6ba3ca894e456ed09ace2868 Mon Sep 17 00:00:00 2001 From: flywind Date: Mon, 8 Mar 2021 20:32:09 +0800 Subject: [PATCH 02/15] a bit better --- tests/stdlib/tisolation.nim | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/stdlib/tisolation.nim b/tests/stdlib/tisolation.nim index 58422426f2ff5..11c51fe05137d 100644 --- a/tests/stdlib/tisolation.nim +++ b/tests/stdlib/tisolation.nim @@ -6,12 +6,18 @@ discard """ import std/[isolation, json] + proc main() = block: # string literals var data = isolate("string") doAssert data.extract == "string" doAssert data.extract == "" + block: # string literals + var data = isolate("") + doAssert data.extract == "" + doAssert data.extract == "" + block: var src = "string" var data = isolate(move src) @@ -33,6 +39,16 @@ proc main() = doAssert data.extract == @["1", "2"] doAssert data.extract == @[] + block: + var data = isolate(@["1", "2", "3", "4", "5"]) + doAssert data.extract == @["1", "2", "3", "4", "5"] + doAssert data.extract == @[] + + block: + var data = isolate(@["", ""]) + doAssert data.extract == @["", ""] + doAssert data.extract == @[] + block: var src = @["1", "2"] var data = isolate(move src) From 9742117cbc9389094e485e6bfd215966d2d87cab Mon Sep 17 00:00:00 2001 From: flywind Date: Thu, 11 Mar 2021 15:28:23 +0800 Subject: [PATCH 03/15] close #11330 --- lib/pure/bitops.nim | 157 +++--------------------------------- lib/std/private/vmutils.nim | 17 ++++ lib/system/sets.nim | 142 +++++++++++++++++++++++++++++++- 3 files changed, 164 insertions(+), 152 deletions(-) create mode 100644 lib/std/private/vmutils.nim diff --git a/lib/pure/bitops.nim b/lib/pure/bitops.nim index b75b0cf9aca0e..6dedf6c5b9ebd 100644 --- a/lib/pure/bitops.nim +++ b/lib/pure/bitops.nim @@ -27,6 +27,13 @@ import macros import std/private/since +from std/private/vmutils import forwardImpl, toUnsigned + + +# sets.nim cannot import bitops, but bitops can use include +# system/sets to eliminate code duplication. sets.nim defines +# countBits32 and countBits64. +include system/sets func bitnot*[T: SomeInteger](x: T): T {.magic: "BitnotI".} ## Computes the `bitwise complement` of the integer `x`. @@ -58,34 +65,12 @@ macro bitxor*[T: SomeInteger](x, y: T; z: varargs[T]): T = for extra in z: result = newCall(fn, result, extra) -const useBuiltins = not defined(noIntrinsicsBitOpts) -const noUndefined = defined(noUndefinedBitOpts) -const useGCC_builtins = (defined(gcc) or defined(llvm_gcc) or - defined(clang)) and useBuiltins -const useICC_builtins = defined(icc) and useBuiltins -const useVCC_builtins = defined(vcc) and useBuiltins + const arch64 = sizeof(int) == 8 const useBuiltinsRotate = (defined(amd64) or defined(i386)) and (defined(gcc) or defined(clang) or defined(vcc) or (defined(icl) and not defined(cpp))) and useBuiltins -template toUnsigned(x: int8): uint8 = cast[uint8](x) -template toUnsigned(x: int16): uint16 = cast[uint16](x) -template toUnsigned(x: int32): uint32 = cast[uint32](x) -template toUnsigned(x: int64): uint64 = cast[uint64](x) -template toUnsigned(x: int): uint = cast[uint](x) - -template forwardImpl(impl, arg) {.dirty.} = - when sizeof(x) <= 4: - when x is SomeSignedInt: - impl(cast[uint32](x.int32)) - else: - impl(x.uint32) - else: - when x is SomeSignedInt: - impl(cast[uint64](x.int64)) - else: - impl(x.uint64) type BitsRange*[T] = range[0..sizeof(T)*8-1] ## A range with all bit positions for type `T`. @@ -436,134 +421,10 @@ func fastlog2Nim(x: uint64): int {.inline.} = v = v or v shr 32 result = lookup[(v * 0x03F6EAF2CD271461'u64) shr 58].int -# sets.nim cannot import bitops, but bitops can use include -# system/sets to eliminate code duplication. sets.nim defines -# countBits32 and countBits64. -include system/sets - -template countSetBitsNim(n: uint32): int = countBits32(n) -template countSetBitsNim(n: uint64): int = countBits64(n) - -template parityImpl[T](value: T): int = - # formula id from: https://graphics.stanford.edu/%7Eseander/bithacks.html#ParityParallel - var v = value - when sizeof(T) == 8: - v = v xor (v shr 32) - when sizeof(T) >= 4: - v = v xor (v shr 16) - when sizeof(T) >= 2: - v = v xor (v shr 8) - v = v xor (v shr 4) - v = v and 0xf - ((0x6996'u shr v) and 1).int - - -when useGCC_builtins: - # Returns the number of set 1-bits in value. - proc builtin_popcount(x: cuint): cint {.importc: "__builtin_popcount", cdecl.} - proc builtin_popcountll(x: culonglong): cint {. - importc: "__builtin_popcountll", cdecl.} - - # Returns the bit parity in value - proc builtin_parity(x: cuint): cint {.importc: "__builtin_parity", cdecl.} - proc builtin_parityll(x: culonglong): cint {.importc: "__builtin_parityll", cdecl.} - - # Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero. - proc builtin_ffs(x: cint): cint {.importc: "__builtin_ffs", cdecl.} - proc builtin_ffsll(x: clonglong): cint {.importc: "__builtin_ffsll", cdecl.} - - # Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. - proc builtin_clz(x: cuint): cint {.importc: "__builtin_clz", cdecl.} - proc builtin_clzll(x: culonglong): cint {.importc: "__builtin_clzll", cdecl.} - - # Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. - proc builtin_ctz(x: cuint): cint {.importc: "__builtin_ctz", cdecl.} - proc builtin_ctzll(x: culonglong): cint {.importc: "__builtin_ctzll", cdecl.} - -elif useVCC_builtins: - # Counts the number of one bits (population count) in a 16-, 32-, or 64-byte unsigned integer. - func builtin_popcnt16(a2: uint16): uint16 {. - importc: "__popcnt16", header: "".} - func builtin_popcnt32(a2: uint32): uint32 {. - importc: "__popcnt", header: "".} - func builtin_popcnt64(a2: uint64): uint64 {. - importc: "__popcnt64", header: "".} - - # Search the mask data from most significant bit (MSB) to least significant bit (LSB) for a set bit (1). - func bitScanReverse(index: ptr culong, mask: culong): cuchar {. - importc: "_BitScanReverse", header: "".} - func bitScanReverse64(index: ptr culong, mask: uint64): cuchar {. - importc: "_BitScanReverse64", header: "".} - - # Search the mask data from least significant bit (LSB) to the most significant bit (MSB) for a set bit (1). - func bitScanForward(index: ptr culong, mask: culong): cuchar {. - importc: "_BitScanForward", header: "".} - func bitScanForward64(index: ptr culong, mask: uint64): cuchar {. - importc: "_BitScanForward64", header: "".} - - template vcc_scan_impl(fnc: untyped; v: untyped): int = - var index: culong - discard fnc(index.addr, v) - index.int - -elif useICC_builtins: - - # Intel compiler intrinsics: http://fulla.fnal.gov/intel/compiler_c/main_cls/intref_cls/common/intref_allia_misc.htm - # see also: https://software.intel.com/en-us/node/523362 - # Count the number of bits set to 1 in an integer a, and return that count in dst. - func builtin_popcnt32(a: cint): cint {. - importc: "_popcnt", header: "".} - func builtin_popcnt64(a: uint64): cint {. - importc: "_popcnt64", header: "".} - - # Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. - func bitScanForward(p: ptr uint32, b: uint32): cuchar {. - importc: "_BitScanForward", header: "".} - func bitScanForward64(p: ptr uint32, b: uint64): cuchar {. - importc: "_BitScanForward64", header: "".} - - # Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. - func bitScanReverse(p: ptr uint32, b: uint32): cuchar {. - importc: "_BitScanReverse", header: "".} - func bitScanReverse64(p: ptr uint32, b: uint64): cuchar {. - importc: "_BitScanReverse64", header: "".} - - template icc_scan_impl(fnc: untyped; v: untyped): int = - var index: uint32 - discard fnc(index.addr, v) - index.int - func countSetBits*(x: SomeInteger): int {.inline.} = ## Counts the set bits in an integer (also called `Hamming weight`:idx:). - runnableExamples: - doAssert countSetBits(0b0000_0011'u8) == 2 - doAssert countSetBits(0b1010_1010'u8) == 4 - - # TODO: figure out if ICC support _popcnt32/_popcnt64 on platform without POPCNT. - # like GCC and MSVC - when x is SomeSignedInt: - let x = x.toUnsigned - when nimvm: - result = forwardImpl(countSetBitsNim, x) - else: - when useGCC_builtins: - when sizeof(x) <= 4: result = builtin_popcount(x.cuint).int - else: result = builtin_popcountll(x.culonglong).int - elif useVCC_builtins: - when sizeof(x) <= 2: result = builtin_popcnt16(x.uint16).int - elif sizeof(x) <= 4: result = builtin_popcnt32(x.uint32).int - elif arch64: result = builtin_popcnt64(x.uint64).int - else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).uint32).int + - builtin_popcnt32((x.uint64 shr 32'u64).uint32).int - elif useICC_builtins: - when sizeof(x) <= 4: result = builtin_popcnt32(x.cint).int - elif arch64: result = builtin_popcnt64(x.uint64).int - else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).cint).int + - builtin_popcnt32((x.uint64 shr 32'u64).cint).int - else: - when sizeof(x) <= 4: result = countSetBitsNim(x.uint32) - else: result = countSetBitsNim(x.uint64) + result = countSetBitsImpl(x) func popcount*(x: SomeInteger): int {.inline.} = ## Alias for `countSetBits <#countSetBits,SomeInteger>`_ (Hamming weight). diff --git a/lib/std/private/vmutils.nim b/lib/std/private/vmutils.nim new file mode 100644 index 0000000000000..d54977b4e23a5 --- /dev/null +++ b/lib/std/private/vmutils.nim @@ -0,0 +1,17 @@ +template forwardImpl*(impl, arg) {.dirty.} = + when sizeof(x) <= 4: + when x is SomeSignedInt: + impl(cast[uint32](x.int32)) + else: + impl(x.uint32) + else: + when x is SomeSignedInt: + impl(cast[uint64](x.int64)) + else: + impl(x.uint64) + +template toUnsigned*(x: int8): uint8 = cast[uint8](x) +template toUnsigned*(x: int16): uint16 = cast[uint16](x) +template toUnsigned*(x: int32): uint32 = cast[uint32](x) +template toUnsigned*(x: int64): uint64 = cast[uint64](x) +template toUnsigned*(x: int): uint = cast[uint](x) diff --git a/lib/system/sets.nim b/lib/system/sets.nim index 42c4488486490..8770259fd2c26 100644 --- a/lib/system/sets.nim +++ b/lib/system/sets.nim @@ -8,26 +8,160 @@ # # set handling +from std/private/vmutils import forwardImpl, toUnsigned + + +const useBuiltins = not defined(noIntrinsicsBitOpts) +const noUndefined {.used.} = defined(noUndefinedBitOpts) +const useGCC_builtins = (defined(gcc) or defined(llvm_gcc) or + defined(clang)) and useBuiltins +const useICC_builtins = defined(icc) and useBuiltins +const useVCC_builtins = defined(vcc) and useBuiltins type NimSet = array[0..4*2048-1, uint8] # bitops can't be imported here, therefore the code duplication. -proc countBits32(n: uint32): int {.compilerproc.} = +template countBitsImpl(n: uint32): int = # generic formula is from: https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel var v = uint32(n) v = v - ((v shr 1'u32) and 0x55555555'u32) v = (v and 0x33333333'u32) + ((v shr 2'u32) and 0x33333333'u32) - result = (((v + (v shr 4'u32) and 0xF0F0F0F'u32) * 0x1010101'u32) shr 24'u32).int + (((v + (v shr 4'u32) and 0xF0F0F0F'u32) * 0x1010101'u32) shr 24'u32).int -proc countBits64(n: uint64): int {.compilerproc, inline.} = +template countBitsImpl(n: uint64): int = # generic formula is from: https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel var v = uint64(n) v = v - ((v shr 1'u64) and 0x5555555555555555'u64) v = (v and 0x3333333333333333'u64) + ((v shr 2'u64) and 0x3333333333333333'u64) v = (v + (v shr 4'u64) and 0x0F0F0F0F0F0F0F0F'u64) - result = ((v * 0x0101010101010101'u64) shr 56'u64).int + ((v * 0x0101010101010101'u64) shr 56'u64).int + +template parityImpl[T](value: T): int = + # formula id from: https://graphics.stanford.edu/%7Eseander/bithacks.html#ParityParallel + var v = value + when sizeof(T) == 8: + v = v xor (v shr 32) + when sizeof(T) >= 4: + v = v xor (v shr 16) + when sizeof(T) >= 2: + v = v xor (v shr 8) + v = v xor (v shr 4) + v = v and 0xf + ((0x6996'u shr v) and 1).int + +when useGCC_builtins: + # Returns the number of set 1-bits in value. + proc builtin_popcount(x: cuint): cint {.importc: "__builtin_popcount", cdecl.} + proc builtin_popcountll(x: culonglong): cint {. + importc: "__builtin_popcountll", cdecl.} + + # Returns the bit parity in value + proc builtin_parity(x: cuint): cint {.importc: "__builtin_parity", cdecl.} + proc builtin_parityll(x: culonglong): cint {.importc: "__builtin_parityll", cdecl.} + + # Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero. + proc builtin_ffs(x: cint): cint {.importc: "__builtin_ffs", cdecl.} + proc builtin_ffsll(x: clonglong): cint {.importc: "__builtin_ffsll", cdecl.} + + # Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. + proc builtin_clz(x: cuint): cint {.importc: "__builtin_clz", cdecl.} + proc builtin_clzll(x: culonglong): cint {.importc: "__builtin_clzll", cdecl.} + + # Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. + proc builtin_ctz(x: cuint): cint {.importc: "__builtin_ctz", cdecl.} + proc builtin_ctzll(x: culonglong): cint {.importc: "__builtin_ctzll", cdecl.} + +elif useVCC_builtins: + # Counts the number of one bits (population count) in a 16-, 32-, or 64-byte unsigned integer. + func builtin_popcnt16(a2: uint16): uint16 {. + importc: "__popcnt16", header: "".} + func builtin_popcnt32(a2: uint32): uint32 {. + importc: "__popcnt", header: "".} + func builtin_popcnt64(a2: uint64): uint64 {. + importc: "__popcnt64", header: "".} + + # Search the mask data from most significant bit (MSB) to least significant bit (LSB) for a set bit (1). + func bitScanReverse(index: ptr culong, mask: culong): cuchar {. + importc: "_BitScanReverse", header: "".} + func bitScanReverse64(index: ptr culong, mask: uint64): cuchar {. + importc: "_BitScanReverse64", header: "".} + + # Search the mask data from least significant bit (LSB) to the most significant bit (MSB) for a set bit (1). + func bitScanForward(index: ptr culong, mask: culong): cuchar {. + importc: "_BitScanForward", header: "".} + func bitScanForward64(index: ptr culong, mask: uint64): cuchar {. + importc: "_BitScanForward64", header: "".} + + template vcc_scan_impl(fnc: untyped; v: untyped): int = + var index: culong + discard fnc(index.addr, v) + index.int + +elif useICC_builtins: + + # Intel compiler intrinsics: http://fulla.fnal.gov/intel/compiler_c/main_cls/intref_cls/common/intref_allia_misc.htm + # see also: https://software.intel.com/en-us/node/523362 + # Count the number of bits set to 1 in an integer a, and return that count in dst. + func builtin_popcnt32(a: cint): cint {. + importc: "_popcnt", header: "".} + func builtin_popcnt64(a: uint64): cint {. + importc: "_popcnt64", header: "".} + + # Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. + func bitScanForward(p: ptr uint32, b: uint32): cuchar {. + importc: "_BitScanForward", header: "".} + func bitScanForward64(p: ptr uint32, b: uint64): cuchar {. + importc: "_BitScanForward64", header: "".} + + # Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. + func bitScanReverse(p: ptr uint32, b: uint32): cuchar {. + importc: "_BitScanReverse", header: "".} + func bitScanReverse64(p: ptr uint32, b: uint64): cuchar {. + importc: "_BitScanReverse64", header: "".} + + template icc_scan_impl(fnc: untyped; v: untyped): int = + var index: uint32 + discard fnc(index.addr, v) + index.int + +func countSetBitsImpl(x: SomeInteger): int {.inline.} = + ## Counts the set bits in an integer (also called `Hamming weight`:idx:). + runnableExamples: + doAssert countSetBits(0b0000_0011'u8) == 2 + doAssert countSetBits(0b1010_1010'u8) == 4 + + # TODO: figure out if ICC support _popcnt32/_popcnt64 on platform without POPCNT. + # like GCC and MSVC + when x is SomeSignedInt: + let x = x.toUnsigned + when nimvm: + result = forwardImpl(countBitsImpl, x) + else: + when useGCC_builtins: + when sizeof(x) <= 4: result = builtin_popcount(x.cuint).int + else: result = builtin_popcountll(x.culonglong).int + elif useVCC_builtins: + when sizeof(x) <= 2: result = builtin_popcnt16(x.uint16).int + elif sizeof(x) <= 4: result = builtin_popcnt32(x.uint32).int + elif arch64: result = builtin_popcnt64(x.uint64).int + else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).uint32).int + + builtin_popcnt32((x.uint64 shr 32'u64).uint32).int + elif useICC_builtins: + when sizeof(x) <= 4: result = builtin_popcnt32(x.cint).int + elif arch64: result = builtin_popcnt64(x.uint64).int + else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).cint).int + + builtin_popcnt32((x.uint64 shr 32'u64).cint).int + else: + when sizeof(x) <= 4: result = countBitsImpl(x.uint32) + else: result = countBitsImpl(x.uint64) + +proc countBits32(n: uint32): int {.compilerProc.} = + result = countSetBitsImpl(n) + +proc countBits64(n: uint64): int {.compilerProc.} = + result = countSetBitsImpl(n) proc cardSet(s: NimSet, len: int): int {.compilerproc, inline.} = var i = 0 From fad4cbca8a84dfc8d3f7762a449fe879f1579df9 Mon Sep 17 00:00:00 2001 From: flywind Date: Thu, 11 Mar 2021 15:39:23 +0800 Subject: [PATCH 04/15] fix style --- lib/system/sets.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/system/sets.nim b/lib/system/sets.nim index 8770259fd2c26..64769b9554d2a 100644 --- a/lib/system/sets.nim +++ b/lib/system/sets.nim @@ -157,10 +157,10 @@ func countSetBitsImpl(x: SomeInteger): int {.inline.} = when sizeof(x) <= 4: result = countBitsImpl(x.uint32) else: result = countBitsImpl(x.uint64) -proc countBits32(n: uint32): int {.compilerProc.} = +proc countBits32(n: uint32): int {.compilerproc.} = result = countSetBitsImpl(n) -proc countBits64(n: uint64): int {.compilerProc.} = +proc countBits64(n: uint64): int {.compilerproc.} = result = countSetBitsImpl(n) proc cardSet(s: NimSet, len: int): int {.compilerproc, inline.} = From e2ca382678f9b9265c2c3843eb1ec4f0482d8571 Mon Sep 17 00:00:00 2001 From: flywind Date: Thu, 11 Mar 2021 15:55:14 +0800 Subject: [PATCH 05/15] impl --- lib/pure/bitops.nim | 14 +++++++++++++- lib/system/sets.nim | 29 ++++++++++++++++------------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/lib/pure/bitops.nim b/lib/pure/bitops.nim index 6dedf6c5b9ebd..340017aab45d3 100644 --- a/lib/pure/bitops.nim +++ b/lib/pure/bitops.nim @@ -33,7 +33,7 @@ from std/private/vmutils import forwardImpl, toUnsigned # sets.nim cannot import bitops, but bitops can use include # system/sets to eliminate code duplication. sets.nim defines # countBits32 and countBits64. -include system/sets +import system/sets func bitnot*[T: SomeInteger](x: T): T {.magic: "BitnotI".} ## Computes the `bitwise complement` of the integer `x`. @@ -421,6 +421,18 @@ func fastlog2Nim(x: uint64): int {.inline.} = v = v or v shr 32 result = lookup[(v * 0x03F6EAF2CD271461'u64) shr 58].int +template parityImpl[T](value: T): int = + # formula id from: https://graphics.stanford.edu/%7Eseander/bithacks.html#ParityParallel + var v = value + when sizeof(T) == 8: + v = v xor (v shr 32) + when sizeof(T) >= 4: + v = v xor (v shr 16) + when sizeof(T) >= 2: + v = v xor (v shr 8) + v = v xor (v shr 4) + v = v and 0xf + ((0x6996'u shr v) and 1).int func countSetBits*(x: SomeInteger): int {.inline.} = ## Counts the set bits in an integer (also called `Hamming weight`:idx:). diff --git a/lib/system/sets.nim b/lib/system/sets.nim index 64769b9554d2a..b97593408c42a 100644 --- a/lib/system/sets.nim +++ b/lib/system/sets.nim @@ -12,7 +12,7 @@ from std/private/vmutils import forwardImpl, toUnsigned const useBuiltins = not defined(noIntrinsicsBitOpts) -const noUndefined {.used.} = defined(noUndefinedBitOpts) +const noUndefined = defined(noUndefinedBitOpts) const useGCC_builtins = (defined(gcc) or defined(llvm_gcc) or defined(clang)) and useBuiltins const useICC_builtins = defined(icc) and useBuiltins @@ -38,18 +38,6 @@ template countBitsImpl(n: uint64): int = v = (v + (v shr 4'u64) and 0x0F0F0F0F0F0F0F0F'u64) ((v * 0x0101010101010101'u64) shr 56'u64).int -template parityImpl[T](value: T): int = - # formula id from: https://graphics.stanford.edu/%7Eseander/bithacks.html#ParityParallel - var v = value - when sizeof(T) == 8: - v = v xor (v shr 32) - when sizeof(T) >= 4: - v = v xor (v shr 16) - when sizeof(T) >= 2: - v = v xor (v shr 8) - v = v xor (v shr 4) - v = v and 0xf - ((0x6996'u shr v) and 1).int when useGCC_builtins: # Returns the number of set 1-bits in value. @@ -174,3 +162,18 @@ proc cardSet(s: NimSet, len: int): int {.compilerproc, inline.} = while i < len: inc(result, countBits32(uint32(s[i]))) inc(i, 1) + + +when not declared(ThisIsSystem): + export useBuiltins, noUndefined, useGCC_builtins, useICC_builtins, useVCC_builtins + export countSetBitsImpl + + when useGCC_builtins: + export builtin_clz, builtin_clzll, builtin_parity, builtin_parityll, builtin_ffs, builtin_ffsll, + builtin_ctz, builtin_ctzll + + elif useVCC_builtins: + export bitScanReverse, bitScanReverse64, bitScanForward, bitScanForward64, vcc_scan_impl + + elif useICC_builtins: + export bitScanForward, bitScanForward64, bitScanReverse, bitScanReverse64, icc_scan_impl From 318be4593941aab254f2656aad331cc29df0bee6 Mon Sep 17 00:00:00 2001 From: flywind Date: Thu, 11 Mar 2021 15:58:25 +0800 Subject: [PATCH 06/15] inline --- lib/system/sets.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/system/sets.nim b/lib/system/sets.nim index b97593408c42a..515aabc7a240a 100644 --- a/lib/system/sets.nim +++ b/lib/system/sets.nim @@ -145,10 +145,10 @@ func countSetBitsImpl(x: SomeInteger): int {.inline.} = when sizeof(x) <= 4: result = countBitsImpl(x.uint32) else: result = countBitsImpl(x.uint64) -proc countBits32(n: uint32): int {.compilerproc.} = +proc countBits32(n: uint32): int {.compilerproc, inline.} = result = countSetBitsImpl(n) -proc countBits64(n: uint64): int {.compilerproc.} = +proc countBits64(n: uint64): int {.compilerproc, inline.} = result = countSetBitsImpl(n) proc cardSet(s: NimSet, len: int): int {.compilerproc, inline.} = From 7975490af64d5b61944e834729b9beaa25ca92bf Mon Sep 17 00:00:00 2001 From: flywind Date: Thu, 11 Mar 2021 16:10:04 +0800 Subject: [PATCH 07/15] import --- lib/system.nim | 2 +- lib/system/sets.nim | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 05b1ff9ffe1f7..2f4fffd5a360d 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2339,7 +2339,7 @@ when notJSnotNims: when hostOS != "standalone" and hostOS != "any": include "system/dyncalls" - include "system/sets" + from system/sets import cardSet when defined(gogc): const GenericSeqSize = (3 * sizeof(int)) diff --git a/lib/system/sets.nim b/lib/system/sets.nim index 515aabc7a240a..f8851201728d2 100644 --- a/lib/system/sets.nim +++ b/lib/system/sets.nim @@ -151,7 +151,7 @@ proc countBits32(n: uint32): int {.compilerproc, inline.} = proc countBits64(n: uint64): int {.compilerproc, inline.} = result = countSetBitsImpl(n) -proc cardSet(s: NimSet, len: int): int {.compilerproc, inline.} = +proc cardSet*(s: NimSet, len: int): int {.compilerproc, inline.} = var i = 0 result = 0 when defined(x86) or defined(amd64): From 4b697ad0b4cc33c3f8848350c35673d96914f35b Mon Sep 17 00:00:00 2001 From: flywind Date: Thu, 11 Mar 2021 16:13:39 +0800 Subject: [PATCH 08/15] remove --- lib/system/sets.nim | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/system/sets.nim b/lib/system/sets.nim index f8851201728d2..112c72b86a43f 100644 --- a/lib/system/sets.nim +++ b/lib/system/sets.nim @@ -21,7 +21,6 @@ const useVCC_builtins = defined(vcc) and useBuiltins type NimSet = array[0..4*2048-1, uint8] -# bitops can't be imported here, therefore the code duplication. template countBitsImpl(n: uint32): int = # generic formula is from: https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel From 96de876a0bf45ebaa00620d67669bb70a538e246 Mon Sep 17 00:00:00 2001 From: flywind Date: Thu, 11 Mar 2021 16:57:17 +0800 Subject: [PATCH 09/15] refactor --- lib/pure/bitops.nim | 54 +++++++++++++++++++++++++++++++++++++++++ lib/system/sets.nim | 59 --------------------------------------------- 2 files changed, 54 insertions(+), 59 deletions(-) diff --git a/lib/pure/bitops.nim b/lib/pure/bitops.nim index 340017aab45d3..db031725140f4 100644 --- a/lib/pure/bitops.nim +++ b/lib/pure/bitops.nim @@ -434,6 +434,60 @@ template parityImpl[T](value: T): int = v = v and 0xf ((0x6996'u shr v) and 1).int + +when useGCC_builtins: + # Returns the bit parity in value + proc builtin_parity(x: cuint): cint {.importc: "__builtin_parity", cdecl.} + proc builtin_parityll(x: culonglong): cint {.importc: "__builtin_parityll", cdecl.} + + # Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero. + proc builtin_ffs(x: cint): cint {.importc: "__builtin_ffs", cdecl.} + proc builtin_ffsll(x: clonglong): cint {.importc: "__builtin_ffsll", cdecl.} + + # Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. + proc builtin_clz(x: cuint): cint {.importc: "__builtin_clz", cdecl.} + proc builtin_clzll(x: culonglong): cint {.importc: "__builtin_clzll", cdecl.} + + # Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. + proc builtin_ctz(x: cuint): cint {.importc: "__builtin_ctz", cdecl.} + proc builtin_ctzll(x: culonglong): cint {.importc: "__builtin_ctzll", cdecl.} + +elif useVCC_builtins: + # Search the mask data from most significant bit (MSB) to least significant bit (LSB) for a set bit (1). + func bitScanReverse(index: ptr culong, mask: culong): cuchar {. + importc: "_BitScanReverse", header: "".} + func bitScanReverse64(index: ptr culong, mask: uint64): cuchar {. + importc: "_BitScanReverse64", header: "".} + + # Search the mask data from least significant bit (LSB) to the most significant bit (MSB) for a set bit (1). + func bitScanForward(index: ptr culong, mask: culong): cuchar {. + importc: "_BitScanForward", header: "".} + func bitScanForward64(index: ptr culong, mask: uint64): cuchar {. + importc: "_BitScanForward64", header: "".} + + template vcc_scan_impl(fnc: untyped; v: untyped): int = + var index: culong + discard fnc(index.addr, v) + index.int + +elif useICC_builtins: + # Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. + func bitScanForward(p: ptr uint32, b: uint32): cuchar {. + importc: "_BitScanForward", header: "".} + func bitScanForward64(p: ptr uint32, b: uint64): cuchar {. + importc: "_BitScanForward64", header: "".} + + # Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. + func bitScanReverse(p: ptr uint32, b: uint32): cuchar {. + importc: "_BitScanReverse", header: "".} + func bitScanReverse64(p: ptr uint32, b: uint64): cuchar {. + importc: "_BitScanReverse64", header: "".} + + template icc_scan_impl(fnc: untyped; v: untyped): int = + var index: uint32 + discard fnc(index.addr, v) + index.int + func countSetBits*(x: SomeInteger): int {.inline.} = ## Counts the set bits in an integer (also called `Hamming weight`:idx:). result = countSetBitsImpl(x) diff --git a/lib/system/sets.nim b/lib/system/sets.nim index 112c72b86a43f..c0d274b897663 100644 --- a/lib/system/sets.nim +++ b/lib/system/sets.nim @@ -44,22 +44,6 @@ when useGCC_builtins: proc builtin_popcountll(x: culonglong): cint {. importc: "__builtin_popcountll", cdecl.} - # Returns the bit parity in value - proc builtin_parity(x: cuint): cint {.importc: "__builtin_parity", cdecl.} - proc builtin_parityll(x: culonglong): cint {.importc: "__builtin_parityll", cdecl.} - - # Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero. - proc builtin_ffs(x: cint): cint {.importc: "__builtin_ffs", cdecl.} - proc builtin_ffsll(x: clonglong): cint {.importc: "__builtin_ffsll", cdecl.} - - # Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. - proc builtin_clz(x: cuint): cint {.importc: "__builtin_clz", cdecl.} - proc builtin_clzll(x: culonglong): cint {.importc: "__builtin_clzll", cdecl.} - - # Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. - proc builtin_ctz(x: cuint): cint {.importc: "__builtin_ctz", cdecl.} - proc builtin_ctzll(x: culonglong): cint {.importc: "__builtin_ctzll", cdecl.} - elif useVCC_builtins: # Counts the number of one bits (population count) in a 16-, 32-, or 64-byte unsigned integer. func builtin_popcnt16(a2: uint16): uint16 {. @@ -69,23 +53,6 @@ elif useVCC_builtins: func builtin_popcnt64(a2: uint64): uint64 {. importc: "__popcnt64", header: "".} - # Search the mask data from most significant bit (MSB) to least significant bit (LSB) for a set bit (1). - func bitScanReverse(index: ptr culong, mask: culong): cuchar {. - importc: "_BitScanReverse", header: "".} - func bitScanReverse64(index: ptr culong, mask: uint64): cuchar {. - importc: "_BitScanReverse64", header: "".} - - # Search the mask data from least significant bit (LSB) to the most significant bit (MSB) for a set bit (1). - func bitScanForward(index: ptr culong, mask: culong): cuchar {. - importc: "_BitScanForward", header: "".} - func bitScanForward64(index: ptr culong, mask: uint64): cuchar {. - importc: "_BitScanForward64", header: "".} - - template vcc_scan_impl(fnc: untyped; v: untyped): int = - var index: culong - discard fnc(index.addr, v) - index.int - elif useICC_builtins: # Intel compiler intrinsics: http://fulla.fnal.gov/intel/compiler_c/main_cls/intref_cls/common/intref_allia_misc.htm @@ -96,22 +63,6 @@ elif useICC_builtins: func builtin_popcnt64(a: uint64): cint {. importc: "_popcnt64", header: "".} - # Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined. - func bitScanForward(p: ptr uint32, b: uint32): cuchar {. - importc: "_BitScanForward", header: "".} - func bitScanForward64(p: ptr uint32, b: uint64): cuchar {. - importc: "_BitScanForward64", header: "".} - - # Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined. - func bitScanReverse(p: ptr uint32, b: uint32): cuchar {. - importc: "_BitScanReverse", header: "".} - func bitScanReverse64(p: ptr uint32, b: uint64): cuchar {. - importc: "_BitScanReverse64", header: "".} - - template icc_scan_impl(fnc: untyped; v: untyped): int = - var index: uint32 - discard fnc(index.addr, v) - index.int func countSetBitsImpl(x: SomeInteger): int {.inline.} = ## Counts the set bits in an integer (also called `Hamming weight`:idx:). @@ -166,13 +117,3 @@ proc cardSet*(s: NimSet, len: int): int {.compilerproc, inline.} = when not declared(ThisIsSystem): export useBuiltins, noUndefined, useGCC_builtins, useICC_builtins, useVCC_builtins export countSetBitsImpl - - when useGCC_builtins: - export builtin_clz, builtin_clzll, builtin_parity, builtin_parityll, builtin_ffs, builtin_ffsll, - builtin_ctz, builtin_ctzll - - elif useVCC_builtins: - export bitScanReverse, bitScanReverse64, bitScanForward, bitScanForward64, vcc_scan_impl - - elif useICC_builtins: - export bitScanForward, bitScanForward64, bitScanReverse, bitScanReverse64, icc_scan_impl From 68bdf407a413b3cecf778b85641d6a25361d5d97 Mon Sep 17 00:00:00 2001 From: flywind Date: Sat, 20 Mar 2021 12:09:03 +0800 Subject: [PATCH 10/15] re --- lib/pure/bitops.nim | 10 ++--- lib/system/countbits_impl.nim | 82 +++++++++++++++++++++++++++++++++-- lib/system/sets.nim | 2 +- 3 files changed, 83 insertions(+), 11 deletions(-) diff --git a/lib/pure/bitops.nim b/lib/pure/bitops.nim index ca289c42d9e26..90728da66d9ea 100644 --- a/lib/pure/bitops.nim +++ b/lib/pure/bitops.nim @@ -66,12 +66,6 @@ macro bitxor*[T: SomeInteger](x, y: T; z: varargs[T]): T = result = newCall(fn, result, extra) -const arch64 = sizeof(int) == 8 -const useBuiltinsRotate = (defined(amd64) or defined(i386)) and - (defined(gcc) or defined(clang) or defined(vcc) or - (defined(icl) and not defined(cpp))) and useBuiltins - - type BitsRange*[T] = range[0..sizeof(T)*8-1] ## A range with all bit positions for type `T`. @@ -423,6 +417,10 @@ func fastlog2Nim(x: uint64): int {.inline.} = import system/countbits_impl +const arch64 = sizeof(int) == 8 +const useBuiltinsRotate = (defined(amd64) or defined(i386)) and + (defined(gcc) or defined(clang) or defined(vcc) or + (defined(icl) and not defined(cpp))) and useBuiltins template parityImpl[T](value: T): int = # formula id from: https://graphics.stanford.edu/%7Eseander/bithacks.html#ParityParallel diff --git a/lib/system/countbits_impl.nim b/lib/system/countbits_impl.nim index 6c85612e25ace..ec35d39827d29 100644 --- a/lib/system/countbits_impl.nim +++ b/lib/system/countbits_impl.nim @@ -9,17 +9,91 @@ ## Contains the used algorithms for counting bits. -proc countBits32*(n: uint32): int {.compilerproc.} = +from std/private/vmutils import forwardImpl, toUnsigned + + +const useBuiltins* = not defined(noIntrinsicsBitOpts) +const noUndefined* = defined(noUndefinedBitOpts) +const useGCC_builtins* = (defined(gcc) or defined(llvm_gcc) or + defined(clang)) and useBuiltins +const useICC_builtins* = defined(icc) and useBuiltins +const useVCC_builtins* = defined(vcc) and useBuiltins + +template countBitsImpl(n: uint32): int = # generic formula is from: https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel var v = uint32(n) v = v - ((v shr 1'u32) and 0x55555555'u32) v = (v and 0x33333333'u32) + ((v shr 2'u32) and 0x33333333'u32) - result = (((v + (v shr 4'u32) and 0xF0F0F0F'u32) * 0x1010101'u32) shr 24'u32).int + (((v + (v shr 4'u32) and 0xF0F0F0F'u32) * 0x1010101'u32) shr 24'u32).int -proc countBits64*(n: uint64): int {.compilerproc, inline.} = +template countBitsImpl(n: uint64): int = # generic formula is from: https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel var v = uint64(n) v = v - ((v shr 1'u64) and 0x5555555555555555'u64) v = (v and 0x3333333333333333'u64) + ((v shr 2'u64) and 0x3333333333333333'u64) v = (v + (v shr 4'u64) and 0x0F0F0F0F0F0F0F0F'u64) - result = ((v * 0x0101010101010101'u64) shr 56'u64).int + ((v * 0x0101010101010101'u64) shr 56'u64).int + + +when useGCC_builtins: + # Returns the number of set 1-bits in value. + proc builtin_popcount(x: cuint): cint {.importc: "__builtin_popcount", cdecl.} + proc builtin_popcountll(x: culonglong): cint {. + importc: "__builtin_popcountll", cdecl.} + +elif useVCC_builtins: + # Counts the number of one bits (population count) in a 16-, 32-, or 64-byte unsigned integer. + func builtin_popcnt16(a2: uint16): uint16 {. + importc: "__popcnt16", header: "".} + func builtin_popcnt32(a2: uint32): uint32 {. + importc: "__popcnt", header: "".} + func builtin_popcnt64(a2: uint64): uint64 {. + importc: "__popcnt64", header: "".} + +elif useICC_builtins: + + # Intel compiler intrinsics: http://fulla.fnal.gov/intel/compiler_c/main_cls/intref_cls/common/intref_allia_misc.htm + # see also: https://software.intel.com/en-us/node/523362 + # Count the number of bits set to 1 in an integer a, and return that count in dst. + func builtin_popcnt32(a: cint): cint {. + importc: "_popcnt", header: "".} + func builtin_popcnt64(a: uint64): cint {. + importc: "_popcnt64", header: "".} + + +func countSetBitsImpl*(x: SomeInteger): int {.inline.} = + ## Counts the set bits in an integer (also called `Hamming weight`:idx:). + runnableExamples: + doAssert countSetBits(0b0000_0011'u8) == 2 + doAssert countSetBits(0b1010_1010'u8) == 4 + + # TODO: figure out if ICC support _popcnt32/_popcnt64 on platform without POPCNT. + # like GCC and MSVC + when x is SomeSignedInt: + let x = x.toUnsigned + when nimvm: + result = forwardImpl(countBitsImpl, x) + else: + when useGCC_builtins: + when sizeof(x) <= 4: result = builtin_popcount(x.cuint).int + else: result = builtin_popcountll(x.culonglong).int + elif useVCC_builtins: + when sizeof(x) <= 2: result = builtin_popcnt16(x.uint16).int + elif sizeof(x) <= 4: result = builtin_popcnt32(x.uint32).int + elif arch64: result = builtin_popcnt64(x.uint64).int + else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).uint32).int + + builtin_popcnt32((x.uint64 shr 32'u64).uint32).int + elif useICC_builtins: + when sizeof(x) <= 4: result = builtin_popcnt32(x.cint).int + elif arch64: result = builtin_popcnt64(x.uint64).int + else: result = builtin_popcnt32((x.uint64 and 0xFFFFFFFF'u64).cint).int + + builtin_popcnt32((x.uint64 shr 32'u64).cint).int + else: + when sizeof(x) <= 4: result = countBitsImpl(x.uint32) + else: result = countBitsImpl(x.uint64) + +proc countBits32*(n: uint32): int {.compilerproc, inline.} = + result = countSetBitsImpl(n) + +proc countBits64*(n: uint64): int {.compilerproc, inline.} = + result = countSetBitsImpl(n) diff --git a/lib/system/sets.nim b/lib/system/sets.nim index 34012f4b4d831..f54383d87c210 100644 --- a/lib/system/sets.nim +++ b/lib/system/sets.nim @@ -14,7 +14,7 @@ type NimSet = array[0..4*2048-1, uint8] -proc cardSet(s: NimSet, len: int): int {.compilerproc, inline.} = +proc cardSet*(s: NimSet, len: int): int {.compilerproc, inline.} = var i = 0 result = 0 when defined(x86) or defined(amd64): From 47542c51275f8ad247ce8dd9b37665a59c9d4b6a Mon Sep 17 00:00:00 2001 From: flywind Date: Sun, 21 Mar 2021 10:26:19 +0800 Subject: [PATCH 11/15] impl --- lib/pure/bitops.nim | 6 +++++- lib/system/countbits_impl.nim | 5 ----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/pure/bitops.nim b/lib/pure/bitops.nim index 90728da66d9ea..489940c515527 100644 --- a/lib/pure/bitops.nim +++ b/lib/pure/bitops.nim @@ -30,7 +30,7 @@ import std/private/since from std/private/vmutils import forwardImpl, toUnsigned -# sets.nim cannot import bitops, but bitops can use include +# sets.nim cannot import bitops, but bitops can use import # system/sets to eliminate code duplication. sets.nim defines # countBits32 and countBits64. import system/sets @@ -491,6 +491,10 @@ elif useICC_builtins: func countSetBits*(x: SomeInteger): int {.inline.} = ## Counts the set bits in an integer (also called `Hamming weight`:idx:). + runnableExamples: + doAssert countSetBits(0b0000_0011'u8) == 2 + doAssert countSetBits(0b1010_1010'u8) == 4 + result = countSetBitsImpl(x) func popcount*(x: SomeInteger): int {.inline.} = diff --git a/lib/system/countbits_impl.nim b/lib/system/countbits_impl.nim index ec35d39827d29..d3c003ff7a181 100644 --- a/lib/system/countbits_impl.nim +++ b/lib/system/countbits_impl.nim @@ -51,7 +51,6 @@ elif useVCC_builtins: importc: "__popcnt64", header: "".} elif useICC_builtins: - # Intel compiler intrinsics: http://fulla.fnal.gov/intel/compiler_c/main_cls/intref_cls/common/intref_allia_misc.htm # see also: https://software.intel.com/en-us/node/523362 # Count the number of bits set to 1 in an integer a, and return that count in dst. @@ -63,10 +62,6 @@ elif useICC_builtins: func countSetBitsImpl*(x: SomeInteger): int {.inline.} = ## Counts the set bits in an integer (also called `Hamming weight`:idx:). - runnableExamples: - doAssert countSetBits(0b0000_0011'u8) == 2 - doAssert countSetBits(0b1010_1010'u8) == 4 - # TODO: figure out if ICC support _popcnt32/_popcnt64 on platform without POPCNT. # like GCC and MSVC when x is SomeSignedInt: From 522a8af6c80710718a801675c45b9333dd53ec1f Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 21 Mar 2021 10:57:28 +0100 Subject: [PATCH 12/15] Update lib/pure/bitops.nim --- lib/pure/bitops.nim | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/pure/bitops.nim b/lib/pure/bitops.nim index 489940c515527..377602e75d9a6 100644 --- a/lib/pure/bitops.nim +++ b/lib/pure/bitops.nim @@ -30,10 +30,6 @@ import std/private/since from std/private/vmutils import forwardImpl, toUnsigned -# sets.nim cannot import bitops, but bitops can use import -# system/sets to eliminate code duplication. sets.nim defines -# countBits32 and countBits64. -import system/sets func bitnot*[T: SomeInteger](x: T): T {.magic: "BitnotI".} ## Computes the `bitwise complement` of the integer `x`. From 6917eea44dedf492839be3537a0a1d01de177ea8 Mon Sep 17 00:00:00 2001 From: flywind Date: Sun, 21 Mar 2021 19:23:32 +0800 Subject: [PATCH 13/15] start to fix --- lib/system.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/system.nim b/lib/system.nim index 7e08289080495..0c7bc48c80c8b 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2339,7 +2339,7 @@ when notJSnotNims: when hostOS != "standalone" and hostOS != "any": include "system/dyncalls" - from system/sets import cardSet + include system/sets when defined(gogc): const GenericSeqSize = (3 * sizeof(int)) From 3a1e07129b5deb0841f9b49bf00d32433dd04a82 Mon Sep 17 00:00:00 2001 From: flywind Date: Sun, 21 Mar 2021 19:24:53 +0800 Subject: [PATCH 14/15] Update lib/system/sets.nim --- lib/system/sets.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/system/sets.nim b/lib/system/sets.nim index f54383d87c210..34012f4b4d831 100644 --- a/lib/system/sets.nim +++ b/lib/system/sets.nim @@ -14,7 +14,7 @@ type NimSet = array[0..4*2048-1, uint8] -proc cardSet*(s: NimSet, len: int): int {.compilerproc, inline.} = +proc cardSet(s: NimSet, len: int): int {.compilerproc, inline.} = var i = 0 result = 0 when defined(x86) or defined(amd64): From 8007f8a4b5a45032f8451bbb653dd995a15d423c Mon Sep 17 00:00:00 2001 From: flywind Date: Sun, 21 Mar 2021 19:26:12 +0800 Subject: [PATCH 15/15] Apply suggestions from code review --- lib/system.nim | 3 ++- lib/system/sets.nim | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 0c7bc48c80c8b..5740431259092 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2339,7 +2339,8 @@ when notJSnotNims: when hostOS != "standalone" and hostOS != "any": include "system/dyncalls" - include system/sets + import system/countbits_impl + include "system/sets" when defined(gogc): const GenericSeqSize = (3 * sizeof(int)) diff --git a/lib/system/sets.nim b/lib/system/sets.nim index 34012f4b4d831..103c8d343ebe2 100644 --- a/lib/system/sets.nim +++ b/lib/system/sets.nim @@ -8,7 +8,6 @@ # # set handling -import system/countbits_impl type NimSet = array[0..4*2048-1, uint8]