Skip to content
This repository was archived by the owner on Dec 23, 2025. It is now read-only.
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

@zu2

Description

@zu2

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

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions