Skip to content

Commit 36a896c

Browse files
committed
Even more lir register classification
1 parent 92c618c commit 36a896c

6 files changed

Lines changed: 53 additions & 51 deletions

File tree

src/hir/hir_builder.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,15 @@ hir::Value *HIRBuilder::build_load(hir::type::Type *loaded_type,
169169
auto *instruction = arena.create<hir::Instruction>(
170170
hir::Opcode::Load, loaded_type, std::vector<hir::Value *>{ptr});
171171
instruction->name = name;
172+
instruction->type_arg = ptr->type;
172173
return insert(instruction);
173174
}
174175

175176
void HIRBuilder::build_store(hir::Value *value, hir::Value *ptr) {
176177
auto *instruction =
177178
arena.create<hir::Instruction>(hir::Opcode::Store, context.void_t(),
178179
std::vector<hir::Value *>{value, ptr});
180+
instruction->type_arg = value->type;
179181

180182
insert(instruction);
181183
}

src/lir/lir_builder.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,10 @@ lir::Register LIRBuilder::emit_copy(lir::Operand src) {
6969
}
7070

7171
lir::Register LIRBuilder::emit_binop(lir::Opcode op, lir::Operand lhs,
72-
lir::Operand rhs) {
72+
lir::Operand rhs,
73+
lir::Register::RegClass clazz) {
7374
auto dst = new_vreg();
74-
if (lhs.is_reg() && lhs.get_reg().get_class() == lir::Register::GPR64 ||
75-
rhs.is_reg() && rhs.get_reg().get_class() == lir::Register::GPR64) {
76-
dst.set_class(lir::Register::GPR64);
77-
rhs.get_reg_mut().set_class(lir::Register::GPR64);
78-
lhs.get_reg_mut().set_class(lir::Register::GPR64);
79-
}
75+
dst.set_class(clazz);
8076
auto *instr = arena.create<lir::Instruction>();
8177
instr->opcode = op;
8278
instr->num_defs = 1;

src/lir/lir_builder.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ struct LIRBuilder {
3737
void emit_ret(std::optional<lir::Operand> value = std::nullopt);
3838
lir::Register emit_mov(lir::Operand src);
3939
lir::Register emit_copy(lir::Operand src);
40-
lir::Register emit_binop(lir::Opcode op, lir::Operand lhs, lir::Operand rhs);
40+
lir::Register emit_binop(lir::Opcode op, lir::Operand lhs, lir::Operand rhs,
41+
lir::Register::RegClass clazz);
4142
lir::Register emit_unop(lir::Opcode op, lir::Operand src);
4243
lir::Register emit_cmp(lir::CmpPredicate pred, lir::Operand lhs,
4344
lir::Operand rhs);

src/lir/lir_lowering.cpp

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,23 @@ lir::BasicBlock *LIRLowering::lower_block_from_operand(hir::Value *value) {
114114
std::unreachable();
115115
}
116116

117-
lir::Operand LIRLowering::ensure_reg(lir::Operand op) {
117+
lir::Register::RegClass LIRLowering::class_from_type(hir::type::Type *type) {
118+
if (type->is_array() || type->is_pointer() || type->is_function() ||
119+
type->is_struct()) {
120+
return lir::Register::GPR64;
121+
} else if (type->is_float()) {
122+
return lir::Register::FPR32;
123+
}
124+
125+
return lir::Register::GPR32;
126+
}
127+
128+
lir::Operand LIRLowering::ensure_reg(lir::Operand op,
129+
lir::Register::RegClass clazz) {
118130
if (op.is_reg())
119131
return op;
120132
auto tmp = builder.emit_mov(op);
133+
tmp.set_class(clazz);
121134
return lir::Operand::from_reg(tmp);
122135
}
123136

@@ -175,19 +188,16 @@ void LIRLowering::lower_instruction(hir::Instruction *hir_instr) {
175188
return;
176189
}
177190
case hir::Opcode::SRem: {
191+
auto reg_class = class_from_type(hir_instr->type);
178192
auto lhs = lower_operand(hir_instr->operand(0));
179193
auto rhs = lower_operand(hir_instr->operand(1));
180-
lhs = ensure_reg(lhs);
181-
rhs = ensure_reg(rhs);
182-
if (hir_instr->type->is_pointer()) {
183-
lhs.get_reg_mut().set_class(lir::Register::GPR64);
184-
rhs.get_reg_mut().set_class(lir::Register::GPR64);
185-
}
186-
auto quot = builder.emit_binop(lir::Opcode::SDiv, lhs, rhs);
187-
auto prod =
188-
builder.emit_binop(lir::Opcode::Mul, lir::Operand::from_reg(quot), rhs);
189-
auto rem =
190-
builder.emit_binop(lir::Opcode::Sub, lhs, lir::Operand::from_reg(prod));
194+
lhs = ensure_reg(lhs, reg_class);
195+
rhs = ensure_reg(rhs, reg_class);
196+
auto quot = builder.emit_binop(lir::Opcode::SDiv, lhs, rhs, reg_class);
197+
auto prod = builder.emit_binop(
198+
lir::Opcode::Mul, lir::Operand::from_reg(quot), rhs, reg_class);
199+
auto rem = builder.emit_binop(lir::Opcode::Sub, lhs,
200+
lir::Operand::from_reg(prod), reg_class);
191201
vreg_map[hir_instr] = rem;
192202
return;
193203
}
@@ -233,26 +243,21 @@ void LIRLowering::lower_instruction(hir::Instruction *hir_instr) {
233243
std::vector<lir::Operand> args;
234244
auto *function_type =
235245
dynamic_cast<hir::type::FunctionType *>(hir_instr->type_arg);
236-
std::cout << function_type->to_string() << std::endl;
237246
for (size_t i = 1; i < hir_instr->operand_count(); i++) {
238247
auto arg_op = lower_operand(hir_instr->operand(i));
239248
if (function_type->param_types.at(i - 1)->is_pointer())
240249
arg_op.get_reg_mut().set_class(lir::Register::GPR64);
241250
args.push_back(arg_op);
242251
}
243-
lir::Register::RegClass clazz;
244-
if (hir_instr->type->is_pointer() || hir_instr->type->is_array()) {
245-
clazz = lir::Register::GPR64;
246-
} else {
247-
clazz = lir::Register::GPR32;
248-
}
252+
lir::Register::RegClass clazz = class_from_type(hir_instr->type);
249253
auto *callee = dynamic_cast<hir::Function *>(hir_instr->operand(0));
250254
auto dst = builder.emit_call(callee->name, std::move(args), clazz);
251255
dst.set_class(clazz);
252256
vreg_map[hir_instr] = dst;
253257
return;
254258
}
255259
case hir::Opcode::Load: {
260+
std::cout << "Type arg for load is " << hir_instr->type_arg << std::endl;
256261
auto ptr = lower_operand(hir_instr->operand(0));
257262
if (ptr.is_reg())
258263
ptr.get_reg_mut().set_class(lir::Register::GPR64);
@@ -261,10 +266,11 @@ void LIRLowering::lower_instruction(hir::Instruction *hir_instr) {
261266
return;
262267
}
263268
case hir::Opcode::Store: {
269+
std::cout << "Type arg for store is " << hir_instr->type_arg << std::endl;
264270
auto base = lower_operand(hir_instr->operand(0));
265271
auto value = lower_operand(hir_instr->operand(1));
266-
auto base_reg = ensure_reg(base);
267-
auto value_reg = ensure_reg(value);
272+
auto base_reg = ensure_reg(base, class_from_type(hir_instr->type));
273+
auto value_reg = ensure_reg(value, class_from_type(hir_instr->type_arg));
268274

269275
if (base.is_reg())
270276
base.get_reg_mut().set_class(lir::Register::GPR64);
@@ -277,14 +283,15 @@ void LIRLowering::lower_instruction(hir::Instruction *hir_instr) {
277283
auto size = hir_instr->type_arg->size_of();
278284
auto size_op = lir::Operand::from_imm(size);
279285

280-
auto index_reg = ensure_reg(index);
281-
auto size_reg = ensure_reg(size_op);
282-
auto offset = builder.emit_binop(lir::Opcode::Mul, index_reg, size_reg);
286+
auto index_reg = ensure_reg(index, class_from_type(hir_instr->type_arg));
287+
auto size_reg = ensure_reg(size_op, class_from_type(hir_instr->type_arg));
288+
auto offset = builder.emit_binop(lir::Opcode::Mul, index_reg, size_reg,
289+
class_from_type(hir_instr->type_arg));
283290
offset.set_class(lir::Register::RegClass::GPR64);
284291

285292
auto ptr = builder.emit_binop(lir::Opcode::Add, base,
286-
lir::Operand::from_reg(offset));
287-
ptr.set_class(lir::Register::RegClass::GPR64);
293+
lir::Operand::from_reg(offset),
294+
lir::Register::GPR64);
288295
vreg_map[hir_instr] = ptr;
289296
return;
290297
}
@@ -304,18 +311,14 @@ void LIRLowering::lower_binop(hir::Instruction *hir_instr, lir::Opcode op) {
304311
auto rhs = lower_operand(hir_instr->operand(1));
305312

306313
// First operand must always be a register
307-
lhs = ensure_reg(lhs);
314+
lhs = ensure_reg(lhs, class_from_type(hir_instr->type));
308315

309316
// Second operand: check if target accepts immediate
310317
if (rhs.is_imm() && !target_info.accepts_imm(op))
311-
rhs = ensure_reg(rhs);
312-
313-
auto dst = builder.emit_binop(op, lhs, rhs);
314-
if (hir_instr->type->is_pointer()) {
315-
lhs.get_reg_mut().set_class(lir::Register::GPR64);
316-
rhs.get_reg_mut().set_class(lir::Register::GPR64);
317-
}
318+
rhs = ensure_reg(rhs, class_from_type(hir_instr->type));
318319

320+
auto dst = builder.emit_binop(op, lhs, rhs, class_from_type(hir_instr->type));
321+
dst.set_class(class_from_type(hir_instr->type));
319322
vreg_map[hir_instr] = dst;
320323
}
321324

src/lir/lir_lowering.hpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,17 @@ struct LIRLowering {
2727
void lower_function(hir::Function *hir_function);
2828
void lower_block(hir::BasicBlock *hir_bb);
2929
void lower_instruction(hir::Instruction *hir_instr);
30-
lir::Operand lower_operand(hir::Value *value);
31-
lir::BasicBlock *lower_block_from_operand(hir::Value *value);
32-
lir::CmpPredicate convert_predicate(hir::ICmpPredicate pred);
33-
inline lir::BasicBlock *get_mbb(hir::BasicBlock *bb) { return block_map[bb]; }
30+
[[nodiscard]] lir::Operand lower_operand(hir::Value *value);
31+
[[nodiscard]] lir::BasicBlock *lower_block_from_operand(hir::Value *value);
32+
[[nodiscard]] lir::CmpPredicate convert_predicate(hir::ICmpPredicate pred);
33+
[[nodiscard]] inline lir::BasicBlock *get_mbb(hir::BasicBlock *bb) {
34+
return block_map[bb];
35+
}
3436
void lower_binop(hir::Instruction *hir_instr, lir::Opcode op);
3537

36-
lir::Operand ensure_reg(lir::Operand op);
38+
[[nodiscard]] lir::Operand ensure_reg(lir::Operand op,
39+
lir::Register::RegClass clazz);
40+
[[nodiscard]] lir::Register::RegClass class_from_type(hir::type::Type *type);
3741

3842
void eliminate_phis(hir::Function *hir_function);
3943
void sequentialize_copies(

tests/array_basic.c0

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@ int main() {
33

44
// Fill array
55
arr[0] = 5;
6-
arr[1] = 3;
7-
arr[2] = 4;
8-
arr[3] = 1;
9-
arr[4] = 2;
106

117
// Sum sorted array
128
int sum = 0;

0 commit comments

Comments
 (0)