Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interference graph support #9

Merged
merged 7 commits into from
Dec 13, 2023
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
113 changes: 90 additions & 23 deletions gematria/basic_block/basic_block.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ std::string AddressTuple::ToString() const {
buffer << "base_register='" << base_register << "', ";
buffer << "base_register_size=" << base_register_size << ", ";
buffer << "base_register_intefered_register={";
for (const std::string& interfered_register : base_register_intefered_register) {
for (const std::string& interfered_register :
base_register_intefered_register) {
buffer << "'" << interfered_register << "', ";
}
buffer << "}, ";
Expand All @@ -74,7 +75,8 @@ std::string AddressTuple::ToString() const {
buffer << "index_Register='" << index_register << "', ";
buffer << "index_register_size=" << index_register_size << ", ";
buffer << "index_register_intefered_register={";
for (const std::string& interfered_register : index_register_intefered_register) {
for (const std::string& interfered_register :
index_register_intefered_register) {
buffer << "'" << interfered_register << "', ";
}
buffer << "}, ";
Expand All @@ -86,7 +88,8 @@ std::string AddressTuple::ToString() const {
buffer << "segment_register='" << segment_register << "', ";
buffer << "segment_register_size=" << segment_register_size << ", ";
buffer << "segment_register_intefered_register={";
for (const std::string& interfered_register : segment_register_intefered_register) {
for (const std::string& interfered_register :
segment_register_intefered_register) {
buffer << "'" << interfered_register << "', ";
}
buffer << "}, ";
Expand Down Expand Up @@ -126,12 +129,15 @@ bool InstructionOperand::operator==(const InstructionOperand& other) const {
}

InstructionOperand InstructionOperand::VirtualRegister(
const std::string register_name, size_t size, const std::vector<std::string>& interfered_registers) {
const std::string register_name, size_t size,
const std::vector<std::string>& interfered_registers,
std::vector<int> interfered_registers_size) {
InstructionOperand result;
result.type_ = OperandType::kVirtualRegister;
result.register_name_ = std::move(register_name);
result.size_ = size;
result.interfered_registers_ = std::move(interfered_registers);
result.interfered_registers_size_ = std::move(interfered_registers_size);
return result;
}

Expand Down Expand Up @@ -166,14 +172,16 @@ InstructionOperand InstructionOperand::Address(AddressTuple address_tuple) {
return result;
}

InstructionOperand InstructionOperand::Address(std::string base_register,
int64_t displacement,
std::string index_register,
int scaling,
std::string segment_register,
int base_register_size,
int index_register_size,
int segment_register_size) {
InstructionOperand InstructionOperand::Address(
std::string base_register, int64_t displacement, std::string index_register,
int scaling, std::string segment_register, int base_register_size,
int index_register_size, int segment_register_size,
const std::vector<std::string>& base_register_intefered_register,
const std::vector<std::string>& index_register_intefered_register,
const std::vector<std::string>& segment_register_intefered_register,
const std::vector<int>& base_register_intefered_register_size,
const std::vector<int>& index_register_intefered_register_size,
const std::vector<int>& segment_register_intefered_register_size) {
InstructionOperand result;
result.type_ = OperandType::kAddress;
result.address_.base_register = std::move(base_register);
Expand All @@ -184,9 +192,18 @@ InstructionOperand InstructionOperand::Address(std::string base_register,
result.address_.base_register_size = base_register_size;
result.address_.index_register_size = index_register_size;
result.address_.segment_register_size = segment_register_size;
result.address_.base_register_intefered_register = {};
result.address_.index_register_intefered_register = {};
result.address_.segment_register_intefered_register = {};
result.address_.base_register_intefered_register =
std::move(base_register_intefered_register);
result.address_.index_register_intefered_register =
std::move(index_register_intefered_register);
result.address_.segment_register_intefered_register =
std::move(segment_register_intefered_register);
result.address_.base_register_intefered_register_sizes =
std::move(base_register_intefered_register_size);
result.address_.index_register_intefered_register_sizes =
std::move(index_register_intefered_register_size);
result.address_.segment_register_intefered_register_sizes =
std::move(segment_register_intefered_register_size);
return result;
}

Expand All @@ -213,14 +230,56 @@ void InstructionOperand::AddTokensToList(
break;
case OperandType::kAddress:
tokens.emplace_back(kAddressToken);
tokens.emplace_back(address().base_register.empty()
? kNoRegisterToken
: address().base_register);
tokens.emplace_back(address().index_register.empty()
? kNoRegisterToken
: address().index_register);
if (!address().segment_register.empty()) {
tokens.push_back(address().segment_register);
if (address().base_register.empty()){
tokens.emplace_back(kNoRegisterToken);
} else {
if (address().base_register_size == '%'){
tokens.emplace_back(getVREG_TOKEN(address().base_register_size));
assert(address().base_register_intefered_register.size() == address().base_register_intefered_register_sizes.size());
for (int i = 0; i < address().base_register_intefered_register.size(); ++i) {
if (address().base_register_intefered_register_sizes[i] == '%'){
tokens.emplace_back(getVREG_TOKEN(address().base_register_intefered_register_sizes[i]));
} else {
tokens.emplace_back(address().base_register_intefered_register[i]);
}
}
} else {
tokens.emplace_back(address().base_register);
}
}
if (address().index_register.empty()){
tokens.emplace_back(kNoRegisterToken);
} else {
if (address().index_register_size == '%'){
tokens.emplace_back(getVREG_TOKEN(address().index_register_size));
assert(address().index_register_intefered_register.size() == address().index_register_intefered_register_sizes.size());
for (int i = 0; i < address().index_register_intefered_register.size(); ++i) {
if (address().index_register_intefered_register_sizes[i] == '%'){
tokens.emplace_back(getVREG_TOKEN(address().index_register_intefered_register_sizes[i]));
} else {
tokens.emplace_back(address().index_register_intefered_register[i]);
}
}
} else {
tokens.emplace_back(address().index_register);
}
}
if (address().segment_register.empty()){
tokens.emplace_back(kNoRegisterToken);
} else {
if (address().segment_register_size == '%'){
tokens.emplace_back(getVREG_TOKEN(address().segment_register_size));
assert(address().segment_register_intefered_register.size() == address().segment_register_intefered_register_sizes.size());
for (int i = 0; i < address().segment_register_intefered_register.size(); ++i) {
if (address().segment_register_intefered_register_sizes[i] == '%'){
tokens.emplace_back(getVREG_TOKEN(address().segment_register_intefered_register_sizes[i]));
} else {
tokens.emplace_back(address().segment_register_intefered_register[i]);
}
}
} else {
tokens.emplace_back(address().segment_register);
}
}
if (address().displacement != 0) {
tokens.emplace_back(kDisplacementToken);
Expand All @@ -231,6 +290,14 @@ void InstructionOperand::AddTokensToList(
break;
case OperandType::kVirtualRegister:
tokens.emplace_back(getVREG_TOKEN(size()));
assert(interfered_registers_.size() == interfered_registers_size_.size());
for (int i = 0; i < interfered_registers_.size(); ++i) {
if (interfered_registers_size_[i] == '%'){
tokens.emplace_back(getVREG_TOKEN(interfered_registers_size_[i]));
} else {
tokens.emplace_back(interfered_registers_[i]);
}
}
break;
}
}
Expand Down
82 changes: 57 additions & 25 deletions gematria/basic_block/basic_block.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ inline constexpr std::string_view kDisplacementToken = "_DISPLACEMENT_";
inline constexpr std::string_view kVirtualRegisterToken = "_VREG";
inline std::string getVREG_TOKEN(size_t size) {
return std::string(kVirtualRegisterToken) + std::to_string(size) + "_";
}
}

// The type of an operand of an instruction.
enum class OperandType {
Expand Down Expand Up @@ -83,13 +83,17 @@ struct AddressTuple {
AddressTuple() {}
AddressTuple(const AddressTuple&) = default;
AddressTuple(AddressTuple&&) = default;
AddressTuple(std::string base_register, int64_t displacement,
std::string index_register, int scaling,
std::string segment_register, int base_register_size = 64,
int index_register_size = 64, int segment_register_size = 64,
const std::vector<std::string> base_register_intefered_register = {},
const std::vector<std::string> index_register_intefered_register = {},
const std::vector<std::string> segment_register_intefered_register = {})
AddressTuple(
std::string base_register, int64_t displacement,
std::string index_register, int scaling, std::string segment_register,
int base_register_size = 64, int index_register_size = 64,
int segment_register_size = 64,
const std::vector<std::string> base_register_intefered_register = {},
const std::vector<std::string> index_register_intefered_register = {},
const std::vector<std::string> segment_register_intefered_register = {},
const std::vector<int> base_register_intefered_register_sizes = {},
const std::vector<int> index_register_intefered_register_sizes = {},
const std::vector<int> segment_register_intefered_register_sizes = {})
: base_register(std::move(base_register)),
displacement(displacement),
index_register(std::move(index_register)),
Expand All @@ -98,10 +102,18 @@ struct AddressTuple {
base_register_size(std::move(base_register_size)),
index_register_size(std::move(index_register_size)),
segment_register_size(std::move(segment_register_size)),
base_register_intefered_register(std::move(base_register_intefered_register)),
index_register_intefered_register(std::move(index_register_intefered_register)),
segment_register_intefered_register(std::move(segment_register_intefered_register))
{}
base_register_intefered_register(
std::move(base_register_intefered_register)),
base_register_intefered_register_sizes(
std::move(base_register_intefered_register_sizes)),
index_register_intefered_register(
std::move(index_register_intefered_register)),
index_register_intefered_register_sizes(
std::move(index_register_intefered_register_sizes)),
segment_register_intefered_register(
std::move(segment_register_intefered_register)),
segment_register_intefered_register_sizes(
std::move(segment_register_intefered_register_sizes)) {}

AddressTuple& operator=(const AddressTuple&) = default;
AddressTuple& operator=(AddressTuple&&) = default;
Expand Down Expand Up @@ -144,12 +156,18 @@ struct AddressTuple {
// The size of the segment register. Used only when segment_register is
size_t segment_register_size;

// The name of the index register of the address. When empty, index register
// The name and size of the base register of the address. When empty, base
// register
std::vector<std::string> base_register_intefered_register;
// The name of the index register of the address. When empty, index register
std::vector<int> base_register_intefered_register_sizes;
// The name and size of the index register of the address. When empty, index
// register
std::vector<std::string> index_register_intefered_register;
// The name of the index register of the address. When empty, index register
std::vector<int> index_register_intefered_register_sizes;
// The name of the segment register of the address. When empty, segment
// register
std::vector<std::string> segment_register_intefered_register;
std::vector<int> segment_register_intefered_register_sizes;
};

std::ostream& operator<<(std::ostream& os, const AddressTuple& address_tuple);
Expand All @@ -170,19 +188,25 @@ class InstructionOperand {
InstructionOperand& operator=(InstructionOperand&&) = default;

// The operands must be created through one of the factory functions.
static InstructionOperand VirtualRegister(std::string register_name,
size_t size, const std::vector<std::string>& interfered_registers);
static InstructionOperand VirtualRegister(
std::string register_name, size_t size,
const std::vector<std::string>& interfered_registers,
std::vector<int> interfered_registers_size);
static InstructionOperand Register(std::string register_name);
static InstructionOperand ImmediateValue(uint64_t immediate_value);
static InstructionOperand FpImmediateValue(double fp_immediate_value);
static InstructionOperand Address(AddressTuple address_tuple);
static InstructionOperand Address(std::string base_register,
int64_t displacement,
std::string index_register, int scaling,
std::string segment_register,
int base_register_size = 64,
int index_register_size = 64,
int segment_register_size = 64);
static InstructionOperand Address(
std::string base_register, int64_t displacement,
std::string index_register, int scaling, std::string segment_register,
int base_register_size = 64, int index_register_size = 64,
int segment_register_size = 64,
const std::vector<std::string>& base_register_intefered_register = {},
const std::vector<std::string>& index_register_intefered_register = {},
const std::vector<std::string>& segment_register_intefered_register = {},
const std::vector<int>& base_register_intefered_register_sizes = {},
const std::vector<int>& index_register_intefered_register_sizes = {},
const std::vector<int>& segment_register_intefered_register_sizes = {});
static InstructionOperand MemoryLocation(int alias_group_id);

bool operator==(const InstructionOperand&) const;
Expand All @@ -196,11 +220,18 @@ class InstructionOperand {
// Returns the list of tokens representing this instruction.
std::vector<std::string> AsTokenList() const;

std::vector<std::string> getInterferedRegisters() const {
const std::vector<std::string>& getInterferedRegisters() const {
assert(type_ == OperandType::kVirtualRegister);
assert(interfered_registers_.size() == interfered_registers_size_.size());
return interfered_registers_;
}

const std::vector<int>& getInterferedRegistersSize() const {
assert(type_ == OperandType::kVirtualRegister);
assert(interfered_registers_.size() == interfered_registers_size_.size());
return interfered_registers_size_;
}

// Returns a human-readable representation of the operand.
//
// This method implements the __str__() and __repr__() methods in the Python
Expand Down Expand Up @@ -258,6 +289,7 @@ class InstructionOperand {
AddressTuple address_;
int alias_group_id_ = 0;
std::vector<std::string> interfered_registers_;
std::vector<int> interfered_registers_size_;
};

std::ostream& operator<<(std::ostream& os, const InstructionOperand& operand);
Expand Down
Loading
Loading