Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,13 @@ public static void main(String[] args) throws RunnerException {
@Setup(Level.Iteration)
public void setup() throws Exception {
engine = new CairoEngine(configuration);
ctx = new SqlExecutionContextImpl(engine, 1);
ctx = new SqlExecutionContextImpl(engine, 1).with(
configuration.getFactoryProvider().getSecurityContextFactory().getRootContext(),
null,
null,
-1,
null
);
compiler = new SqlCompilerImpl(engine);

boolean jitShouldBeEnabled = false;
Expand Down
1,183 changes: 1,183 additions & 0 deletions core/src/main/c/share/jit/aarch64.h

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions core/src/main/c/share/jit/avx2.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ namespace questdb::avx2 {
case data_type_t::f64: {
double value = instr.dpayload;
Vec dummy;
if (!cache.findFloat(value, dummy)) {
if (!cache.findFloat(value, type, dummy)) {
Vec reg = c.new_ymm("const_ymm_f_%f", value);
if (type == data_type_t::f32) {
Mem mem = c.new_float_const(scope, static_cast<float>(value));
Expand All @@ -106,7 +106,7 @@ namespace questdb::avx2 {
Mem mem = c.new_double_const(scope, value);
c.vbroadcastsd(reg, mem);
}
cache.addFloat(value, reg);
cache.addFloat(value, type, reg);
}
break;
}
Expand Down Expand Up @@ -391,7 +391,7 @@ namespace questdb::avx2 {
// Check cache for float constants
if (type == data_type_t::f32 || type == data_type_t::f64) {
Vec cached;
if (cache.findFloat(instr.dpayload, cached)) {
if (cache.findFloat(instr.dpayload, type, cached)) {
return {cached, type, data_kind_t::kConst};
}
}
Expand Down
156 changes: 140 additions & 16 deletions core/src/main/c/share/jit/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@
#define QUESTDB_JIT_COMMON_H

#include <asmjit/core.h>
#ifdef __aarch64__
#include <asmjit/a64.h>
#else
#include <asmjit/x86.h>
#endif
#include <asmjit/support/arenavector.h>

enum class data_type_t : uint8_t {
Expand Down Expand Up @@ -99,9 +103,13 @@ struct jit_value_t {

inline jit_value_t &operator=(const jit_value_t &other) noexcept = default;

#ifdef __aarch64__
inline const asmjit::a64::Vec &vec() const noexcept { return op_.as<asmjit::a64::Vec>(); }
inline const asmjit::a64::Gp &gp() const noexcept { return op_.as<asmjit::a64::Gp>(); }
#else
inline const asmjit::x86::Vec &vec() const noexcept { return op_.as<asmjit::x86::Vec>(); }

inline const asmjit::x86::Gp &gp() const noexcept { return op_.as<asmjit::x86::Gp>(); }
#endif

inline data_type_t dtype() const noexcept { return type_; }

Expand Down Expand Up @@ -154,6 +162,22 @@ struct ColumnAddressCache {
return column_idx >= 0 && static_cast<size_t>(column_idx) < MAX_COLUMNS && valid[column_idx];
}

#ifdef __aarch64__
asmjit::a64::Gp get(int32_t column_idx) const {
return addresses[column_idx];
}

void set(int32_t column_idx, asmjit::a64::Gp reg) {
if (column_idx >= 0 && static_cast<size_t>(column_idx) < MAX_COLUMNS) {
addresses[column_idx] = reg;
valid[column_idx] = true;
}
}

private:
asmjit::a64::Gp addresses[MAX_COLUMNS];
bool valid[MAX_COLUMNS];
#else
asmjit::x86::Gp get(int32_t column_idx) const {
return addresses[column_idx];
}
Expand All @@ -168,6 +192,7 @@ struct ColumnAddressCache {
private:
asmjit::x86::Gp addresses[MAX_COLUMNS];
bool valid[MAX_COLUMNS];
#endif
};

// Cache for pre-loaded constants to avoid redundant loads inside the loop
Expand All @@ -176,8 +201,8 @@ struct ConstantCache {

ConstantCache() : count(0) {}

// Find an integer constant and return its register
bool findInt(int64_t value, asmjit::x86::Gp &out_reg) const {
#ifdef __aarch64__
bool findInt(int64_t value, asmjit::a64::Gp &out_reg) const {
for (size_t i = 0; i < count; ++i) {
if (!is_float[i] && int_values[i] == value) {
out_reg = gp_regs[i];
Expand All @@ -187,18 +212,62 @@ struct ConstantCache {
return false;
}

// Find a float constant and return its register
bool findFloat(double value, asmjit::x86::Vec &out_reg) const {
bool findFloat(double value, asmjit::a64::Vec &out_reg) const {
for (size_t i = 0; i < count; ++i) {
if (is_float[i] && float_values[i] == value) {
out_reg = vec_regs[i];
return true;
}
}
return false;
}

void addInt(int64_t value, asmjit::a64::Gp reg) {
if (count < MAX_CONSTANTS) {
is_float[count] = false;
int_values[count] = value;
gp_regs[count] = reg;
count++;
}
}

void addFloat(double value, asmjit::a64::Vec reg) {
if (count < MAX_CONSTANTS) {
is_float[count] = true;
float_values[count] = value;
vec_regs[count] = reg;
count++;
}
}

private:
size_t count;
bool is_float[MAX_CONSTANTS];
int64_t int_values[MAX_CONSTANTS];
double float_values[MAX_CONSTANTS];
asmjit::a64::Gp gp_regs[MAX_CONSTANTS];
asmjit::a64::Vec vec_regs[MAX_CONSTANTS];
#else
bool findInt(int64_t value, asmjit::x86::Gp &out_reg) const {
for (size_t i = 0; i < count; ++i) {
if (!is_float[i] && int_values[i] == value) {
out_reg = gp_regs[i];
return true;
}
}
return false;
}

bool findFloat(double value, data_type_t type, asmjit::x86::Vec &out_reg) const {
for (size_t i = 0; i < count; ++i) {
if (is_float[i] && float_values[i] == value && float_types[i] == type) {
out_reg = xmm_regs[i];
return true;
}
}
return false;
}

// Add an integer constant
void addInt(int64_t value, asmjit::x86::Gp reg) {
if (count < MAX_CONSTANTS) {
is_float[count] = false;
Expand All @@ -208,11 +277,11 @@ struct ConstantCache {
}
}

// Add a float constant
void addFloat(double value, asmjit::x86::Vec reg) {
void addFloat(double value, data_type_t type, asmjit::x86::Vec reg) {
if (count < MAX_CONSTANTS) {
is_float[count] = true;
float_values[count] = value;
float_types[count] = type;
xmm_regs[count] = reg;
count++;
}
Expand All @@ -223,8 +292,10 @@ struct ConstantCache {
bool is_float[MAX_CONSTANTS];
int64_t int_values[MAX_CONSTANTS];
double float_values[MAX_CONSTANTS];
data_type_t float_types[MAX_CONSTANTS];
asmjit::x86::Gp gp_regs[MAX_CONSTANTS];
asmjit::x86::Vec xmm_regs[MAX_CONSTANTS];
#endif
};

// Cache for loaded column values to avoid redundant loads within a single row iteration
Expand All @@ -233,7 +304,59 @@ struct ColumnValueCache {

ColumnValueCache() : count(0) {}

// Find a cached value for a column
#ifdef __aarch64__
bool find(int32_t column_idx, data_type_t type, asmjit::a64::Gp &out_reg) const {
for (size_t i = 0; i < count; ++i) {
if (column_idxs[i] == column_idx && types[i] == type && !is_fp[i]) {
out_reg = gp_regs[i];
return true;
}
}
return false;
}

bool findXmm(int32_t column_idx, data_type_t type, asmjit::a64::Vec &out_reg) const {
for (size_t i = 0; i < count; ++i) {
if (column_idxs[i] == column_idx && types[i] == type && is_fp[i]) {
out_reg = vec_regs[i];
return true;
}
}
return false;
}

void add(int32_t column_idx, data_type_t type, asmjit::a64::Gp reg) {
if (count < MAX_VALUES) {
column_idxs[count] = column_idx;
types[count] = type;
is_fp[count] = false;
gp_regs[count] = reg;
count++;
}
}

void addXmm(int32_t column_idx, data_type_t type, asmjit::a64::Vec reg) {
if (count < MAX_VALUES) {
column_idxs[count] = column_idx;
types[count] = type;
is_fp[count] = true;
vec_regs[count] = reg;
count++;
}
}

void clear() {
count = 0;
}

private:
size_t count;
int32_t column_idxs[MAX_VALUES];
data_type_t types[MAX_VALUES];
bool is_fp[MAX_VALUES];
asmjit::a64::Gp gp_regs[MAX_VALUES];
asmjit::a64::Vec vec_regs[MAX_VALUES];
#else
bool find(int32_t column_idx, data_type_t type, asmjit::x86::Gp &out_reg) const {
for (size_t i = 0; i < count; ++i) {
if (column_idxs[i] == column_idx && types[i] == type && !is_xmm[i]) {
Expand All @@ -244,7 +367,6 @@ struct ColumnValueCache {
return false;
}

// Find a cached float/double value for a column
bool findXmm(int32_t column_idx, data_type_t type, asmjit::x86::Vec &out_reg) const {
for (size_t i = 0; i < count; ++i) {
if (column_idxs[i] == column_idx && types[i] == type && is_xmm[i]) {
Expand All @@ -255,7 +377,6 @@ struct ColumnValueCache {
return false;
}

// Add an integer column value
void add(int32_t column_idx, data_type_t type, asmjit::x86::Gp reg) {
if (count < MAX_VALUES) {
column_idxs[count] = column_idx;
Expand All @@ -266,7 +387,6 @@ struct ColumnValueCache {
}
}

// Add a float/double column value
void addXmm(int32_t column_idx, data_type_t type, asmjit::x86::Vec reg) {
if (count < MAX_VALUES) {
column_idxs[count] = column_idx;
Expand All @@ -277,7 +397,6 @@ struct ColumnValueCache {
}
}

// Clear cache (call at start of each row iteration if needed)
void clear() {
count = 0;
}
Expand All @@ -289,8 +408,10 @@ struct ColumnValueCache {
bool is_xmm[MAX_VALUES];
asmjit::x86::Gp gp_regs[MAX_VALUES];
asmjit::x86::Vec xmm_regs[MAX_VALUES];
#endif
};

#ifndef __aarch64__
// Cache for pre-broadcasted constants in YMM registers for AVX2 SIMD loops
struct ConstantCacheYmm {
static constexpr size_t MAX_CONSTANTS = 8;
Expand All @@ -309,9 +430,9 @@ struct ConstantCacheYmm {
}

// Find a float constant and return its YMM register
bool findFloat(double value, asmjit::x86::Vec &out_reg) const {
bool findFloat(double value, data_type_t type, asmjit::x86::Vec &out_reg) const {
for (size_t i = 0; i < count; ++i) {
if (is_float[i] && float_values[i] == value) {
if (is_float[i] && float_values[i] == value && float_types[i] == type) {
out_reg = ymm_regs[i];
return true;
}
Expand All @@ -330,10 +451,11 @@ struct ConstantCacheYmm {
}

// Add a float constant
void addFloat(double value, asmjit::x86::Vec reg) {
void addFloat(double value, data_type_t type, asmjit::x86::Vec reg) {
if (count < MAX_CONSTANTS) {
is_float[count] = true;
float_values[count] = value;
float_types[count] = type;
ymm_regs[count] = reg;
count++;
}
Expand All @@ -344,7 +466,9 @@ struct ConstantCacheYmm {
bool is_float[MAX_CONSTANTS];
int64_t int_values[MAX_CONSTANTS];
double float_values[MAX_CONSTANTS];
data_type_t float_types[MAX_CONSTANTS];
asmjit::x86::Vec ymm_regs[MAX_CONSTANTS];
};
#endif // !__aarch64__

#endif //QUESTDB_JIT_COMMON_H
Loading
Loading