-
Notifications
You must be signed in to change notification settings - Fork 638
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Indexable_deque for use in new hip sync.
- Loading branch information
Showing
6 changed files
with
331 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// Copyright 2024 The IREE Authors | ||
// | ||
// Licensed under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
||
#include "iree/base/indexable_deque.h" | ||
|
||
#include "iree/base/assert.h" | ||
|
||
void iree_indexable_queue_initialize(iree_indexable_queue_t* queue, | ||
iree_allocator_t allocator, | ||
iree_host_size_t element_size, | ||
iree_host_size_t inline_count) { | ||
queue->allocator = allocator; | ||
queue->elements = &queue->initial_allocation[0]; | ||
queue->element_size = element_size; | ||
queue->element_count = 0; | ||
queue->capacity = inline_count; | ||
queue->head = 0; | ||
} | ||
|
||
void iree_indexable_queue_deinitialize(iree_indexable_queue_t* queue) { | ||
IREE_ASSERT_ARGUMENT(queue); | ||
if (queue->elements != &queue->initial_allocation[0]) { | ||
iree_allocator_free(queue->allocator, queue->elements); | ||
} | ||
} | ||
|
||
iree_status_t iree_indexable_queue_push_back(iree_indexable_queue_t* queue, | ||
void* element) { | ||
// Expand | ||
if (queue->capacity == queue->element_count) { | ||
uint8_t* new_mem; | ||
queue->capacity = iree_max(16, queue->capacity << 1); | ||
IREE_RETURN_IF_ERROR(iree_allocator_malloc( | ||
queue->allocator, queue->element_size * queue->capacity, | ||
(void**)&new_mem)); | ||
memcpy(new_mem, queue->elements + (queue->head * queue->element_size), | ||
(queue->element_count - queue->head) * queue->element_size); | ||
memcpy( | ||
new_mem + ((queue->element_count - queue->head) * queue->element_size), | ||
queue->elements, queue->head * queue->element_size); | ||
if (queue->elements != &queue->initial_allocation[0]) { | ||
iree_allocator_free(queue->allocator, queue->elements); | ||
} | ||
queue->head = 0; | ||
queue->elements = new_mem; | ||
} | ||
memcpy(queue->elements + | ||
(((queue->head + queue->element_count) % queue->capacity) * | ||
queue->element_size), | ||
element, queue->element_size); | ||
queue->element_count++; | ||
return iree_ok_status(); | ||
} | ||
|
||
void iree_indexable_queue_pop_front(iree_indexable_queue_t* queue, | ||
iree_host_size_t count) { | ||
IREE_ASSERT_ARGUMENT(queue); | ||
IREE_ASSERT(count <= queue->element_count, "Popping too many elements"); | ||
queue->head += count; | ||
queue->head = queue->head % queue->capacity; | ||
queue->element_count -= count; | ||
} | ||
|
||
void* iree_indexable_queue_at(iree_indexable_queue_t* queue, | ||
iree_host_size_t i) { | ||
IREE_ASSERT_ARGUMENT(queue); | ||
IREE_ASSERT(i < queue->element_count, "Index out of range"); | ||
return queue->elements + | ||
((queue->head + i) % queue->capacity) * queue->element_size; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// Copyright 2024 The IREE Authors | ||
// | ||
// Licensed under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
||
#ifndef IREE_BASE_INDEXABLE_DEQUE_H__ | ||
#define IREE_BASE_INDEXABLE_DEQUE_H__ | ||
|
||
#include "iree/base/allocator.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
// The indexable deque essentially a circular array | ||
// where we can push to the back and pop from the front. | ||
// The helper functions allow you to index into the array. | ||
// Furthermore an initial allocation may be provided inline | ||
// as an optimization. | ||
typedef struct iree_indexable_queue_t { | ||
iree_allocator_t allocator; | ||
uint8_t* elements; | ||
iree_host_size_t element_size; | ||
iree_host_size_t element_count; | ||
iree_host_size_t capacity; | ||
iree_host_size_t head; | ||
uint8_t initial_allocation[]; | ||
} iree_indexable_queue_t; | ||
|
||
// Initializes the indexable_queue with the given allocator, element size and | ||
// number of inline elements (which may be 0). | ||
void iree_indexable_queue_initialize(iree_indexable_queue_t* queue, | ||
iree_allocator_t allocator, | ||
iree_host_size_t element_size, | ||
iree_host_size_t inline_count); | ||
|
||
// Deinitializes the list, it does not have to be empty. | ||
void iree_indexable_queue_deinitialize(iree_indexable_queue_t* queue); | ||
|
||
// Copies the given element into the back of the array. This may cause a | ||
// re-allocation of data. | ||
iree_status_t iree_indexable_queue_push_back(iree_indexable_queue_t* queue, | ||
void* element); | ||
|
||
// Pops the element from the front of the array and moves the head. | ||
void iree_indexable_queue_pop_front(iree_indexable_queue_t* queue, | ||
iree_host_size_t count); | ||
|
||
// Returns a pointer to the element at index i | ||
void* iree_indexable_queue_at(iree_indexable_queue_t* queue, | ||
iree_host_size_t i); | ||
|
||
#define IREE_TYPED_INDEXABLE_QUEUE_WRAPPER(name, type, default_element_count) \ | ||
typedef struct name##_indexable_queue_t { \ | ||
iree_allocator_t allocator; \ | ||
void* elements; \ | ||
iree_host_size_t element_size; \ | ||
iree_host_size_t element_count; \ | ||
iree_host_size_t capacity; \ | ||
iree_host_size_t head; \ | ||
iree_alignas(iree_max_align_t) uint8_t \ | ||
initial_allocation[default_element_count * sizeof(type)]; \ | ||
} name##_indexable_queue_t; \ | ||
static inline void name##_initialize(name##_indexable_queue_t* out_queue, \ | ||
iree_allocator_t allocator) { \ | ||
iree_indexable_queue_initialize((iree_indexable_queue_t*)out_queue, \ | ||
allocator, sizeof(type), \ | ||
default_element_count); \ | ||
} \ | ||
static inline void name##_deinitialize( \ | ||
name##_indexable_queue_t* out_queue) { \ | ||
iree_indexable_queue_deinitialize((iree_indexable_queue_t*)out_queue); \ | ||
} \ | ||
iree_status_t name##_push_back(name##_indexable_queue_t* queue, \ | ||
type element) { \ | ||
return iree_indexable_queue_push_back((iree_indexable_queue_t*)queue, \ | ||
&element); \ | ||
} \ | ||
void name##_pop_front(name##_indexable_queue_t* queue, \ | ||
iree_host_size_t count) { \ | ||
return iree_indexable_queue_pop_front((iree_indexable_queue_t*)queue, \ | ||
count); \ | ||
} \ | ||
type name##_at(name##_indexable_queue_t* queue, iree_host_size_t i) { \ | ||
type t; \ | ||
memcpy(&t, iree_indexable_queue_at((iree_indexable_queue_t*)queue, i), \ | ||
sizeof(type)); \ | ||
return t; \ | ||
} | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif // IREE_BASE_INTERNAL_INDEXABLE_DEQUE_H__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// Copyright 2024 The IREE Authors | ||
// | ||
// Licensed under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
||
#include "iree/base/indexable_deque.h" | ||
|
||
#include "iree/testing/gtest.h" | ||
|
||
IREE_TYPED_INDEXABLE_QUEUE_WRAPPER(test_queue, int32_t, 4); | ||
|
||
class IndexableDequeTest : public ::testing::Test { | ||
protected: | ||
void SetUp() override { | ||
test_queue_initialize(&queue_, iree_allocator_system()); | ||
} | ||
|
||
void TearDown() override { test_queue_deinitialize(&queue_); } | ||
|
||
test_queue_indexable_queue_t queue_; | ||
}; | ||
|
||
TEST_F(IndexableDequeTest, initialize) { | ||
EXPECT_EQ(queue_.element_count, 0); | ||
EXPECT_EQ(queue_.capacity, 4); | ||
EXPECT_EQ(queue_.element_size, sizeof(int)); | ||
} | ||
|
||
TEST_F(IndexableDequeTest, push_back) { | ||
int value = 42; | ||
IREE_CHECK_OK(test_queue_push_back(&queue_, value)); | ||
EXPECT_EQ(queue_.element_count, 1); | ||
EXPECT_EQ(test_queue_at(&queue_, 0), value); | ||
} | ||
|
||
TEST_F(IndexableDequeTest, push_back_and_expand) { | ||
for (int i = 0; i < 5; ++i) { | ||
IREE_CHECK_OK(test_queue_push_back(&queue_, i)); | ||
} | ||
EXPECT_EQ(queue_.element_count, 5); | ||
EXPECT_GT(queue_.capacity, 4); | ||
} | ||
|
||
TEST_F(IndexableDequeTest, pop_front) { | ||
IREE_CHECK_OK(test_queue_push_back(&queue_, 12)); | ||
IREE_CHECK_OK(test_queue_push_back(&queue_, 15)); | ||
test_queue_pop_front(&queue_, 1); | ||
EXPECT_EQ(queue_.element_count, 1); | ||
EXPECT_EQ(test_queue_at(&queue_, 0), 15); | ||
} | ||
|
||
TEST_F(IndexableDequeTest, at) { | ||
int value1 = 42; | ||
int value2 = 84; | ||
IREE_CHECK_OK(test_queue_push_back(&queue_, value1)); | ||
IREE_CHECK_OK(test_queue_push_back(&queue_, value2)); | ||
EXPECT_EQ(test_queue_at(&queue_, 0), value1); | ||
EXPECT_EQ(test_queue_at(&queue_, 1), value2); | ||
} | ||
|
||
TEST_F(IndexableDequeTest, cycle_around_queue) { | ||
for (int i = 0; i < 4; ++i) { | ||
IREE_CHECK_OK(test_queue_push_back(&queue_, i)); | ||
} | ||
for (int i = 0; i < 4; ++i) { | ||
test_queue_pop_front(&queue_, 1); | ||
IREE_CHECK_OK(test_queue_push_back(&queue_, i + 4)); | ||
} | ||
for (int i = 0; i < 4; ++i) { | ||
EXPECT_EQ(test_queue_at(&queue_, i), i + 4); | ||
} | ||
EXPECT_EQ(queue_.element_count, 4); | ||
} | ||
|
||
TEST_F(IndexableDequeTest, cycle_around_queue_twice) { | ||
for (int i = 0; i < 4; ++i) { | ||
IREE_CHECK_OK(test_queue_push_back(&queue_, i)); | ||
} | ||
for (int i = 0; i < 8; ++i) { | ||
test_queue_pop_front(&queue_, 1); | ||
IREE_CHECK_OK(test_queue_push_back(&queue_, i + 4)); | ||
} | ||
for (int i = 0; i < 4; ++i) { | ||
EXPECT_EQ(test_queue_at(&queue_, i), i + 8); | ||
} | ||
EXPECT_EQ(queue_.element_count, 4); | ||
} | ||
|
||
TEST_F(IndexableDequeTest, allocate_twice) { | ||
for (int i = 0; i < 8; ++i) { | ||
IREE_CHECK_OK(test_queue_push_back(&queue_, i)); | ||
} | ||
EXPECT_EQ(queue_.element_count, 8); | ||
EXPECT_GT(queue_.capacity, 4); | ||
|
||
for (int i = 8; i < 16; ++i) { | ||
IREE_CHECK_OK(test_queue_push_back(&queue_, i)); | ||
} | ||
EXPECT_EQ(queue_.element_count, 16); | ||
EXPECT_GT(queue_.capacity, 8); | ||
} | ||
|
||
TEST_F(IndexableDequeTest, no_reallocation_when_capacity_sufficient) { | ||
size_t initial_capacity = queue_.capacity; | ||
for (int i = 0; i < initial_capacity; ++i) { | ||
IREE_CHECK_OK(test_queue_push_back(&queue_, i)); | ||
} | ||
EXPECT_EQ(queue_.capacity, initial_capacity); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters