diff --git a/benchmarks/mem/quicksort.bril b/benchmarks/mem/quicksort.bril new file mode 100644 index 000000000..b7e0f7f15 --- /dev/null +++ b/benchmarks/mem/quicksort.bril @@ -0,0 +1,125 @@ +# An implementation of Quicksort using the Lomuto partition scheme, adapted from the pseudocode on Wikipedia +# Input: an array of length 6 +# Output: the input array sorted in ascending order +# Adopted two helper functions, pack and print_array, from Jiajie Li's bubble sort benchmark + +# ARGS: 94 21 5 6 82 46 +@main(n1: int, n2: int, n3: int, n4: int, n5: int, n6:int) { + size: int = const 6; + array: ptr = call @pack size n1 n2 n3 n4 n5 n6; + one: int = const 1; + size_minus_one: int = sub size one; + + zero: int = const 0; + call @qsort array zero size_minus_one; + + # Print array + call @print_array array size; + + free array; +} + +@qsort(array : ptr, l: int, r:int) { + # if l >= r or r < 0, return + l_ge_r: bool = ge l r; + zero: int = const 0; + neg_r: bool = lt r zero; + ret_cond: bool = or l_ge_r neg_r; + + br ret_cond .done .continue; + + .continue: + p: int = call @partition array l r; + one: int = const 1; + p_minus_one: int = sub p one; + p_plus_one: int = add p one; + + call @qsort array l p_minus_one; + call @qsort array p_plus_one r; + + .done: + ret; +} + +@partition(array : ptr, l: int, r:int) : int { + # choose the last element as the pivot + pivot_loc: ptr = ptradd array r; + pivot: int = load pivot_loc; + one: int = const 1; + i:int = sub l one; + j:int = id i; + + .loop.init: + j:int = add j one; + cond: bool = lt j r; + br cond .body .post.loop; + + .body: + j_loc: ptr = ptradd array j; + a_j: int = load j_loc; + swap_cond: bool = le a_j pivot; + br swap_cond .swap .loop.init; + + .swap: + # increment i by 1 + i: int = add i one; + + # swap the current element with the element at the temporary pivot index i + i_loc: ptr = ptradd array i; + a_i: int = load i_loc; + store j_loc a_i; + store i_loc a_j; + jmp .loop.init; + + .post.loop: + i:int = add i one; + i_loc: ptr = ptradd array i; + a_i: int = load i_loc; + store i_loc pivot; + store pivot_loc a_i; + ret i; +} + +# allocate an array of the given size and pack the input values into the array +@pack(size: int, n1: int, n2: int, n3: int, n4: int, n5: int, n6: int) : ptr { + one: int = const 1; + i: int = const 0; + array: ptr = alloc size; +# Pack data into array manually. Cannot use loop because of the different var name. + loc: ptr = ptradd array i; + store loc n1; + i: int = add i one; + loc: ptr = ptradd array i; + store loc n2; + i: int = add i one; + loc: ptr = ptradd array i; + store loc n3; + i: int = add i one; + loc: ptr = ptradd array i; + store loc n4; + i: int = add i one; + loc: ptr = ptradd array i; + store loc n5; + i: int = add i one; + loc: ptr = ptradd array i; + store loc n6; + + ret array; +} + +@print_array(array: ptr, size: int) { + i: int = const 0; + one: int = const 1; +.loop: + cond: bool = lt i size; + br cond .body .done; +.body: + loc: ptr = ptradd array i; + val: int = load loc; + print val; +.loop_end: + i: int = add i one; + jmp .loop; +.done: + ret; +} \ No newline at end of file diff --git a/benchmarks/mem/quicksort.out b/benchmarks/mem/quicksort.out new file mode 100644 index 000000000..0ab8cac08 --- /dev/null +++ b/benchmarks/mem/quicksort.out @@ -0,0 +1,6 @@ +5 +6 +21 +46 +82 +94 diff --git a/benchmarks/mem/quicksort.prof b/benchmarks/mem/quicksort.prof new file mode 100644 index 000000000..32b1ccbf7 --- /dev/null +++ b/benchmarks/mem/quicksort.prof @@ -0,0 +1 @@ +total_dyn_inst: 264 diff --git a/docs/tools/bench.md b/docs/tools/bench.md index 2cb2625c6..0f72c85f5 100644 --- a/docs/tools/bench.md +++ b/docs/tools/bench.md @@ -49,6 +49,7 @@ The current benchmarks are: * `primitive-root`: Computes a [primitive root][primitive_root] modulo a prime number input. * `pythagorean_triple`: Prints all Pythagorean triples with the given c, if such triples exist. An intentionally very naive implementation. * `quadratic`: The [quadratic formula][qf], including a hand-rolled implementation of square root. +* `quicksort`: [Quicksort using the Lomuto partition scheme][qsort]. * `recfact`: Compute *n!* using recursive function calls. * `rectangles-area-difference`: Output the difference between the areas of rectangles (as a positive value) given their respective side lengths. * `relative-primes`: Print all numbers relatively prime to *n* using [Euclidean algorithm][euclidean_into]. @@ -92,5 +93,6 @@ Credit for several of these benchmarks goes to Alexa VanHattum and Gregory Yaune [palindrome]: https://en.wikipedia.org/wiki/Palindrome [hanoi]: https://en.wikipedia.org/wiki/Tower_of_Hanoi [euler]: https://en.wikipedia.org/wiki/E_(mathematical_constant) +[qsort]: https://en.wikipedia.org/wiki/Quicksort#Lomuto_partition_scheme [modinv]: https://en.wikipedia.org/wiki/Modular_multiplicative_inverse [totient]: https://en.wikipedia.org/wiki/Euler's_totient_function