Skip to content

Commit 7e49741

Browse files
authored
Merge pull request #131 from nosba0957/master
Fix bad logical-and implementation
2 parents c2afdc2 + 43f02a7 commit 7e49741

File tree

8 files changed

+276
-33
lines changed

8 files changed

+276
-33
lines changed

src/arm-codegen.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -440,16 +440,6 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
440440
emit(__mov_i(__NE, rd, 0));
441441
emit(__mov_i(__EQ, rd, 1));
442442
return;
443-
case OP_log_and:
444-
/* TODO: short-circuit evaluation */
445-
emit(__teq(rn));
446-
emit(__mov_i(__NE, __r8, 1));
447-
emit(__mov_i(__EQ, __r8, 0));
448-
emit(__teq(rm));
449-
emit(__mov_i(__NE, rd, 1));
450-
emit(__mov_i(__EQ, rd, 0));
451-
emit(__and_r(__AL, rd, rd, __r8));
452-
return;
453443
case OP_log_or:
454444
emit(__or_r(__AL, rd, rn, rm));
455445
emit(__teq(rd));

src/defs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#define MAX_FUNC_TRIES 2160
2121
#define MAX_BLOCKS 2048
2222
#define MAX_TYPES 64
23-
#define MAX_IR_INSTR 36864
23+
#define MAX_IR_INSTR 40000
2424
#define MAX_BB_PRED 128
2525
#define MAX_BB_DOM_SUCC 64
2626
#define MAX_GLOBAL_IR 256
@@ -175,6 +175,7 @@ struct var {
175175
ref_block_list_t ref_block_list; /* blocks which kill variable */
176176
int consumed;
177177
bool is_ternary_ret;
178+
bool is_log_and_ret;
178179
bool is_const; /* whether a constant representaion or not */
179180
};
180181

src/parser.c

Lines changed: 170 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,9 @@ void read_char_param(block_t *parent, basic_block_t *bb)
662662
add_insn(parent, bb, OP_load_constant, ph1_ir->dest, NULL, NULL, 0, NULL);
663663
}
664664

665+
void read_log_and_operation(block_t *parent,
666+
basic_block_t **bb,
667+
char *label_else);
665668
void read_ternary_operation(block_t *parent, basic_block_t **bb);
666669
void read_func_parameters(block_t *parent, basic_block_t **bb)
667670
{
@@ -973,20 +976,37 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
973976
}
974977
}
975978

979+
void finalize_log_and(block_t *parent,
980+
basic_block_t **bb,
981+
char *label_else,
982+
basic_block_t *else_bb);
983+
976984
void read_expr(block_t *parent, basic_block_t **bb)
977985
{
978986
ph1_ir_t *ph1_ir;
979987
var_t *vd;
980988
opcode_t oper_stack[10];
981989
int oper_stack_idx = 0;
982990

991+
/* These variables used for parsing logical-and operation. False branch of
992+
* each logical-and operand points to the same basic block.
993+
*/
994+
bool has_log_and = false;
995+
basic_block_t *else_bb = bb_create(parent);
996+
char land_else_label[MAX_VAR_LEN];
997+
strcpy(land_else_label, gen_label());
998+
983999
read_expr_operand(parent, bb);
9841000

9851001
opcode_t op = get_operator();
9861002
if (op == OP_generic || op == OP_ternary)
9871003
return;
988-
989-
oper_stack[oper_stack_idx++] = op;
1004+
if (op == OP_log_and) {
1005+
bb_connect(*bb, else_bb, ELSE);
1006+
read_log_and_operation(parent, bb, land_else_label);
1007+
has_log_and = true;
1008+
} else
1009+
oper_stack[oper_stack_idx++] = op;
9901010
read_expr_operand(parent, bb);
9911011
op = get_operator();
9921012

@@ -1011,8 +1031,25 @@ void read_expr(block_t *parent, basic_block_t **bb)
10111031
same = 1;
10121032
} while (oper_stack_idx > 0 && same == 0);
10131033
}
1034+
if (op == OP_log_and) {
1035+
bb_connect(*bb, else_bb, ELSE);
1036+
read_log_and_operation(parent, bb, land_else_label);
1037+
has_log_and = true;
1038+
}
1039+
/* When encountering an operator with lower priority, conclude the
1040+
* current logical-and and create a new "else" basic block for next
1041+
* logical-and operator.
1042+
*/
1043+
if (has_log_and &&
1044+
get_operator_prio(op) < get_operator_prio(OP_log_and)) {
1045+
finalize_log_and(parent, bb, land_else_label, else_bb);
1046+
else_bb = bb_create(parent);
1047+
strcpy(land_else_label, gen_label());
1048+
has_log_and = false;
1049+
}
10141050
read_expr_operand(parent, bb);
1015-
oper_stack[oper_stack_idx++] = op;
1051+
if (op != OP_log_and)
1052+
oper_stack[oper_stack_idx++] = op;
10161053
op = get_operator();
10171054
}
10181055

@@ -1027,6 +1064,9 @@ void read_expr(block_t *parent, basic_block_t **bb)
10271064
add_insn(parent, *bb, ph1_ir->op, ph1_ir->dest, ph1_ir->src0,
10281065
ph1_ir->src1, 0, NULL);
10291066
}
1067+
if (has_log_and) {
1068+
finalize_log_and(parent, bb, land_else_label, else_bb);
1069+
}
10301070
}
10311071

10321072
/* Return the address that an expression points to, or evaluate its value.
@@ -1343,6 +1383,127 @@ void read_lvalue(lvalue_t *lvalue,
13431383
}
13441384
}
13451385

1386+
void read_log_and_operation(block_t *parent,
1387+
basic_block_t **bb,
1388+
char *label_else)
1389+
{
1390+
char label_true[MAX_VAR_LEN];
1391+
var_t *vd;
1392+
ph1_ir_t *ph1_ir;
1393+
strcpy(label_true, gen_label());
1394+
1395+
/* test the operand before the logical-and operator */
1396+
ph1_ir = add_ph1_ir(OP_branch);
1397+
ph1_ir->dest = opstack_pop();
1398+
vd = require_var(parent);
1399+
strcpy(vd->var_name, label_true);
1400+
ph1_ir->src0 = vd;
1401+
vd = require_var(parent);
1402+
strcpy(vd->var_name, label_else);
1403+
ph1_ir->src1 = vd;
1404+
add_insn(parent, *bb, OP_branch, NULL, ph1_ir->dest, NULL, 0, NULL);
1405+
1406+
/* true branch label */
1407+
ph1_ir = add_ph1_ir(OP_label);
1408+
vd = require_var(parent);
1409+
strcpy(vd->var_name, label_true);
1410+
ph1_ir->src0 = vd;
1411+
1412+
basic_block_t *then_ = bb_create(parent);
1413+
bb_connect(*bb, then_, THEN);
1414+
1415+
bb[0] = then_;
1416+
}
1417+
1418+
void finalize_log_and(block_t *parent,
1419+
basic_block_t **bb,
1420+
char *label_else,
1421+
basic_block_t *else_bb)
1422+
{
1423+
basic_block_t *then_next_ = bb_create(parent);
1424+
basic_block_t *end_ = bb_create(parent);
1425+
bb_connect(*bb, then_next_, THEN);
1426+
bb_connect(*bb, else_bb, ELSE);
1427+
bb_connect(then_next_, end_, NEXT);
1428+
bb_connect(else_bb, end_, NEXT);
1429+
char label_and_true[MAX_VAR_LEN], label_end[MAX_VAR_LEN];
1430+
strcpy(label_and_true, gen_label());
1431+
strcpy(label_end, gen_label());
1432+
var_t *and_res;
1433+
1434+
/* create branch instruction for final logical-and operand */
1435+
ph1_ir_t *ph1_ir = add_ph1_ir(OP_branch);
1436+
var_t *vd = opstack_pop();
1437+
ph1_ir->dest = vd;
1438+
vd = require_var(parent);
1439+
strcpy(vd->var_name, label_and_true);
1440+
ph1_ir->src0 = vd;
1441+
vd = require_var(parent);
1442+
strcpy(vd->var_name, label_else);
1443+
ph1_ir->src1 = vd;
1444+
add_insn(parent, *bb, OP_branch, NULL, ph1_ir->dest, NULL, 0, NULL);
1445+
1446+
/* true branch of the logical-and operation */
1447+
ph1_ir = add_ph1_ir(OP_label);
1448+
vd = require_var(parent);
1449+
strcpy(vd->var_name, label_and_true);
1450+
ph1_ir->dest = vd;
1451+
1452+
ph1_ir = add_ph1_ir(OP_load_constant);
1453+
vd = require_var(parent);
1454+
strcpy(vd->var_name, gen_name());
1455+
vd->init_val = 1;
1456+
ph1_ir->dest = vd;
1457+
add_insn(parent, then_next_, OP_load_constant, ph1_ir->dest, NULL, NULL, 0,
1458+
NULL);
1459+
1460+
ph1_ir = add_ph1_ir(OP_assign);
1461+
and_res = require_var(parent);
1462+
strcpy(and_res->var_name, gen_name());
1463+
ph1_ir->dest = and_res;
1464+
ph1_ir->src0 = vd;
1465+
add_insn(parent, then_next_, OP_assign, ph1_ir->dest, ph1_ir->src0, NULL, 0,
1466+
NULL);
1467+
1468+
/* end of true branch, jump over the false branch */
1469+
ph1_ir = add_ph1_ir(OP_jump);
1470+
vd = require_var(parent);
1471+
strcpy(vd->var_name, label_end);
1472+
ph1_ir->dest = vd;
1473+
1474+
/* false branch of logical-and operation */
1475+
ph1_ir = add_ph1_ir(OP_label);
1476+
vd = require_var(parent);
1477+
strcpy(vd->var_name, label_else);
1478+
ph1_ir->src0 = vd;
1479+
1480+
ph1_ir = add_ph1_ir(OP_load_constant);
1481+
vd = require_var(parent);
1482+
strcpy(vd->var_name, gen_name());
1483+
vd->init_val = 0;
1484+
ph1_ir->dest = vd;
1485+
add_insn(parent, else_bb, OP_load_constant, ph1_ir->dest, NULL, NULL, 0,
1486+
NULL);
1487+
1488+
/* final basic block to retrieve the value from one of previous basic block
1489+
*/
1490+
ph1_ir = add_ph1_ir(OP_assign);
1491+
ph1_ir->dest = and_res;
1492+
ph1_ir->src0 = vd;
1493+
add_insn(parent, else_bb, OP_assign, ph1_ir->dest, ph1_ir->src0, NULL, 0,
1494+
NULL);
1495+
1496+
ph1_ir = add_ph1_ir(OP_label);
1497+
vd = require_var(parent);
1498+
strcpy(vd->var_name, label_end);
1499+
ph1_ir->src0 = vd;
1500+
1501+
and_res->is_log_and_ret = true;
1502+
opstack_push(and_res);
1503+
1504+
bb[0] = end_;
1505+
}
1506+
13461507
void read_ternary_operation(block_t *parent, basic_block_t **bb)
13471508
{
13481509
char true_label[MAX_VAR_LEN], false_label[MAX_VAR_LEN];
@@ -2074,6 +2235,8 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
20742235
strcpy(var_break->var_name, label_end);
20752236
break_exit[break_exit_idx++] = var_break;
20762237

2238+
basic_block_t *cond = bb_create(parent);
2239+
cond = bb;
20772240
lex_expect(T_open_bracket);
20782241
read_expr(parent, &bb);
20792242
lex_expect(T_close_bracket);
@@ -2118,7 +2281,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
21182281

21192282
/* return, break, continue */
21202283
if (body_)
2121-
bb_connect(body_, bb, NEXT);
2284+
bb_connect(body_, cond, NEXT);
21222285

21232286
return else_;
21242287
}
@@ -2365,9 +2528,9 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
23652528

