This repository was archived by the owner on Dec 23, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 23
This repository was archived by the owner on Dec 23, 2025. It is now read-only.
be-codegen-6800.c be-code-6800.c Ideas for making signed/unsigned char comparisons more efficient #162
Copy link
Copy link
Open
Labels
enhancementNew feature or requestNew feature or request
Description
If both can be compared as char, gen_rewrite rewrites the AST to reduce T_CAST. This allows cmp_direct to generate efficient code.
The problem with this method is that the code becomes more complicated as the number of patterns that can be made more efficient increases (global variables can also be made more efficient).
I'm also concerned that gen_rewrite and cmp_direct perform similar comparisons. However, cmp_direct alone was unable to remove unnecessary casts, so the code looks like this.
Now, if we make it more efficient like this, the jsr boolXX/jeq after cmpb can become jXX. To do this, I need to know that this comparison does not require a result (0/1). How can I know that?
diff -u ../Fuzix-Compiler-Kit/be-codegen-6800.c be-codegen-6800.c
--- ../Fuzix-Compiler-Kit/be-codegen-6800.c 2024-11-13 00:32:04
+++ be-codegen-6800.c 2024-11-13 14:07:11
@@ -374,6 +375,46 @@
n->left = r;
}
}
+ if (op == T_EQEQ || op == T_BANGEQ || op == T_LT || op == T_LTEQ || op == T_GT || op == T_GTEQ) {
+ if (l->op == T_CAST && l->type == CSHORT
+ && l->right->op == T_LREF && l->right->type == CCHAR
+ && r->op == T_CONSTANT && -128<=(long)r->value && r->value<=127) {
+ squash_right(l, T_LREF);
+ l->type = CCHAR;
+ r->type = CCHAR;
+ }
+ if (l->op == T_CAST && l->type == CSHORT
+ && l->right->op == T_LREF && l->right->type == CCHAR
+ && r->op == T_CAST && r->type == CSHORT
+ && r->right->op == T_LREF && r->right->type == CCHAR ){
+ squash_right(l, T_LREF);
+ squash_right(r, T_LREF);
+ l->type = CCHAR;
+ r->type = CCHAR;
+ }
+ if (l->op == T_CAST && l->type == CSHORT
+ && l->right->op == T_LREF && l->right->type == UCHAR
+ && r->op == T_CONSTANT && 0<=r->value && r->value<=255) {
+ squash_right(l, T_LREF);
+ l->type = UCHAR;
+ r->type = UCHAR;
+ }
+ if (l->op == T_CAST && l->type == USHORT
+ && l->right->op == T_LREF && l->right->type == UCHAR
+ && r->op == T_CAST && r->type == USHORT
+ && r->right->op == T_LREF && r->right->type == UCHAR ){
+ squash_right(l, T_LREF);
+ squash_right(r, T_LREF);
+ l->type = UCHAR;
+ r->type = UCHAR;
+ }
+ }
return n;
}
diff -u ../Fuzix-Compiler-Kit/be-code-6800.c be-code-6800.c
--- ../Fuzix-Compiler-Kit/be-code-6800.c 2024-11-13 00:32:04
+++ be-code-6800.c 2024-11-13 13:57:31
@@ -990,32 +986,36 @@
unsigned cmp_direct(struct node *n, const char *uop, const char *op)
{
register struct node *r = n->right;
+ register struct node *l = n->left;
register unsigned v = r->value;
register unsigned s = get_size(r->type);
- if (r->op != T_CONSTANT)
- return 0;
if (r->type & UNSIGNED)
op = uop;
- /* If we knoww the upper half matches - eg a byte var that has been expanded then
- shortcut it. Need to think about this for signed math. I think we can do signed
- math if we use uop in the size 2 upper match case : TODO*/
- if (s == 1 || (op == uop && a_valid && (v >> 8) == a_val)) {
- printf("\tcmpb #%u\n\t%s %s\n", v & 0xFF, jsr_op, op);
- n->flags |= ISBOOL;
- invalidate_b();
- return 1;
+ if (s == 1) {
+ if ((r->op == T_CONSTANT && l->type == UCHAR && r->value>=0 && r->value<=255)
+ || (r->op == T_CONSTANT && l->type == CCHAR && (int)r->value>=-128 && (int)r->value<=127)
+ || (r->op == T_LREF && l->type == r->type)) {
+ op8_on_node(r, "cmp", 0);
+ printf("\t%s %s\n",jsr_op,(l->type==UCHAR)?uop:op);
+ n->flags |= ISBOOL;
+ invalidate_b();
+ return 1;
+ }
}
- if (s == 2) {
+ if (s == 2 && r->op == T_CONSTANT) {
/* If we know the value of A (eg from a cast) */
if (cpu_has_d) {
+ if (r->type & UNSIGNED)
+ op = uop;
printf("\tsubd #%u\n\t%s %s\n", v & 0xFFFF, jsr_op, op);
n->flags |= ISBOOL;
invalidate_work();
return 1;
}
}
+
return 0;
}
sample program:
int
main(int argc, char **argv)
{
signed char i=0;
signed char k=0;
signed char j=10;
while (i<j) {
i++;
}
if (i!=10)
return 1;
return 0;
}
compiled asm at while loop.
;make local ptr off 0, rlim 255 noff 0
tsx
ldb 0,x
;make local ptr off 2, rlim 255 noff 2
cmpb 2,x
jsr boollt
;
jeq L1_b
if statement.
;make local ptr off 0, rlim 255 noff 0
tsx
ldb 0,x
cmpb #<10
jsr boolne
;
jeq L2_e
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request