Hello, I'm currently writing a gcc 4.4.5 backend for an 18 bit architecture. I have a c-project with some thousand lines of code. Without optimizations it compiles. But with -O1 and -O2 I encounter a problem in the induction variables optimization pass. The main issue is, that a temporary variable is created which works as a memory reference but is a 36 bit value (SImode). This results in an error at explow.c line 326, because pointers have to be 18 bit wide (HImode). The code at this position is:
rtx convert_memory_address (enum machine_mode to_mode ATTRIBUTE_UNUSED, rtx x) { #ifndef POINTERS_EXTEND_UNSIGNED gcc_assert (GET_MODE (x) == to_mode || GET_MODE (x) == VOIDmode); This asserts because x has mode SI and to_mode is Pmode/HImode. I used the -fdump-tree-all option and in the source.c.126t.final_cleanup file I found the following: isr00 () { unsigned int ivtmp.112; unsigned int D.3690; long unsigned int D.3683; unsigned int ivtmp.105; unsigned int ivtmp.104; unsigned int prephitmp.91; unsigned int length; unsigned int D.1415; struct usb * usb0.0; … <bb 5>: D.3683 = (long unsigned int) ivtmp.105 + (long unsigned int) ((unsigned int *) (long unsigned int) usb0.0 + 320); spi_temporary_data[ivtmp.112] = [bit_and_expr] (unsigned char) (MEM[base: D.3683] >> 8) & 255; spi_temporary_data[ivtmp.112 + 1] = [bit_and_expr] (unsigned char) MEM[base: D.3683] & 255 The problem is the D.3683 variable. The casts in the assignment for this variable are kind of senseless, because ivtmp.105 is unsigned int (18 bit), usb0.0 is a pointer which is also only 18 bit. I checked the source files and I think the main problem is the use of sizetype in several locations working with addresses. sizetype is defined as long unsigned int and results in SImode when used. I found 3 code positions with an input tree mode of HImode where the use of sizetype or size_type_node results in a tree node with SImode: tree-ssa-address.c line 414 here parts->index becomes a SImode tree node static void add_to_parts (struct mem_address *parts, tree elt) { tree type; if (!parts->index) { parts->index = fold_convert (sizetype, elt); return; } tree-ssa-address.c line 547 here part becomes a SImode tree node static void addr_to_parts (aff_tree *addr, struct mem_address *parts, bool speed) { ... /* Then try to process the remaining elements. */ for (i = 0; i < addr->n; i++) { part = fold_convert (sizetype, addr->elts[i].val); ... } tree.cline 8332 here t becomes a SImode tree node signed_or_unsigned_type_for (int unsignedp, tree type) { tree t = type; if (POINTER_TYPE_P (type)) t = size_type_node; if (!INTEGRAL_TYPE_P (t) || TYPE_UNSIGNED (t) == unsignedp) return t; return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp); } As a solution, I tried to replace those 3 sizetype uses with global_trees[TI_UINTHI_TYPE]. So the relevant lines look like this: parts->index = fold_convert (global_trees[TI_UINTHI_TYPE] /*sizetype*/, elt); part = fold_convert (global_trees[TI_UINTHI_TYPE] /*sizetype*/, addr->elts[i].val); t = global_trees[TI_UINTHI_TYPE] /*size_type_node*/; With those changes, the compilation comes farther but crashes on the following gcc_assert: tree.cline 3312function build2_stat if (code == POINTER_PLUS_EXPR && arg0 && arg1 && tt) gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0)) && INTEGRAL_TYPE_P (TREE_TYPE (arg1)) && useless_type_conversion_p (sizetype, TREE_TYPE (arg1))); If I comment out the "&& useless_type_conversion_p (sizetype, TREE_TYPE (arg1))" part the compilation works. I know its bad, but I don't know how to replace the sizetype in this case so that the assert doesn't happen. I'm aware of the fact that those fixes would result in errors with other architectures. But just for my "strange 18 bit" architecture, is this ok? Might there be problems in some cases? Why is sizetype used in this positions anyways? Wouldn't it be better to somehow use the input tree type instead of sizetype? I hope the description of the problem is understandable. Regards, Eric Neumann