23662529
basic_block_t *cond_ = bb_create(blk);
23672530
basic_block_t *for_end = bb_create(parent);
2531+
basic_block_t *cond_start = cond_;
23682532
break_bb[break_exit_idx] = for_end;
23692533
bb_connect(setup, cond_, NEXT);
2370-
bb_connect(cond_, for_end, ELSE);
23712534

23722535
/* condition - check before the loop */
23732536
ph1_ir = add_ph1_ir(OP_label);
@@ -2388,6 +2551,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
23882551
add_insn(blk, cond_, OP_load_constant, ph1_ir->dest, NULL, NULL, 0,
23892552
NULL);
23902553
}
2554+
bb_connect(cond_, for_end, ELSE);
23912555

23922556
ph1_ir = add_ph1_ir(OP_branch);
23932557
ph1_ir->dest = opstack_pop();
@@ -2443,7 +2607,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
24432607

24442608
if (body_) {
24452609
bb_connect(body_, inc_, NEXT);
2446-
bb_connect(inc_, cond_, NEXT);
2610+
bb_connect(inc_, cond_start, NEXT);
24472611
} else {
24482612
/* TODO: Release dangling inc basic block */
24492613
}

src/riscv-codegen.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -412,15 +412,6 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
412412
emit(__sltu(rd, __zero, rs1));
413413
emit(__xori(rd, rd, 1));
414414
return;
415-
case OP_log_and:
416-
/* TODO: short-circuit evaluation */
417-
emit(__xor(__t0, rs1, rs2));
418-
emit(__sub(rd, __t0, rs1));
419-
emit(__sub(__t0, __t0, rs2));
420-
emit(__sltu(rd, __zero, rd));
421-
emit(__sltu(__t0, __zero, __t0));
422-
emit(__and(rd, rd, __t0));
423-
return;
424415
case OP_log_or:
425416
emit(__or(rd, rs1, rs2));
426417
emit(__sltu(rd, __zero, rd));

src/ssa.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ bool insert_phi_insn(basic_block_t *bb, var_t *var)
409409
bb->insn_list.head = n;
410410
bb->insn_list.tail = n;
411411
} else {
412+
head->prev = n;
412413
n->next = head;
413414
bb->insn_list.head = n;
414415
}
@@ -455,13 +456,14 @@ void solve_phi_insertion()
455456
if (insert_phi_insn(df, var)) {
456457
bool found = false;
457458

458-
/* Restrict phi insertion of ternary operation.
459+
/* Restrict phi insertion of ternary operation and
460+
* logical-and operation.
459461
*
460-
* The ternary operation doesn't create new scope, so
461-
* prevent temporary variable from propagating through
462-
* the dominance tree.
462+
* The ternary and logical-and operation doesn't create
463+
* new scope, so prevent temporary variable from
464+
* propagating through the dominance tree.
463465
*/
464-
if (var->is_ternary_ret)
466+
if (var->is_ternary_ret || var->is_log_and_ret)
465467
continue;
466468

467469
for (int l = 0; l < work_list_idx; l++)
@@ -665,6 +667,8 @@ void bb_unwind_phi(fn_t *fn, basic_block_t *bb)
665667
bb->insn_list.head = insn;
666668
if (!insn)
667669
bb->insn_list.tail = NULL;
670+
else
671+
insn->prev = NULL;
668672
}
669673

670674
void unwind_phi()

0 commit comments

Comments
 (0)