Nios2 arch=r1/r2
Hi, I'm looking at gcc-nios2 options -march. It seems two instruction sets can be selected (r1/r2) but I cannot find out where theses instructions set are described. On the other end I found this document https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/nios2/n2cpu_nii51017.pdf which describes several updates of the instruction set (section Document Revision History) from 2004 to 2015. I'm looking for a recent gcc-nios2 compiler compatible pour nios2 version 6.1 (November 2006) i.e. without the 'jmpi' instruction. Do I have to modify the backend to add a -mno-jmpi option ? Regards, Selim
LTO + conditional jump + delay slot
Hi, I encountered a problem on test 'gcc.c-torture/execute/loop-7.c' (gcc4.7.3) on my private port during test case "-O2 -flto -fuse-linker-plugin -fno-fat-lto-objects" Here is the tested code : void foo (unsigned int n) { int i, j = -1; for (i = 0; i < 10 && j < 0; i++) { if ((1UL << i) == n) j = i; } if (j < 0) abort (); } main() { foo (64); exit (0); } The LTO option merge the foo function into the main function. I'll try present my problem by simplifying the resulting assembler. : :L1 [...] << content of the loop compare 0, $R0 << test to know if the loop goes on or stop ($R0 synthetize the whole loop end condition) jump_delayed.ifNE L1 << conditional delayed jump : the loop end if $R0 == 0 nop #delayslot1 sll $R1, 1, $R0 #delayslot2 << instruction which is part of the loop content but placed into the 2nd delay slot of jump_delayed.ifNE instruction compare -1, $R2 << test if (j < 0) branch.ifeq abort<< conditional branch to abort branch exit << branch to exit which expect a 0 into $R0 as first parameter The test fail, not because abort is called, but because exit is called with $R0 containing 0x80 and not 0. I think GCC expect $R0 to be equal to 0 when the loop end (so no need to set explicitly $R0 to 0) But in this case the 'sll' instruction placed into the delay slot of the conditional delayed jump modify $R0 even if no jump is performed. Is it a bug due to LTO merging the 'foo' and 'main' function ? Or does GCC really thinks that the instructions placed into the delay slot of conditional jump are executed only if the condition is true ? Or is it simply a GCC incompatibility between 'conditional jump' & 'delay slots' ? Here are some parts of my backend relative to delay slot and conditional jump (nothing formidable :) ): (define_delay (ior (eq_attr "type" "jump") (eq_attr "type" "cond_jump")) [(and (eq_attr "delayable" "yes") (eq_attr "length" "1")) (nil) (nil) (and (eq_attr "delayable" "yes") (eq_attr "length" "1")) (nil) (nil)]) (define_insn "jumpif" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(match_operand 2 "cc_register" "") (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc)))] "" { [...] // use final_sequence to detect delay slot } [set_attr "type" "cond_jump") (set_attr "delayable" "no")] Regards, Selim
Gimplilfy ICE in gnat.dg/array18.adb
Hi, On my private port, I'm unable to debug an ICE on GCC4.7.3 (GNAT 7.1.2) during the internal test testsuite/gnat.dg/array18.adb. Here is the test source code: - with Array18_Pkg; use Array18_Pkg; procedure Array18 is A : String (1 .. 1); begin A := F; end; - - package Array18_Pkg is function N return Positive; subtype S is String (1 .. N); function F return S; end Array18_Pkg; - The size of the String returned by 'F' can't be known at compile time. GNAT will compare the size of the returned string to the size of 'A' at runtime (to call last_chance_handler or not). The ICE is an assert inside force_constant_size of gimplify.c (at line 717) : --- static void force_constant_size (tree var) { /* The only attempt we make is by querying the maximum size of objects of the variable's type. */ HOST_WIDE_INT max_size; gcc_assert (TREE_CODE (var) == VAR_DECL); max_size = max_int_size_in_bytes (TREE_TYPE (var)); gcc_assert (max_size >= 0); max_size = -1 !! DECL_SIZE_UNIT (var) = build_int_cst (TREE_TYPE (DECL_SIZE_UNIT (var)), max_size); DECL_SIZE (var) = build_int_cst (TREE_TYPE (DECL_SIZE (var)), max_size * BITS_PER_UNIT); } --- The 'var' parameter contains : --- unit size align 8 symtab 0 alias set -1 canonical type 0x2ab02348 precision 8 min max context pointer_to_this > sizes-gimplified visited nonaliased-component BLK size readonly visited arg 0 readonly visited arg 0 > arg 1 > unit size readonly visited arg 0 > align 8 symtab 0 alias set 0 canonical type 0x2abb2f18 domain sizes-gimplified visited SI size unit size align 32 symtab 0 alias set -1 canonical type 0x2abb2e70 precision 32 min max index type chain > context chain > used ignored BLK file /vues_statiques/FPGA/belbachir/prism/compiler/gcc_test/internal/../../gcc/gcc/testsuite/gnat.dg/array18.adb line 9 col 9 size unit size align 8> --- I used -fdump-tree-all option and run my cross compiler and the native x86_64 compiler (same GCC/GNAT version) to compare the dumps I don't have the same results event in the first dump : >> X86_64 array18.adb.003t.original : -- Array18 () { typedef array18__TTaSP1___XDLU_1__1 array18__TTaSP1___XDLU_1__1; typedef struct ; typedef character array18__TaS[1:1]; character a[1:1]; character R.0[1:(sizetype) (integer) array18_pkg__R1s]; typedef array18__TTaSP1___XDLU_1__1 array18__TTaSP1___XDLU_1__1; typedef struct ; typedef character array18__TaS[1:1]; character a[1:1]; if (array18_pkg__R1s != 1) { .gnat_last_chance_handler ("array18.adb", 9); } else { } character R.0[1:(sizetype) (integer) array18_pkg__R1s]; R.0 = array18_pkg.f (); a = VIEW_CONVERT_EXPR(R.0); return; } _GLOBAL.SZ0.ada_array18 (integer p0, integer p1) { return p1 <= p0 ? (bitsizetype) sizetype) p0 - (sizetype) p1) + 1) * 8) : 0; _GLOBAL.SZ1.ada_array18 (integer p0, integer p1) { return p1 <= p0 ? ((sizetype) p0 - (sizetype) p1) + 1 : 0; -- >> MyPort array18.adb.003t.original : -- Array18 () { typedef array18__TTaSP1___XDLU_1__1 array18__TTaSP1___XDLU_1__1; typedef struct ; typedef character array18__TaS[1:1]; typedef struct array18__a___PAD array18__a___PAD; struct array18__a___PAD a; typedef array18__TTaSP1___XDLU_1__1 array18__TTaSP1___XDLU_1__1; typedef struct ; typedef character array18__TaS[1:1]; typedef struct array18__a___PAD array18__a___PAD; struct array18__a___PAD a; if (array18_pkg__R1s != 1) { .gnat_last_chance_handler ("array18.adb", 9); } else { } a = {.F=VIEW_CONVERT_EXPR(array18_pkg.f ())}; return; } _GLOBAL.SZ0.ada_array18 (integer p0, integer p1) { return p1 <= p0 ? ((bitsizetype) ((sizetype) p0 - (sizetype) p1) + 1) * 8 : 0; _GLOBAL.SZ1.ada_array18 (integer p0, integer p1) { return p1 <= p0 ? ((sizetype) p0 - (sizetype) p1) + 1 : 0; -- The next 004t.gimple dump is incomplete since the ICE is during gimplify pass. Using debugger I saw that the X86_64 port never goes inside force_constant_size (where is located the ICE on my port)... Can someone give me a hint to solve my problem ? I have no idea which part of my backend could be related to the GENERIC or GIMPLE generation and I'm very unfamiliar with this part of GCC. Regards, Selim Belbachir
RE: Gimplilfy ICE in gnat.dg/array18.adb
arg 0 readonly visited arg 0 readonly visited arg 0 >>> arg 1 > unit size align 8 symtab 0 alias set 0 canonical type 0x2ad27c8ee498 domain unit size align 64 symtab 0 alias set -1 canonical type 0x2ad27c79a000 precision 64 min max > sizes-gimplified visited DI size unit size align 64 symtab 0 alias set -1 canonical type 0x2ad27c8ee3f0 precision 64 min max index type sizes-gimplified public visited unsigned SI size unit size align 32 symtab 0 alias set 0 canonical type 0x2ad27c8ee150 precision 32 min max context RM size RM min RM max chain > chain > context chain > There are also differenced in the gnu_result_type I cannot explain ... -Message d'origine- De : Eric Botcazou [mailto:ebotca...@adacore.com] Envoyé : vendredi 6 juin 2014 00:00 À : BELBACHIR Selim Cc : gcc@gcc.gnu.org Objet : Re: Gimplilfy ICE in gnat.dg/array18.adb > Can someone give me a hint to solve my problem ? I have no idea which > part of my backend could be related to the GENERIC or GIMPLE > generation and I'm very unfamiliar with this part of GCC. Look at the patch installed in conjunction with gnat.dg/array18.adb. -- Eric Botcazou
RE: Gimplilfy ICE in gnat.dg/array18.adb
The intent of the patch change is clear. The strange thing concern the variable "A" declared this way "A : String (1 .. 1);", used that way "A := F;" and displayed in tree (gnu_target) as a RECORD_TYPE instead of an ARRAY_TYPE. The test to know if a temporary for return value is needed only check ARRAY_RANGE_REF and ARRAY_TYPE and not RECORD_TYPE : TREE_CODE (gnu_target) == ARRAY_RANGE_REF || (TREE_CODE (TREE_TYPE (gnu_target)) == ARRAY_TYPE && TREE_CODE (TYPE_SIZE (TREE_TYPE (gnu_target))) == INTEGER_CST) I don't why in my case fixed Strings are RECORD_TYPE and not ARRAY_TYPE. Maybe its normal and I should extend the if condition with RECORD_TYPE : TREE_CODE (gnu_target) == ARRAY_RANGE_REF || (TREE_CODE (TREE_TYPE (gnu_target)) == ARRAY_TYPE && TREE_CODE (TYPE_SIZE (TREE_TYPE (gnu_target))) == INTEGER_CST) || (TREE_CODE (TREE_TYPE (gnu_target)) == RECORD_TYPE && TREE_CODE (TYPE_SIZE (TREE_TYPE (gnu_target))) == INTEGER_CST) -Message d'origine- De : gcc-ow...@gcc.gnu.org [mailto:gcc-ow...@gcc.gnu.org] De la part de Eric Botcazou Envoyé : vendredi 6 juin 2014 10:20 À : BELBACHIR Selim Cc : gcc@gcc.gnu.org Objet : Re: Gimplilfy ICE in gnat.dg/array18.adb > strangely my var_decl for 'a' is a record and not an array_type so the 'if' > condition is false (and true on X86_64) I looked for somewhere in > my backend something that would transform an array_type into a > record_type but I did not find anything. The comment should clearly state the intent of the change though and how to adjust it to your needs. -- Eric Botcazou
RE: gnat.dg test: div_no_warning.adb
Hi, I've noticed that Constraint_error warning produced by gcc/testsuite/gnat.dg/div_no_warning.adb disappears if the target runtime contains : "Configurable_Run_Time : constant Boolean := False;" * x86 native gnat contains Configurable_Run_Time := False ==> no warning * Cross gnat port without full runtime contains Configurable_Run_Time := True ==> warning raised When I read the description of "Configurable_Run_Time_On_Target : Boolean := False;" in gcc/ada/targparm.ads (which may not be complete) I don't see any relation with this particular constraint error raising. Can someone explain what are the full impact of Configurable_Run_Time boolean in system.ads and what is the relation between it and the "constant folding for short-circuit control forms" tested by gcc/testsuite/gnat.dg/div_no_warning.adb ? Regards, Selim
implicit gnat_malloc seen as vararg function
Hi, I'm working on a private port of GCC 4.7.3/GNAT 7.1.2. Calls to ADA 'new' operator generates implicit gnat_malloc(size) calls (which has to be provided by user program or runtime). In my macro INIT_CUMULATIVE_ARGS I noticed that gnat_malloc(size) calls are seen as vararg function because the tree.c function stdarg_p(fntype) returns true. This creates bad code because caller put the argument in stack (this is normal behaviour for my vararg functions) whereas the callee expected argument in register (gnat_malloc signature should only contains the 'size' argument of type size_type). microblaze and iq2000 backend should have the same problem because inside INIT_CUMULATIVE_ARGS macro, variable argument function are identified by browsing fntype tree chain (like stdarg_p does) Do I have to fix the GNAT frontend or did I missed an option dealing with gnat_malloc behaviour ? Regards, Selim Belbachir
RE: implicit gnat_malloc seen as vararg function
Hi, I have more info concerning my gnat_malloc problem. I watched the code in gcc/ada/gcc-interface/trans.c and found the location where malloc_decl tree is built. In gigi ()function (trans.c:411), the ftype for malloc_decl is done this way : ftype = build_function_type_list (ptr_void_type_node, sizetype, NULL_TREE); I looked at the code of build_function_type_list_1 in tree.c and found that stdargs function are built with their chained list of argument ending with a void_list_node : { last = args; args = nreverse (args); TREE_CHAIN (last) = void_list_node; } But I also noticed that void_list_node was a null pointer!! instead of being a node with TREE_VALUE = void_type_node and no TREE_CHAIN (as described in tree.h) So I wondered, where should void_list_node be initialized in GNAT frontend and noticed that the initialization of void_list_node was done AFTER its use to declare ftype for malloc_decl. ftype for malloc_decl is initialized in gigi() function at trans.c:411 whereas void_list_node in only initialized in gigi() function at trans.c:665 by a call to gnat_install_builtins() ---> install_builtin_elementary_types() --> void_list_node = build_void_list_node (); It seems like a bug. Is it a known one ? someone has the proper fix ? I put the call to gnat_install_builtins() higher inside gigi() and it solve my current problem but I'm not sure exactly when it has to be called and if there are bad side effects. Regards, Selim Belbachir
g++.dg/lto/lto.exp bug
Hi, In gcc 4.7.3 I found a bug in the testsuite script g++.dg/lto/lto.exp when a target does not support LTO (ENABLE_LTO not defined) The following lines : if { ![check_effective_target_lto] } { return } Should be called before : g++_init lto_init no-mathlib (Like in gcc.dg/lto/lto.exp) Otherwise 'lto_init' may hack board_info (removing the mathlib option) without being restored by 'lto_finish' because of the brutal return after 'check_effective_target_lto' Selim
bug in lra-constraints.c (simple_move_p register_move_cost)
Hi, I may have found a bug when I was trying to port my private backend to new LRA pass (using gcc 4.9.2+patches). In lra-constraints.c, in function simple_move_p, the target hook targetm.register_move_cost is called with two badly swapped parameters : targetm.register_move_cost (GET_MODE (src), sclass, dclass) should be : targetm.register_move_cost (GET_MODE (src), dclass, sclass) In my port of GCC it leads to an error when checking constrain_operands at the end of LRA pass Regards, Selim Belbachir
try_merge_delay_insn with delay list > 1
Hi, I'm still working on a private backend on gcc 4.9.2. My processor provides instructions with 2 delay slots. I'm well aware that this feature is very uncommon and not fully tested. Nevertheless I submit the problem and the solution I've found. The bug is located in the function try_merge_delay_insns(INSN, THREAD) in reorg.c. In there, gcc " tries to merge insns starting at THREAD which match exactly the insns in INSN's delay list ". Suppose INSN is a 'delayed jump' filled with 2 delayed insns : jmp_if_EQ_delayed .L1 # jump to L1 if condition code indicates equality mov r1, r2 mov r3, mem(r1++) # move r0 in memory pointed by r6 and post increment r6 and TARGET is a 'delayed jump if zero' filled with 1 delayed insn : jmpz_delayed --r7, L2# decrement r7 and jump L2 if r7 == 0 mov r1, r2 The current implementation of try_merge_delay_insns(INSN, THREAD) will delete 'mov r1,r2' from the delay slot of TARGET because it matches the 'mov r1,r2' inside INSN delay list. No check verifies that r1 has changed between the 2 'mov r1,r2' insns. I attached a patch that tries to solve this problem. Regards, Selim try_merge_patch Description: try_merge_patch
RE: try_merge_delay_insn with delay list > 1
Me again :) I enhanced my patch because it was not generalized for instructions with N delay_slots. Selim try_merge_patch2 Description: try_merge_patch2
RE: try_merge_delay_insn with delay list > 1
I've attached the fixed version of the patch. I've tested it on the trunk with my private target. I can't provide a test because apparently no backend (other than my private one) uses delay slots with more that 1 slot. I was also unable to test the behaviour of this patch for an hypothetic target providing delay lots with more that 1 slot AND the possibility to annul instruction in delay slots. It seems to me that this patch is a small enhancement anyway. I hope it's ok for trunk :) Regards, Selim -Message d'origine- De : Jeff Law [mailto:l...@redhat.com] Envoyé : vendredi 17 avril 2015 18:41 À : BELBACHIR Selim; gcc@gcc.gnu.org Objet : Re: try_merge_delay_insn with delay list > 1 On 03/10/2015 07:40 AM, BELBACHIR Selim wrote: > Me again :) > > I enhanced my patch because it was not generalized for instructions with N > delay_slots. Mostly OK, though there are some formatting nits that need to be corrected. We have whitespace around arithmetic, logical and comparison operators to separate them from their operands. So instead of slot_number+j Use slot_number + j Instead of j=1 Use j = 1 Lines should be wrapped at 80 columns. So you end up with something like this foo (argument1, argument2, argument3) ie, when you wrap, the arguments to the call will line up vertically. It may help wrapping to create a local variable to hold PATTERN (insn). Call it 'pat' :-) When referring to variables or parameters in a comment, capitalize them. The patch may need updating for the trunk, please test it with the trunk when you ask for it to be included on the trunk. These are all fairly minor issues. The actual change seems reasonable. What systems do you have that you could do a bootstrap and regression test with? Ideally since you're changing the delay slot branching code it'd be a system with delay slots :-) If that's not possible because you don't have access to a bootstrapping system with delay slots, make sure to mention it. Ideally you'd have a test for this bug. However, with a private port I wouldn't consider it a necessity. However, you may want to go ahead and create one for internal uses. And if you ever submit your port to the offficial sources, you can include target specific tests at that time. try_merge_patch3 Description: try_merge_patch3
RE: try_merge_delay_insn with delay list > 1
Great, I'll read more closely formatting rules next time I'll submit something. Regards, Selim -Message d'origine- De : Jeff Law [mailto:l...@redhat.com] Envoyé : lundi 20 avril 2015 19:47 À : BELBACHIR Selim; gcc@gcc.gnu.org Objet : Re: try_merge_delay_insn with delay list > 1 On 04/20/2015 05:08 AM, BELBACHIR Selim wrote: > I've attached the fixed version of the patch. I've tested it on the trunk > with my private target. > > I can't provide a test because apparently no backend (other than my private > one) uses delay slots with more that 1 slot. > I was also unable to test the behaviour of this patch for an hypothetic > target providing delay lots with more that 1 slot AND the possibility to > annul instruction in delay slots. > > It seems to me that this patch is a small enhancement anyway. > I hope it's ok for trunk :) Even for small enhancements or bugfixes, we try to at least do some basic testing. Unfortunately with no sparc or mips machines in the compile farm, good testing of a reorg.c change is hard. I built mips-elf cross tools and used those to compile newlib for mips-elf. Then I applied your patch, rebuilt the compiler and used that to compile newlib again. Then I compared all the objects from the two copies of newlib and verified the code we generated as identical. So there's at least some degree of confidence we didn't mess anything up in the single delay slot case. I fixed a couple more minor formatting problems and installed your change on the trunk. jeff
postreload problem using reload_inm and SECONDARY_RELOAD macros
Hi, I'm writing a backend for gcc3.4.6 and I'm a bit confused about reload passes. -> my constraints : 'b' = arithmetic/logical unit register ($R, class R_REGS) 'c' = counter register ($C, class C_REGS) 'v' = memory with several special constraint (also described in predicate my_mem_or_reg_operand) -> movsi expand/insn : (define_insn "movsi_internal" [(set (match_operand:SI 0 "my_mem_or_reg_operand" "=v,v,c,b,b ") (match_operand: SI 1 "general_operand" "c,b,v,v,i "))] "" "@ mov %1,%0 [.] loadi %1,%0" ) (define_expand "movsi" [(set (match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "general_operand" ""))] "" { /* Handle Memory to Memory and immediate to memory movs */ if (((GET_CODE (operands[1]) == MEM) || immediate_operand (operands[1], SImode)) && (GET_CODE(operands[0])== MEM) ) { operands[1] = force_reg(SImode,operands[1]); } } ) Note there is no instruction to move immediate to $R regs ('b' constraint) but there is one to move immediate to $C regs ('c' constraint). I have no mean to express this limitation inside predicates (because pseudo register don't known in which hard register they will be allocated), reload pass create some moves from immediate to $R. : arithmetic.c:197: error: insn does not satisfy its constraints: (insn 1505 903 1506 0 (set (reg:SI 25 $R9) (const_int 8 [0x8])) 0 {movsi_internal} (nil) (nil)) arithmetic.c:197: internal compiler error: in reload_cse_simplify_operands, at postreload.c:391 So, I read the doc :) and figured out how to control the reload pass. I added 2 MACROs and the reload_insi expand : #define PREFERRED_RELOAD_CLASS(X,CLASS) my_preferred_reload_class(X,CLASS) #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) my_secondary_input_reload_class (CLASS, MODE, X) enum reg_class my_preferred_reload_class(rtx x, enum reg_class rclass) { if (GET_CODE(x) == CONST_INT || GET_CODE(x) == CONST_DOUBLE) { if (rclass == GENERAL_REGS) { return C_REGS; } else if (rclass == R_REGS) { return NO_REGS; /* put the constant in memory */ } } return rclass; } enum reg_class my_secondary_input_reload_class(enum reg_class rclass, enum machine_mode mode, rtx x) { if ((GET_CODE(x) == CONST_INT || GET_CODE(x) == CONST_DOUBLE) && rclass == R_REGS) { return C_REGS; /* use C_REGS for clobber in reload_insi */ } return NO_REGS; } (define_expand "reload_insi" [(set (match_operand:SI 0 "register_operand" "=b") (match_operand:SI 1 "immediate_operand" "i")) (clobber (match_operand:SI 2 "register_operand" "=c"))] " { emit_insn(gen_rtx_SET(SImode, operands[2], operands[1])); emit_insn(gen_rtx_SET(SImode, operands[0], operands[2])); DONE; } ) Theses MACROs and insn do not solve my problem and the forbidden move keeps on being emitted. Did I misunderstood something ? A my doing something illegal ? Should I do things differently? (A printf in my reload_insi shows that this expand is never called.) Thank you for your help.
RE: postreload problem using reload_inm and SECONDARY_RELOAD macros
Yes I know gcc 3.4.6 is quite old :) but the backend work has started on this version for bad reasons and now we plan to make something work (pass a few test cases) before migrating to last gcc 4 version. Concerning REGISTER_MOVE_COST, I don't know what can be fixed with it. The 3 params of REGISTER_MOVE_COST are (machine_mode mode, regclass from, reg_class to). So I can only write cost for register to register moves. I don't see any suitable macro to specify immediate to register moves. (in gcc3.4.6 internals ) Nevertheless, the REGISTER_MOVE_COST is defined with costs 3 for all valid moves (C_REGS <-> R_REGS). Is there a way to prevent totally the allocation of a hard register in specific context using 'costs'? -Message d'origine- De : Ian Lance Taylor [mailto:i...@google.com] Envoyé : mercredi 14 septembre 2011 15:40 À : BELBACHIR Selim Cc : gcc@gcc.gnu.org Objet : Re: postreload problem using reload_inm and SECONDARY_RELOAD macros BELBACHIR Selim writes: > I'm writing a backend for gcc3.4.6 and I'm a bit confused about reload passes. You know gcc 3.4.6 is really old, right? > I have no mean to express this limitation inside predicates (because > pseudo register don't known in which hard register they will be > allocated), reload pass create some moves from immediate to $R. : First guess would be REGISTER_MOVE_COST. Ian
RE: postreload problem using reload_inm and SECONDARY_RELOAD macros
further hints : The immediate which gcc wants to move in R_REGS is a (const_int 8) as described in the error message below : arithmetic.c:197: error: insn does not satisfy its constraints: (insn 1505 903 1506 0 (set (reg:SI 25 $R9) (const_int 8 [0x8])) 0 {movsi_internal} (nil) (nil)) arithmetic.c:197: internal compiler error: in reload_cse_simplify_operands, at postreload.c:391 So I added some debug trace in function 'my_secondary_input_reload_class' to understand why (const_int 8) is not reloaded to C_REGS. 'my_secondary_input_reload_class' is called several times but never with rtl expression (const_int 8). I also checked 'my_preferred_reload_class' function and I don't see expression (const_int 8). Selim
Instruction scheduler question
Hello, I'm trying to express the instruction latency time constraints of a private processor. * Overview : Two cycles are necessary between a comparison instruction and a conditionnal jump instruction (GSR is updated 2 cycles after comparison). If nothing better than 'nop' can be used between compare and jump the asm shall be : cmp $A $B nop nop jmpifeq $C I copied mips method to insert 'nop' (using TARGET_MACHINE_DEPENDENT_REORG macro). * Automaton definition : (define_cpu_unit "ctrl") (define_cpu_unit "readmem") (define_cpu_unit "gsr") ;; To express that the compare result (gsr) will only be available in 3 cycles (define_insn_reservation "COMPARE" 3 (eq_attr "type" "compare") "gsr+ctrl,gsr*2") ;; To express that jump uses the gsr result (define_insn_reservation "JUMP" 1 (eq_attr "type" "jump") "ctrl+gsr") My compare insn has attribute type = 'compare' and my jump insn has attribute type = 'jump' * Problem : I never see instruction other than 'nop' between the compare and jump instructions. For example, I see : (asm result) load d($C2),$R1 <--1st operand for comparison ctrl,readmem,nothing loadi 0,$C4 <- 2nd operand for comparison ctrl,nothing load d($C2+4),$R2 <--no data dependancies ctrl,readmem,nothing cmp $C4,$R1 (gsr+ctrl),gsr*2 nop nop jmpifeq .L5 (ctrl+gsr) (.sched2) ;; --- Region Dependences --- b 2 bb 0 ;; insn code bb dep prio cost reservation ;; -- --- --- ;; 18 0 2 14 7 3 ctrl,readmem,nothing : 23 22 19 ;; 19 0 2 15 3 3 ctrl,readmem,nothing : 23 ;; 81 0 2 1 6 2 ctrl,nothing : 23 22 ;; 22 10 2 3 4 3 (gsr+ctrl),gsr*2 : 23 ;; 23 9 2 20 1 1 (ctrl+gsr) : ;; dependencies resolved: insn 81 ;; Ready-->Q: insn 81: queued for 1 cycles. ;; tick updated: insn 81 into queue with cost=1 ;; dependencies resolved: insn 18 ;; tick updated: insn 18 into ready ;; Ready list (t = 18): 18:17 ;; Q-->Ready: insn 81: moving to ready without stalls ;; Ready list after queue_to_ready: 81:19 18:17 ;; Ready list after ready_sort: 81:19 18:17 ;; Ready list (t = 19): 81:19 18:17 ;; 19--> 18 $R1=[$C2] :ctrl,datar,nothing ;; dependencies resolved: insn 19 ;; tick updated: insn 19 into ready ;; Ready list (t = 19): 19:18 81:19 ;; Ready list after queue_to_ready: 19:18 81:19 ;; Ready list after ready_sort: 19:18 81:19 ;; Ready list (t = 20): 19:18 81:19 ;; 20--> 81 $C4=0x0 :ctrl,nothing ;; dependencies resolved: insn 22 ;; Ready-->Q: insn 22: queued for 2 cycles. ;; tick updated: insn 22 into queue with cost=2 ;; Ready list (t = 20): 19:18 ;; Ready list after queue_to_ready: 19:18 ;; Ready list after ready_sort: 19:18 ;; Ready list (t = 21): 19:18 ;; 21--> 19 $R2=[$C2+0x4] :ctrl,datar,nothing ;; Ready list (t = 21): ;; Q-->Ready: insn 22: moving to ready without stalls ;; Ready list after queue_to_ready: 22:20 ;; Ready list after ready_sort: 22:20 ;; Ready list (t = 22): 22:20 ;; 22--> 22 {$GSR=cmp($R1,$C4);clobber $R3;} :(gsr+ctrl),gsr*2 ;; dependencies resolved: insn 23 ;; Ready-->Q: insn 23: queued for 3 cycles. ;; tick updated: insn 23 into queue with cost=3 ;; Ready list (t = 22): ;; Q-->Ready: insn 23: moving to ready with 2 stalls ;; Ready list after queue_to_ready: 23:21 ;; Ready list after ready_sort: 23:21 ;; Ready list (t = 25): 23:21 ;; 25--> 23 pc={($GSR==0x0)?L110:pc} :(ctrl+gsr) ;; Ready list (t = 25): ;; Ready list (final): The 'load d($C2+4),$R2' instruction seems a good canditate to be moved between compare and jump instruction because there are no data dependencies with compare/jump instructions and no reservation collision. Can someone explain me how to obtain the following assembler ? : load d($C2),$R1 loadi 0,$C4 cmp $C4,$R1 load d($C2+4),$R2 nop jmpifeq .L5 Regards, Selim Belbachir
arithmetic standard pattern using only memory_operand
Hi, My target has arithmetic instruction whose operands can ONLY be memory (offseted, post/pre inc, ...). For example 'add' can only have a memory operand as its first operand : add mem($C1), $C2, $C3 I tried to simply write the addsi3 pattern with using memory_operand as predicate for operand 2 but gcc often (always?) tries to use a register instead of memory and finally send the error message : unrecognizable insn : set (reg:SI 0) (plus:SI (reg SI 1) (reg SI 2)) Is it possible to define arithmetic standard parttern with operands matched by memory_operand only ? How ? Maybe I forgot a important MACRO in may .h ? Regards, Selim
gnat cross compilation
Hi, Is it possible to compile a gnat cross compiler based on gcc 4.5.2 using my pre-installed gnat native compiler based on gcc 3.4.6 ? Or should I try to build my own local native compiler based on gcc 4.5.2 ? I ask the question because for the moment, I'm stuck with the following error during the make : a-except.adb:45:01: warning: unrecognized pragma "Compiler_Unit" And I think that "Compiler_Unit" may no exist in gcc 3.4.6... Regards, Selim
Building cross gnat + minimal RTS
Hi, I'm trying to build a gnat cross compiler based on gcc 4.5.2 for my private target (named prism). To do this, I'm using a native gnat-6.4.2 (containing gcc 4.5.2). I want the minimal amount of lib and runtime so I presume that I nearly only need to provide 'system.ads'. (I will add secondary stack management later). I don't find the standard procedure to build my cross gnat + minimal RTS. First I configure this way : configure --prefix=$(INSTALLDIR) --target=prism --disable-nls --enable-languages=c,ada --with-gmp=$(INSTALLDIR) --with-mpfr=$(INSTALLDIR) --with-mpc=$(INSTALLDIR) LDFLAGS="-static" --without-libiconv-prefix --disable-libmudflap --disable-libffi --disable-libstdcxx-pch --disable-libada --disable-libgcc --disable-libssp --enable-checking=release Then I simply do : make make install but it ends like this : You must first build the GNAT library: make gnatlib make[5]: *** [../stamp-gnatlib-rts] Error 1 make[4]: *** [install-gnatlib] Error 2 (I though that --disable-libada option would disable the need for libs...) At this point my new cross compiler provide the following error when I try to compile a simple adb : fatal error, run-time library not installed correctly cannot locate file system.ads compilation abandoned If I copy manually my system.ads into the right install dir (taking example on another working cross compiler), my cross compile seems to work. I browsed the source directory gcc/ada, and I tried to insert the following lines in gcc/ada/gcc-interface/Makefile.in hoping it will copy my system-prism.ads automatically during build process : ifeq ($(strip $(filter-out %prism,$(arch))),) LIBGNAT_TARGET_PAIRS = \ system.ads
maddsidi4 detection
Hi, I'm trying to define the standard pattern maddsidi4. To do this I wrote this in my backend (gcc4.5.2) : (define_insn "maddsidi4" [(set (match_operand:DI 0 "register_operand" "=a") (plus:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "general_operand" "%g")) (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))) (match_operand:DI 3 "register_operand" " 0")))] "" "mulacc %2,%1,%0"; ) ('a' constraints is for accumulator registers) (the movdi standard pattern defines the moves from and to accumulator registers) When I compile the following code, mulacc is properly emitted : void test_maddsidi4(int a, int b, long long * c) { *c += (long long)a*(long long)b; } But when I write the following code, (mulsidi3 + adddi3) is chosen instead of maddsi4: void maddsidi4_alt(int a, int b, long long * c) { *c = (long long)a*(long long)b + (*c); } I tried in debug mode to figure out why maddsi4 is ignore in the last case. I found in expr.c file, in 'expand_expr_real_2' function and in 'PLUS_EXPR' switch case that instead of encountering a MULT_EXPR following the PLUS_EXPR, an INDIRECT_REF is encountered. This seems quite logical given the '+(*c)' in my test. I'm quite surprised that the multiplication/addition detection is so restrictive. Is there a way to enhance the mul/add detection without patching expr.c ? Someone else has certainly met the same problem :) Feel free to send me the trick or patch :) Regards, Selim
dse2 remove wrong insn
Hi, I'm still working on a new gcc-4.5.2 backend for a private processor. I encountered a strange behavior and I'm unable to find what causes this behavior. As an overview, it seems that dse2 pass removes insn where it should not (optim -O2, -O3) Here is the code giving me headachs which returns 0 when it should return 0x3F80 (hex representation of 1.0f) : void f1(int *ret2) { *ret2 = 2; } float f2(float par1) { return par1; } void (*ff)() = f1; int main() { int x; float af; ff(&x); af = f2(1.0f); return *((int *)(&af)); } When I try to simplify this sample code further, the problem disappear even if apparenlty there is no relation between the f2 call and the ff call... I watched the rtl dump and here is an extract of the interesting part dealing with the *((int *)(&af)) with f2 previously inlined (-O2 -O3) : * in expand dump : LC0->$72 The 1.0f constant (LC0) is in data section. Its a normal behavior because I have to insn to load a constant in $FP regs. Hence I have to load the address of LC0 first. (insn 9 8 10 3 (set:SI (reg:SI 72) (symbol_ref/u:SI ("*.LC0") [flags 0x2])) -1 (nil)) M($72)->$73 Memory pointing LC0 is loaded into reg 73 (insn 10 9 11 3 (set:SF (reg:SF 73) (mem:SF (reg:SI 72) [0 S4 A32])) -1 (nil)) $73->M($62+4) reg 73 moved into mem(stack+4). (There are no memory to memory moves so using the temp reg 73 to move M($72) to M($62+4) is normal) (insn 11 10 12 3 (set:SF (mem/c/i:SF (plus:SI (reg/f:SI 62 virtual-stack-vars) (const_int 4 [0x4])) [3 af+0 S4 A32]) (reg:SF 73)) -1 (nil)) $62+4->$75 mem(stack+4) moved to reg 75 (insn 12 11 13 3 (set (reg:SI 75) (plus:SI (reg/f:SI 62 virtual-stack-vars) (const_int 4 [0x4] M($75)->76 reg 75 to reg 76 (insn 13 12 14 3 (set (reg:SI 76) (mem:SI (reg:SI 75) [4 S4 A32])) -1 (nil)) $76->$69 reg 76 to reg 69 which is the fixed return register (I don't know why insn 12 don't move directly to reg 69... nevertheless it's correct) (insn 14 13 15 3 (set (reg:SI 69 [ ]) (reg:SI 76)) -1 (nil)) * in pro_and_epilogue dump (just before dse2) : $C0+8->$C3 (insn 24 12 27 2 (set (reg/f:SI 3 $C3 [77]) (plus:SI (reg/f:SI 0 $C0) (const_int 8 [0x8] [...] LC0->$C2 (insn 9 8 29 2 (set:SI (reg/f:SI 2 $C2 [72]) (symbol_ref/u:SI ("*.LC0") [flags 0x2])) 1 {movsi_internal} (expr_list:REG_EQUIV (symbol_ref/u:SI ("*.LC0") [flags 0x2]) (nil))) M($C2)->$FP1 (insn 29 9 11 2 (set (reg:SF 41 $FP1) (mem:SF (reg/f:SI 2 $C2 [72]) [0 S4 A32])) 10 {movsf_internal} (nil)) $FP1->M($C0+12) (insn 11 29 13 2 (set:SF (mem/c/i:SF (plus:SI (reg/f:SI 0 $C0) (const_int 12 [0xc])) [3 af+0 S4 A32]) (reg:SF 41 $FP1)) 10 {movsf_internal} (nil)) M($C3+4)->$R0 (insn 13 11 21 2 (set (reg/i:SI 16 $R0) (mem:SI (plus:SI (reg/f:SI 3 $C3 [77]) (const_int 4 [0x4])) [4 S4 A32])) 1 {movsi_internal} (nil)) Every thing seems normal except the fact that $FP1 is moved in M($C0+12) and then the stored value is read with M($C3+4) where $C3=$C0+8. This is due to optimisation (factorization) done during previous passes with the code before inline f2 call. * in pro_ dse2_epilogue dump (we die here) : $C0+8->$C3 (insn 24 12 27 2 (set (reg/f:SI 3 $C3 [77]) (plus:SI (reg/f:SI 0 $C0) (const_int 8 [0x8] M($C3+4)->$R0 (insn 13 8 21 2 (set (reg/i:SI 16 $R0) (mem:SI (plus:SI (reg/f:SI 3 $C3 [77]) (const_int 4 [0x4])) [4 S4 A32])) 1 {movsi_internal} (expr_list:REG_DEAD (reg/f:SI 3 $C3 [77]) (nil))) insn 9, 29 and 11 have been deleted ! :) Here is what the dump says concerning insn 9, 29, 11 and 13 **scanning insn=9 mems_found = 0, cannot_delete = true **scanning insn=29 mem: (reg/f:SI 2 $C2 [72]) after canon_rtx address: (reg/f:SI 2 $C2 [72]) after cselib_expand address: (symbol_ref/u:SI ("*.LC0") [flags 0x2]) after canon_rtx address: (symbol_ref/u:SI ("*.LC0") [flags 0x2]) gid=1 offset=0 processing const load gid=1[0..4) mems_found = 0, cannot_delete = true **scanning insn=11 mem: (plus:SI (reg/f:SI 0 $C0) (const_int 12 [0xc])) after canon_rtx address: (plus:SI (reg/f:SI 0 $C0) (const_int 12 [0xc])) gid=2 offset=12 processing const base store gid=2[12..16) mems_found = 1, cannot_delete = false **scanning insn=13 mem: (plus:SI (reg/f:SI 3 $C3 [77]) (const_int 4 [0x4])) after canon_rtx address: (plus:SI (reg/f:SI 3 $C3 [77]) (const_int 4 [0x4])) after cselib_expand address: (plus:SI (reg/f:SI 3 $C3 [77]) (const_int 4 [0
RE: dse2 remove wrong insn
Everything seems good when I use a union instead of "*((int *)(&af))". But I think that "*((int *)(&af))" is a valid syntax to get the integer representation of my floating point value (in my test case 0x3F80 for 1.0f in IEEE-754). It may be target dependant but I think it should work on target having 32 bits float and integer (and IEEE754 compliance). I have gone on my debugging and I found what was wrong in my backend. I had STACK_POINTER_REGNUM=$C0, ARG_POINTER_REGNUM=$C1, FRAME_POINTER_REGNUM=$C0, no reg elimination macro, and prolog/epilog in adequacy. When I replaced my FRAME_POINTER_REGNUM by its own $C2 reg (i.e. a different value than STACK_POINTER_REGNUM) and added reg elimination macros the problem in dse2 pass disappeared (without adding unnecessary frame pointer in the asm output). I have done this because looking as dse2.c I saw that some optimization was dealing with frame pointer and I was unsure of the correctness of the macro defining my ABI. Are there requirement in dse2 pass according to FRAME_POINTER_REGNUM and STACK_POINTER_REGNUM definition ? Does my initial definition of FRAME_POINTER_REGNUM was totally dumb ? I don't know ... Selim -Message d'origine- De : gcc-ow...@gcc.gnu.org [mailto:gcc-ow...@gcc.gnu.org] De la part de Andrew Haley Envoyé : vendredi 9 décembre 2011 18:37 À : gcc@gcc.gnu.org Objet : Re: dse2 remove wrong insn On 12/09/2011 03:05 PM, BELBACHIR Selim wrote: > int main() { > int x; > float af; > ff(&x); > af = f2(1.0f); > return *((int *)(&af)); > } Please try this again, but with a union rather than a pointer cast. I don't think this code is legal C. Andrew.
add and compare combination
Hi, I'd like to know if there a way to express 'add' and 'compare' insn so that the combiner transform it in and 'add_and_compare' insn. I watch arm backend and it seems possible when I look at 'addsi3', 'cbranchsi4' and '*addsi3_compare0'. In my backend I have written the following insn/expand : (define_expand "addsi3" [(set (match_operand:SI 0 "register_operand" "") (plus:SI (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "off1post_general_op" "")))] "" "" ) (define_insn "add_and_compare" [(set (reg:CC CCI_REG) (compare:CC (plus:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "register_operand" "r")) (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_dup 1) (match_dup 2)))] "" "add %1,%2,%0" ) (define_insn "add" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "register_operand" "r")))] "" "addk %1,%2,%0" ) (define_expand "cbranchsi4" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" "")]) (label_ref (match_operand 3 "" "")) (pc)))] { emit_insn(gen_comparesi (operands[1], operands[2])); operands[1] = gen_rtx_REG (CCmode, CCI_REG); operands[2] = const0_rtx; } ) (define_insn "comparesi" [(set (reg:CC CCI_REG) (compare:CC (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "register_operand" "r")))] "" "cmp %1,%0" ) (define_insn "jmpifsi" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(reg:CC CCI_REG) (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc)))] "" "jmp.if %c0 %1" ) When I compile : c = a + b; if (c) {...} No combination occurs between "add" and "comparesi" insn. I was expecting to see my "add_and_compare" pattern. The resulting assembler is addk cmp jmp.if instead of add jmp.if Do someone see why combination fails ? (gcc 4.5.2) Thanks, Selim
RE: add and compare combination
Well, I run combine pass in debug mode and found my mistakes. I'd like to share what I have found :) There were 2 mistake. First my HARD_REGNO_MODE_OK returned 0 for regno=CCI_REG and mode=CCmode which lead to an early failure in combine.c. So I added this to my macro : if (GET_MODE_CLASS (mode) == MODE_CC) return (regno == CCI_REG) Secondly, I figured out that combination was different for the 2 following code : c = a + b; if (c) {...} /* use c further in code */ and if (a + b) {...} /* the addition result is a DEAD_REG */ In the first case the combiner create and try to match a parallel rtx similar to my "add_and_compare". This case was in fact working. In the second case the combiner see the DEAD_REG and try to match a single set rtx of this form : (define_insn "comparesi_plus" [(set (reg:CC CCI_REG) (compare:CC (match_operand:SI 0 "register_operand" "r") (neg:SI (match_operand:SI 1 "register_operand" "r"] ;; the 'trick' is in the neg !! "" "cmp_plus %1,%0" ) As I had no such insn the combination was failing, when I added one (with a clobbered result because I have no cmp_plus instruction), everything run ok. I watched in arm backend and I found a similar insn... So the solution was in front of me but I did not see it :) Selim -Message d'origine- De : gcc-ow...@gcc.gnu.org [mailto:gcc-ow...@gcc.gnu.org] De la part de BELBACHIR Selim Envoyé : jeudi 15 décembre 2011 16:12 À : gcc@gcc.gnu.org Objet : add and compare combination Hi, I'd like to know if there a way to express 'add' and 'compare' insn so that the combiner transform it in and 'add_and_compare' insn. I watch arm backend and it seems possible when I look at 'addsi3', 'cbranchsi4' and '*addsi3_compare0'. In my backend I have written the following insn/expand : (define_expand "addsi3" [(set (match_operand:SI 0 "register_operand" "") (plus:SI (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "off1post_general_op" "")))] "" "" ) (define_insn "add_and_compare" [(set (reg:CC CCI_REG) (compare:CC (plus:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "register_operand" "r")) (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_dup 1) (match_dup 2)))] "" "add %1,%2,%0" ) (define_insn "add" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "register_operand" "r")))] "" "addk %1,%2,%0" ) (define_expand "cbranchsi4" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" "")]) (label_ref (match_operand 3 "" "")) (pc)))] { emit_insn(gen_comparesi (operands[1], operands[2])); operands[1] = gen_rtx_REG (CCmode, CCI_REG); operands[2] = const0_rtx; } ) (define_insn "comparesi" [(set (reg:CC CCI_REG) (compare:CC (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "register_operand" "r")))] "" "cmp %1,%0" ) (define_insn "jmpifsi" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(reg:CC CCI_REG) (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc)))] "" "jmp.if %c0 %1" ) When I compile : c = a + b; if (c) {...} No combination occurs between "add" and "comparesi" insn. I was expecting to see my "add_and_compare" pattern. The resulting assembler is addk cmp jmp.if instead of add jmp.if Do someone see why combination fails ? (gcc 4.5.2) Thanks, Selim
reverse conditionnal jump
Hi, I'm still developping a new private target backend (gcc4.5.2) and I noticed something strange in the assembler generated for conditionnal jump. The compiled C code source is : void funct (int c) { int a; a = 7; if (c < 0) a = 4; return a; } The assembler generated is : [...] mov 7,a cmp 0,c #set the CC status jmpif LT .L2 #conditionnal jump using CC status .L1 ret a #return to callee .L2 mov 4,a jmp .L1 #unconditionnal jump But, I was expecting only one jump as follow : [...] mov 7,a cmp 0,c #set the CC status jmpif GE .L1 #conditionnal jump using CC status mov 4,a .L1 ret a #return to callee All comparison are available and I defined REVERSIBLE_CC_MODE(MODE) to 1. I also have the following branch insn (and the cbranchsi4 expand) (define_insn "*jmpif" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(reg:CC CCI_REG) (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc)))] "" "jmpif %c0 %l1" ) (define_insn "*reverse_jmpif" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(reg:CC CCI_REG) (const_int 0)]) (pc) (label_ref (match_operand 1 "" ""] "" "jmpif %C0 %l1" ) How can I tell GCC to perform the best conditionnal jump by sometimes reversing the comparison ? Regards, Selim
readonly register
Hi, I'm trying to support an 'in' instruction which reads a value on a peripheral and writes it into a $INP register. The $INP register can be used in almost every insn as input operand (add, sub, mul ...). I defined a builting to access the 'in' instruction. How should I express to gcc that the $INP register can only be 'read' and must never be written? For the moment, I encounter a problem during IRA pass where some of my 'classic' registers are reloaded into $INP (apparently because I have no register left). Regards, Selim
RE: readonly register
In fact my final purpose is to replace $INP by a register bank in order to be able to read several inputs using pipelined instructions (and instruction scheduler). The fixed reg solution will prevent me from doing this. Is there another way to prevent the use of some registers during the reload pass without turning them into fixed register ? Selim -Message d'origine- De : Ian Lance Taylor [mailto:i...@google.com] Envoyé : jeudi 19 janvier 2012 00:17 À : BELBACHIR Selim Cc : gcc@gcc.gnu.org Objet : Re: readonly register BELBACHIR Selim writes: > I'm trying to support an 'in' instruction which reads a value on a peripheral > and writes it into a $INP register. > The $INP register can be used in almost every insn as input operand (add, > sub, mul ...). > I defined a builting to access the 'in' instruction. > > How should I express to gcc that the $INP register can only be 'read' and > must never be written? > > For the moment, I encounter a problem during IRA pass where some of my > 'classic' registers are reloaded into $INP (apparently because I have no > register left). If you have a builtin to access the value, then you should be able to make it a fixed register. The register allocator will never try to allocate a fixed register. Ian
DWARF2 offset for local variables
Hi, I'm (still) working on a new gcc-4.5.2 backend for a private processor. Today i'm concerned about the debug mode using DWARF2. Here is my problem: When I use GDB on a executable compiled with -g option I notice that the addresses of all my local variables are wrong. I read gccint doc and tried to use DEBUGGER_AUTO_OFFSET(X) and DEBUGGER_ARG_OFFSET(OFFSET, X) but I noticed (thanks to printf) that they were never called for DWARF2. (I saw afterward that dwarf2out.c did not use these macros) My stack frame is organized as follow : Hi mem Address | | +---+ <= $SP before prologue | | | Reg save | | | +---+ | | | Locals / Temps | | | +---+ | | |Args Block | | | +---+ <= $SP after prologue Lo mem Address | | With #define STACK_GROWS_DOWNWARD 1 #define FRAME_POINTER_CFA_OFFSET(FNDECL) 0 #define STARTING_FRAME_OFFSET crtl->outgoing_args_size #define FIRST_PARM_OFFSET(FUNDECL) 0 #define DWARF2_DEBUGGING_INFO #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG #define ELIMINABLE_REGS \ {{HARD_FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ {ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ {ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ } #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ (OFFSET) = my_initial_elimination_offset ((FROM), (TO)) HOST_WIDE_INT my_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED) { HOST_WIDE_INT offset; switch (from) { case HARD_FRAME_POINTER_REGNUM: offset = 0; break; case FRAME_POINTER_REGNUM: offset = 0; break; case ARG_POINTER_REGNUM: offset = my_stack_frame_size(); break; default: gcc_unreachable (); } return offset; } How can I express an offset for local variables in DWARF2 for GDB ? Regards, Selim Belbachir
delay slot of conditionnal branch with no annuled jump strategy
Hi, I'm porting gcc 4.5.2 on a private processor. I encountered a problem concerning delay slots of conditionnal branch instructions (Note : the processor has no 'annuled jump strategy') Here is my delay slot definition : (define_delay (eq_attr "type" "jump") [(and (eq_attr "delayable" "yes") (eq_attr "length" "1")) (nil) (nil)]) Here is a sample of erroneous code : sub 0,$R5,$R1 #compare $R5 to 0 ($R1 is clobbered) jmpd.ifCC .L0#conditionnal delayed branch followed by 1 delay slot sub $R0,$R4,$R0 #compare $R4 to $R0 ($R0 is clobbered) problem ... addk 1,$R0,$R0#increment $R0, but $R0 was modified by 'sub $R0,$R4,$R0' !!! ... .L0: bra.ifLS __chk_fail#conditionnal call symbol_ref GCC put my compare insn 'sub $R0,$R4,$R0' into the delay slot knowing that $R0 was clobbered by the compare insn (see the definition below). It's ok if 'jmpd.ifCC .L7' jumps otherwize it's ko because $R0 is used in the fall-through path by 'addk 1,$R0,$R0'. Here is my compare insn : (define_insn "compare" [(set (reg:CC CCI_REG) (compare:CC (match_operand:SI 1 "general_operand""g ") (match_operand:SI 2 "general_operand""g"))) (clobber (match_operand:SI 0 "register_operand" "=r "))] "sub %2,%1,%0" [(set_attr "length" "1") (set_attr " delayable " "yes")] ) I was expecting 'instruction reorganization pass' to produce the following code : sub 0,$R5,$R1 #compare $R5 to 0 ($R1 is clobbered) jmp.ifCC .L0 #conditionnal delayed branch (with 0 delay slot) ... addk 1,$R0,$R0#increment $R0 ... .L0: sub $R0,$R4,$R0 #compare $R4 to $R0 ($R0 is clobbered) bra.ifLS __chk_fail#conditionnal call symbol_ref Why GCC doesn't see, in this case, that it's not safe to fill the delay slot with my compare insn (which is a parallel RTX which clobber one register used in fallthrough branch) ? Is a processor 'annuled jump strategy' mandatory to handle delay slot of conditionnal jump instructions ? Regards, Selim Belbachir
RE: delay slot of conditionnal branch with no annuled jump strategy
> Does this happen systematically with the compare insn or is it isolated? I encountered this problem only once in gcc testsuite (gcc.c-torture/execute/builtins/strncat-chk.c). I think the problem is quite rare because gcc does not put often a parallel compare insn into the delay slot of a conditional jump, and when it happens it's not certain that the register clobbered by the parallel compare is used in the fall-through path after the conditional jump. So I would say the problem is isolated. > This looks like a bug in the dbr pass (several of them have been fixed since > 4.5.2) but it's impossible to be more precise without further details. The > support of annulled instructions is not required for proper operation. My current investigation showed that when I comment the call to 'fill_eager_delay_slots' in ' reorg.c:dbr_schedule' the problem disappear. The problem does not come from the 2 others techniques for filling delay slots : 'fill_simple_delay_slots' or 'relax_delay_slots'. To illustrate the problem previously described in asm, I copied and commented the rtl dumps below : -- * Dumps before dbr scheduling (dump xx.214r.barriers) -- ### compare $R5 to 0 ($R1 is clobbered) (insn 38 97 39 test.c:14:21 (parallel [ (set:CC (reg:CC 56 $CCI) (compare:CC (reg:SI 18 $R5 [108]) (const_int 0 [0x0]))) (clobber (reg:SI 18 $R1 [109])) ]) 45 {compare} (expr_list:REG_DEAD (reg:SI 18 $R5 [108]) (nil))) ### conditionnal branch to label 51 (jump_insn 39 38 71 test.c:14:21 (set (pc) (if_then_else (eq (reg:CC 56 $CCI) (const_int 0 [0x0])) (label_ref 51) (pc))) 131 {jmpif} (expr_list:REG_DEAD (reg:CC 56 $CCI) (expr_list:REG_BR_PROB (const_int 900 [0x384]) (nil))) -> 51) (code_label 71 39 70 6 "" [1 uses]) (note 70 71 41 [bb 3] NOTE_INSN_BASIC_BLOCK) ### increment $R0 in fall-through path (insn 41 70 43 test.c:16:7 (set (reg/v:SI 16 $R0 [orig:85 len ] [85]) (plus:SI (reg/v:SI 16 $R0 [orig:85 len ] [85]) (const_int 1 [0x1]))) 40 {addsi3_nocompare} (nil)) ### I have hidden some insn not very usefull [...] ### target of the conditionnal jump (code_label 51 50 52 3 "" [1 uses]) (note 52 51 53 [bb 4] NOTE_INSN_BASIC_BLOCK) ### compare $R4 to $R0 ($R0 is clobbered) (insn 53 52 56 test.c:19:11 (parallel [ (set:CC (reg:CC 56 $CCI) (compare:CC (reg/v:SI 20 $R4 [orig:93 size ] [93]) (reg/v:SI 16 $R0 [orig:85 len ] [85]))) (clobber (reg:SI 16 $R0 [117])) ]) 45 {compare} (expr_list:REG_DEAD (reg/v:SI 20 $R4 [orig:93 size ] [93]) (expr_list:REG_DEAD (reg/v:SI 16 $R0 [orig:85 len ] [85]) (nil (note 56 53 57 NOTE_INSN_DELETED) ### conditionnal call symbol_ref (call_insn 57 56 60 test.c:20:16 (cond_exec (leu (reg:CC 56 $CCI) (const_int 0 [0x0])) (parallel [ (set (reg:SI 16 $R0) (call (mem:SI (symbol_ref:SI ("__chk_fail") [flags 0x41] ) [0 S4 A32]) (const_int 0 [0x0]))) (clobber (reg:SI 1 $C1)) ])) 161 {call_value_cond} (expr_list:REG_DEAD (reg:SI 1 $C1) -- * Dumps after dbr scheduling (dump xx.c.215r.db) -- ### compare $R5 to 0 ($R1 is clobbered) (insn 38 97 121 test.c:14:21 (parallel [ (set:CC (reg:CC 56 $CCI) (compare:CC (reg:SI 18 $R5 [108]) (const_int 0 [0x0]))) (clobber (reg:SI 18 $R1 [109])) ]) 45 {compare} (expr_list:REG_DEAD (reg:SI 18 $R5 [108]) (nil))) ### conditionnal branch to label 51 with delay slot filled by parallel [compare $R4 to $R0, clobber $R0]. ### the parallel compare was taken from the conditional jump 'target' path and should not have any side effect ### on the 'fall-through' path. But unfortunately the clobber $R0 has side effect ... (insn 121 38 70 test.c:14:21 (sequence [ (jump_insn 39 38 119 test.c:14:21 (set (pc) (if_then_else (eq (reg:CC 56 $CCI) (const_int 0 [0x0])) (label_ref:SI 120) (pc))) 131 {jmpif} (expr_list:REG_BR_PRED (const_int 48 [0x30]) (expr_list:REG_DEAD (reg:CC 56 $CCI) (expr_list:REG_BR_PROB (const_int 900 [0x384]) (nil -> 120) (insn/s 119 39 70 (parallel [ (set:CC (reg:CC 56 $CCI) (compare:CC (reg/v:SI 20 $R4 [orig:93 size ] [93]) (reg/v:SI 16 $R0
RE: delay slot of conditionnal branch with no annuled jump strategy
> I have a gcc 4.6.1 port that has the same sort of problems. I tried > selectively porting some patches from later 4.6 releases, but they didn't > seem to actually address the issue. I haven't looked at the trunk to see if > there are patches that are more apropos. I looked at the revisions of reorg.c in gitHub since gcc 4.5.2 but I did not see any obvious correction concerning this issue.
RE: delay slot of conditionnal branch with no annuled jump strategy
Thanks for the hints ! I found a recent correction on resource.c ' https://github.com/mirrors/gcc/commit/d8e17376c1b6ba379cc918f06843792e35c4e38e' which treat my problem. It seems my problem was not related to my parallel compare insn but produced by the conditional call at the beginning of the target path. Let's hope this correction does not hide another problem by just applying a side effect on my specific test case :) Regards, Selim -Message d'origine- De : Jeff Law [mailto:l...@redhat.com] Envoyé : vendredi 11 octobre 2013 22:34 À : BELBACHIR Selim; Eric Botcazou Cc : gcc@gcc.gnu.org Objet : Re: delay slot of conditionnal branch with no annuled jump strategy On 10/11/13 05:51, BELBACHIR Selim wrote: > >> Does this happen systematically with the compare insn or is it isolated? > > I encountered this problem only once in gcc testsuite > (gcc.c-torture/execute/builtins/strncat-chk.c). > I think the problem is quite rare because gcc does not put often a > parallel compare insn into the delay slot of a conditional jump, and when it > happens it's not certain that the register clobbered by the parallel compare > is used in the fall-through path after the conditional jump. > So I would say the problem is isolated. > >> This looks like a bug in the dbr pass (several of them have been >> fixed since >> 4.5.2) but it's impossible to be more precise without further details. The >> support of annulled instructions is not required for proper operation. > > My current investigation showed that when I comment the call to > 'fill_eager_delay_slots' in ' reorg.c:dbr_schedule' the problem disappear. > The problem does not come from the 2 others techniques for filling delay > slots : 'fill_simple_delay_slots' or 'relax_delay_slots'. > > To illustrate the problem previously described in asm, I copied and commented > the rtl dumps below : I'd look at the code in resource.c very carefully, it's possible it's not properly handling all the side effects of the parallel. jeff
how to use -fomit-frame-pointer by default
Hi, I'm migrating my private port from gcc 4.5.2 to gcc 4.7.3. I noticed that -fomit-frame-pointer was not triggered when using -O1 -O2 or -O3. Could you indicate me how to modify my port to use -fomit-frame-pointer by default (as it was in gcc 4.5.2 I presume) ? Regards, Selim
cross compile & exceptions
Hi, I'm trying to migrate from gcc4.5.2 to gcc4.7.3. Here are a part of my makefile to build gcc (same config used with gcc4.5.2 and gcc4.7.3) : cd $(GCC_OBJDIR); CFLAGS="-g -O0" $(GCC_SRCDIR)/configure -quiet --prefix=$(INSTALLDIR) --target=$(TARGET) --enable-languages=c,c++,ada --disable-nls --disable-decimal-float --disable-fixed-point --disable-libmudflap --disable-libffi --disable-libssp --disable-shared --disable-threads --without-headers --disable-libada --enable-version-specific-runtime-lib --enable-checking=release make -C $(GCC_OBJDIR) all-gcc make -C $(GCC_OBJDIR) install-gcc The c++ (and not c) compiler produced segmentation fault on very small source only when I use default option -O0 cmd : pgcc test.cpp -S src : extern void bar(int *); void toto () { int tmp; bar (&tmp); } Looking at the dumps I noticed in test.cpp.152r.rtl_eh that a bad RTL SET is generated inside a bunch of rtl dealing with exception. (insn 19 20 12 5 (set (reg:SI 131) (reg:SI -1)) -1<<<--- REG -1 is invalid (nil)) (insn 12 19 13 5 (set (reg/f:SI 130 [ D.1841 ]) (reg:SI 131)) -1 (nil)) (insn 13 12 14 5 (set (reg:SI 4 $C4) (reg/f:SI 130 [ D.1841 ])) -1 (nil)) (call_insn 14 13 15 5 (parallel [ (call (mem:SI (symbol_ref:SI ("_Unwind_Resume") [flags 0x41] ) [0 __builtin_unwind_resume S4 A32]) (const_int 0 [0])) (clobber (reg:SI 1 $C1)) ]) -1 I don't want need/want exceptions on my port and it seems that -00 always produce some extra code to handle exception in c++. That was not the normal behaviour of gcc4.5.2. I don't see any good configure option but I tried --enable-sjlj-exceptions to see the result. The segmentation fault disappears but extra code to call _Unwind_SjLj_Register is produced (with a save of all registers in function prologue ...), that's not what I wanted. Configure using --disable-sjlj-exceptions produce the same segmentation described above. I also tried to compile my test with -fno-exceptions. It produces the result I expected with no error and no extra code equivalent to the gcc4.5.2 without options. Something new in gcc4.7.3 has to be configured to disable exceptions by default ? I noticed a change of behaviour on -fomit-frame-pointer between 4.5.2 & 4.7.3 (described in my previous post). gcc4.5.2 behaviour was exactly what I wanted (fomit-frame-pointer & fno-exceptions by default) how to obtain that with 4.7.3 ? Regards, Selim
RE: how to use -fomit-frame-pointer by default
Thx that's what I was looking for :) I forgot the new gcc/common/config part ... -Message d'origine- De : Joseph Myers [mailto:jos...@codesourcery.com] Envoyé : mercredi 20 novembre 2013 17:41 À : BELBACHIR Selim Cc : gcc@gcc.gnu.org Objet : Re: how to use -fomit-frame-pointer by default On Tue, 19 Nov 2013, BELBACHIR Selim wrote: > I'm migrating my private port from gcc 4.5.2 to gcc 4.7.3. I noticed > that -fomit-frame-pointer was not triggered when using -O1 -O2 or -O3. > Could you indicate me how to modify my port to use > -fomit-frame-pointer by default (as it was in gcc 4.5.2 I presume) ? This is now handled through the TARGET_OPTION_OPTIMIZATION_TABLE hook (in gcc/common/config). -- Joseph S. Myers jos...@codesourcery.com
RE: cross compile & exceptions
I did this in order to build gcc, libgcc and libstdc++ independently. when I do the simple integrated build process (following http://gcc.gnu.org/install) : cd $(GCC_OBJDIR); CFLAGS="-g -O0" $(GCC_SRCDIR)/configure -quiet --prefix=$(INSTALLDIR) --target=$(TARGET) --enable-languages=c,c++,ada --disable-nls --disable-decimal-float --disable-fixed-point --disable-libmudflap --disable-libffi --disable-libssp --disable-shared --disable-threads --without-headers --disable-libada --enable-version-specific-runtime-lib --disable-bootstrap --enable-checking=release make -C $(GCC_OBJDIR) I encounter a problem on libstdc++v3 : Configuring in prism/libstdc++-v3 Configuring in prism/libiberty configure: error: Link tests are not allowed after GCC_NO_EXECUTABLES. make[2]: *** [configure-target-libiberty] Error 1 make[2]: *** Waiting for unfinished jobs configure: error: Link tests are not allowed after GCC_NO_EXECUTABLES. make[2]: *** [configure-target-libstdc++-v3] Error 1 make[1]: *** [all] Error 2 make: *** [gcc_make] Error 2 because stdio.h is not found (my libc is externally built and --without-header prevent gcc from knowing where are these headers) I tried --with-headers with my own libc header files (incomplete home made libc) but this time I found stuck on libgcc2 requiring unistd.h that I don't have (or want) : In file included from /vues_statiques/FPGA/belbachir/prism2/MPUCores/tools/gcc-4.5.2/libgcc/../gcc/libgcc2.c:29:0: /vues_statiques/FPGA/belbachir/prism2/MPUCores/tools/gcc-4.5.2/libgcc/../gcc/tsystem.h:102:20: fatal error: unistd.h: No such file or directory compilation terminated. So, to build libgcc I would need --without-header to compensate for my small libc, and to build libstdc++ I would have to use --with-header in order to provide stdio.h ... Do you know a better way to solve that than building gcc, libgcc & libstdc++ independently ?
post_inc mem in parallel rtx
Hi, I encountered a bug in cselib.c:2360 using gnat7.1.2 (gcc4.7.3) /* The register should have been invalidated. */ gcc_assert (REG_VALUES (dreg)->elt == 0);<<== assert(false) I investigated the dump and found that the crash occurred during 207r.dse2 pass. Here is what I saw in the previous dump (206r.pro_and_epilogue) : (insn 104 47 105 7 (parallel [ (set (reg:CC_NOOV 56 $CCI) (compare:CC_NOOV (minus:SI (reg/f:SI 22 $R6 [orig:133 D.3274 ] [133]) (mem/f:SI (post_inc:SI (reg:SI 2 $R2 [orig:140 ivtmp.363 ] [140])) [0 MEM[base: D.4517_59, offset: 0B]+0 S4 A32])) (const_int 0 [0]))) (set (reg:SI 16 $R0 [153]) (minus:SI (reg/f:SI 22 $R6 [orig:133 D.3274 ] [133]) (mem/f:SI (post_inc:SI (reg:SI 2 $R2 [orig:140 ivtmp.363 ] [140])) [0 MEM[base: D.4517_59, offset: 0B]+0 S4 A32]))) ]) Note the post_inc MEM on $R2 appearing twice This rtl match my pattern (predicate and contraint ok) below : (define_insn "subsi3_compare0" [(set (reg:CC_NOOV CCI_REG) (compare:CC_NOOV (minus:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 " general_operand " " g")) (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r ") (minus:SI (match_dup 1) (match_dup 2)))] But I think It may be an error to authorize post_inc MEM in this parallel rtx in operand 1 & 2. When I put a more restrictive constraint which forbid the use of post_inc, the crash in cselib.c disappear. Question : What does GCC understand when the md describes a pattern allowing the same post_inc MEM in 2 slot of a parallel rtx ? Is it forbidden ? the MEM address is supposed to be incremented twice ? Regards, Selim
RE: cross compile & exceptions
>> >> So, to build libgcc I would need --without-header to compensate for my small >> libc, and to build libstdc++ I would have to use --with-header in order to >> provide stdio.h ... >> >> >> Do you know a better way to solve that than building gcc, libgcc & libstdc++ >> independently ? > What is $(TARGET) ? >Andrew. $(TARGET) is a private embedded platform (cpu/os/lib) Selim
RE: post_inc mem in parallel rtx
Ok so I should avoid the auto_inc alternatives in PARALLEL. It's certainly a quite rare RTL and I doubt the effort worth it. -Message d'origine- De : Jeff Law [mailto:l...@redhat.com] Envoyé : vendredi 22 novembre 2013 17:55 À : BELBACHIR Selim; gcc@gcc.gnu.org Objet : Re: post_inc mem in parallel rtx On 11/22/13 09:43, BELBACHIR Selim wrote: > Hi, > > I encountered a bug in cselib.c:2360 using gnat7.1.2 (gcc4.7.3) > > /* The register should have been invalidated. */ >gcc_assert (REG_VALUES (dreg)->elt == 0);<<== > assert(false) > > > I investigated the dump and found that the crash occurred during 207r.dse2 > pass. > > Here is what I saw in the previous dump (206r.pro_and_epilogue) : > > (insn 104 47 105 7 (parallel [ > (set (reg:CC_NOOV 56 $CCI) > (compare:CC_NOOV (minus:SI (reg/f:SI 22 $R6 [orig:133 D.3274 > ] [133]) > (mem/f:SI (post_inc:SI (reg:SI 2 $R2 [orig:140 > ivtmp.363 ] [140])) [0 MEM[base: D.4517_59, offset: 0B]+0 S4 A32])) > (const_int 0 [0]))) > (set (reg:SI 16 $R0 [153]) > (minus:SI (reg/f:SI 22 $R6 [orig:133 D.3274 ] [133]) > (mem/f:SI (post_inc:SI (reg:SI 2 $R2 [orig:140 ivtmp.363 > ] [140])) [0 MEM[base: D.4517_59, offset: 0B]+0 S4 A32]))) > ]) > > Note the post_inc MEM on $R2 appearing twice > > This rtl match my pattern (predicate and contraint ok) below : > > (define_insn "subsi3_compare0" >[(set (reg:CC_NOOV CCI_REG) > (compare:CC_NOOV >(minus:SI > (match_operand:SI 1 "general_operand" "g") > (match_operand:SI 2 " general_operand " " g")) >(const_int 0))) > (set (match_operand:SI 0 "register_operand" "=r ") > (minus:SI >(match_dup 1) >(match_dup 2)))] > > But I think It may be an error to authorize post_inc MEM in this parallel rtx > in operand 1 & 2. > When I put a more restrictive constraint which forbid the use of post_inc, > the crash in cselib.c disappear. > > Question : What does GCC understand when the md describes a pattern allowing > the same post_inc MEM in 2 slot of a parallel rtx ? > Is it forbidden ? the MEM address is supposed to be incremented twice ? I think the semantics are defined by the PARALLEL. Namely that the uses are evaluated, then side effects are performed. So both sets use the value before incrementing. The only question is what is the resulting value, and given the fundamental nature of PARALLEL, I think a single visible side effect is the most obvious answer. Now having said that, there's a distinct possibility various passes don't handle this properly. jeff
dwarf2out & var-tracking & cond_exec call
Hi, I'm still porting my private backing from gcc 4.5.2 to gcc 4.7.3. When compiling the following code with -g option, I encountered "internal compiler error: in dwarf2out_var_location, at dwarf2out.c:20883" void toto(int* , float); void foo(int a, float b, int * c) { if (b) toto(c, b); } I don't know well what should contain NOTES but when I look at the gcc_assert at dwarf2out.c:20883 : gcc_assert (prev && (CALL_P (prev) || (NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE && CALL_P (XVECEXP (PATTERN (prev), 0, 0); I would say that COND_EXEC(CALL(..)) handling is missing. Is It right or something went wrong on previous pass (var-tracking pass for example ...) Here is my conditional call pattern : (define_insn "call_cond" [(cond_exec (match_operator 3 "comparison_operator" [(match_operand 4 "cc_register" "") (const_int 0)]) (parallel[ (call (mem:SI (match_operand:SI 0 "call_address_op" " i,r")) (match_operand:SI 1 "immediate_operand" " X,X")) (clobber (match_operand:SI 2 "register_operand" "=r,r"))]))] Regards, Selim
RE: dwarf2out & var-tracking & cond_exec call
I found my problem totally elsewhere (sorry to bother) I was loosing proper NOTES during a COND_EXEC((..)(CALL(..))) split ... Selim -Message d'origine- De : gcc-ow...@gcc.gnu.org [mailto:gcc-ow...@gcc.gnu.org] De la part de BELBACHIR Selim Envoyé : vendredi 29 novembre 2013 14:29 À : gcc@gcc.gnu.org Objet : dwarf2out & var-tracking & cond_exec call Hi, I'm still porting my private backing from gcc 4.5.2 to gcc 4.7.3. When compiling the following code with -g option, I encountered "internal compiler error: in dwarf2out_var_location, at dwarf2out.c:20883" void toto(int* , float); void foo(int a, float b, int * c) { if (b) toto(c, b); } I don't know well what should contain NOTES but when I look at the gcc_assert at dwarf2out.c:20883 : gcc_assert (prev && (CALL_P (prev) || (NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE && CALL_P (XVECEXP (PATTERN (prev), 0, 0); I would say that COND_EXEC(CALL(..)) handling is missing. Is It right or something went wrong on previous pass (var-tracking pass for example ...) Here is my conditional call pattern : (define_insn "call_cond" [(cond_exec (match_operator 3 "comparison_operator" [(match_operand 4 "cc_register" "") (const_int 0)]) (parallel[ (call (mem:SI (match_operand:SI 0 "call_address_op" " i,r")) (match_operand:SI 1 "immediate_operand" " X,X")) (clobber (match_operand:SI 2 "register_operand" "=r,r"))]))] Regards, Selim
Controling reloads of movsicc pattern
Hi, My target has : - 2 registers class to store SImode (like m68k, data $D & address $A). - moves from wide offset MEM to $D or $A (ex: mov d($A1+50),$A2 ormov d($A1+50),$D1) - conditional moves from offset MEM to $D or $A but with a restriction : offset MEM conditionally moved to $A has a limited offset of 0 or 1 (ex: mov.ifEQ d($A1,1),$A1 whereas we can still do mov.ifEQ d($A1,50),$D1) The predicate of movsicc pattern tells GCC that wide offset MEM is allowed and constraints describe 2 alternatives for 'wide offset MEM -> $D ' and 'restricted offset MEM -> $A" : (define_insn_and_split "movsicc_internal" [(set (match_operand:SI 0 "register_operand" "=a,d,m,a,d,m,a,d,m") (if_then_else:SI (match_operator 1 "prism_comparison_operator" [(match_operand 4 "cc_register" "") (const_int 0)]) (match_operand:SI 2 "nonimmediate_operand" " v,m,r,0,0,0,v,m,r") ;; "v" constraint is for restricted offset MEM (match_operand:SI 3 " nonimmediate_operand" " 0,0,0,v,m,r,v,m,r")))] ;; the last 3 alternatives are split to match the other alternatives I encountered : (on gcc4.7.3) core_main.c:354:1: error: insn does not satisfy its constraints: (insn 1176 1175 337 26 (set (reg:SI 5 $A5) (if_then_else:SI (ne (reg:CC 56 $CCI) (const_int 0 [0])) (mem/c:SI (plus:SI (reg/f:SI 0 $A0) (const_int 2104 [0x838])) [9 %sfp+2104 S4 A32]) (const_int 1 [0x1]))) core_main.c:211:32 158 {movsicc_internal} Due to reload pass (core_main.c.199r.reload). How can I tune reload or write my movsicc pattern to prevent reload pass from generating a conditional move from wide offset MEM to $A registers ?? Regards, Selim
RE: Controling reloads of movsicc pattern
Hum, I can't change gcc branch because I'm tighted to gnat 7.1.2 based on gcc 4.7.3 (I saw that LRA was merged in 4.8). I will use a workaround for the moment (i.e. disable wide offset MEM on conditional moves). Does someone know if gnat frontend will rebase on 4.8 soon :) ? (or maybe LRA will be merged in 4.7.4 ?) Thanks Selim -Message d'origine- De : Jeff Law [mailto:l...@redhat.com] Envoyé : mercredi 4 décembre 2013 18:02 À : BELBACHIR Selim; gcc@gcc.gnu.org Objet : Re: Controling reloads of movsicc pattern On 12/04/13 03:22, BELBACHIR Selim wrote: > Hi, > > My target has : > - 2 registers class to store SImode (like m68k, data $D & address $A). > - moves from wide offset MEM to $D or $A (ex: mov d($A1+50),$A2 ormov > d($A1+50),$D1) > - conditional moves from offset MEM to $D or $A but with a restriction : > offset MEM conditionally moved to $A has a limited offset of > 0 or 1 (ex: mov.ifEQ d($A1,1),$A1 whereas we can still do mov.ifEQ > d($A1,50),$D1) > > The predicate of movsicc pattern tells GCC that wide offset MEM is allowed > and constraints describe 2 alternatives for 'wide offset MEM -> $D ' and > 'restricted offset MEM -> $A" : > > (define_insn_and_split "movsicc_internal" >[(set (match_operand:SI 0 "register_operand" "=a,d,m,a,d,m,a,d,m") > (if_then_else:SI >(match_operator 1 "prism_comparison_operator" > [(match_operand 4 "cc_register" "") (const_int 0)]) >(match_operand:SI 2 "nonimmediate_operand" " v,m,r,0,0,0,v,m,r") > ;; "v" constraint is for restricted offset MEM >(match_operand:SI 3 " nonimmediate_operand" " > 0,0,0,v,m,r,v,m,r")))] ;; the last 3 alternatives are split to match > the other alternatives > > > > I encountered : (on gcc4.7.3) > > core_main.c:354:1: error: insn does not satisfy its constraints: > (insn 1176 1175 337 26 (set (reg:SI 5 $A5) > (if_then_else:SI (ne (reg:CC 56 $CCI) > (const_int 0 [0])) > (mem/c:SI (plus:SI (reg/f:SI 0 $A0) > (const_int 2104 [0x838])) [9 %sfp+2104 S4 A32]) > (const_int 1 [0x1]))) core_main.c:211:32 158 > {movsicc_internal} > > Due to reload pass (core_main.c.199r.reload). > > > How can I tune reload or write my movsicc pattern to prevent reload pass from > generating a conditional move from wide offset MEM to $A registers ?? If at all possible, I would recommend switching to LRA. There's an up-front cost, but it's definitely the direction all ports should be heading. Avoiding reload is, umm, good. jeff
RE: Controling reloads of movsicc pattern
Any gnat official release ? Maybe gnat 7.2 beta is based on 4.8, I'll try to get this one. -Message d'origine- De : Andrew Pinski [mailto:pins...@gmail.com] Envoyé : vendredi 6 décembre 2013 09:54 À : BELBACHIR Selim Cc : Jeff Law; gcc@gcc.gnu.org Objet : Re: Controling reloads of movsicc pattern On Fri, Dec 6, 2013 at 12:41 AM, BELBACHIR Selim wrote: > Hum, I can't change gcc branch because I'm tighted to gnat 7.1.2 based on gcc > 4.7.3 (I saw that LRA was merged in 4.8). I will use a workaround for the > moment (i.e. disable wide offset MEM on conditional moves). > Does someone know if gnat frontend will rebase on 4.8 soon :) ? (or > maybe LRA will be merged in 4.7.4 ?) If this is the Ada front-end, then it is already part of 4.8 release. Or is this some other front-end? Thanks, Andrew Pinski > > Thanks > > Selim > > -Message d'origine- > De : Jeff Law [mailto:l...@redhat.com] > Envoyé : mercredi 4 décembre 2013 18:02 À : BELBACHIR Selim; > gcc@gcc.gnu.org Objet : Re: Controling reloads of movsicc pattern > > On 12/04/13 03:22, BELBACHIR Selim wrote: >> Hi, >> >> My target has : >> - 2 registers class to store SImode (like m68k, data $D & address $A). >> - moves from wide offset MEM to $D or $A (ex: mov d($A1+50),$A2 or >> mov d($A1+50),$D1) >> - conditional moves from offset MEM to $D or $A but with a restriction : >> offset MEM conditionally moved to $A has a limited offset >> of >> 0 or 1 (ex: mov.ifEQ d($A1,1),$A1 whereas we can still do mov.ifEQ >> d($A1,50),$D1) >> >> The predicate of movsicc pattern tells GCC that wide offset MEM is allowed >> and constraints describe 2 alternatives for 'wide offset MEM -> $D ' and >> 'restricted offset MEM -> $A" : >> >> (define_insn_and_split "movsicc_internal" >>[(set (match_operand:SI 0 "register_operand" "=a,d,m,a,d,m,a,d,m") >> (if_then_else:SI >>(match_operator 1 "prism_comparison_operator" >> [(match_operand 4 "cc_register" "") (const_int 0)]) >>(match_operand:SI 2 "nonimmediate_operand" " >> v,m,r,0,0,0,v,m,r") ;; "v" constraint is for restricted offset MEM >>(match_operand:SI 3 " nonimmediate_operand" " >> 0,0,0,v,m,r,v,m,r")))] ;; the last 3 alternatives are split to match >> the other alternatives >> >> >> >> I encountered : (on gcc4.7.3) >> >> core_main.c:354:1: error: insn does not satisfy its constraints: >> (insn 1176 1175 337 26 (set (reg:SI 5 $A5) >> (if_then_else:SI (ne (reg:CC 56 $CCI) >> (const_int 0 [0])) >> (mem/c:SI (plus:SI (reg/f:SI 0 $A0) >> (const_int 2104 [0x838])) [9 %sfp+2104 S4 A32]) >> (const_int 1 [0x1]))) core_main.c:211:32 158 >> {movsicc_internal} >> >> Due to reload pass (core_main.c.199r.reload). >> >> >> How can I tune reload or write my movsicc pattern to prevent reload pass >> from generating a conditional move from wide offset MEM to $A registers ?? > If at all possible, I would recommend switching to LRA. There's an up-front > cost, but it's definitely the direction all ports should be heading. > Avoiding reload is, umm, good. > > jeff >
cpp0x test suite PASS/FAIL
Hi, I'm playing c++ testsuite on my gcc.4.7.3 port and I encounter the following result on test auto27.C PASS: g++.dg/cpp0x/auto27.C -std=c++98 std (test for errors, line 3) PASS: g++.dg/cpp0x/auto27.C -std=c++98 auto (test for errors, line 3) PASS: g++.dg/cpp0x/auto27.C -std=c++98 no type (test for errors, line 3) PASS: g++.dg/cpp0x/auto27.C -std=c++98 (test for excess errors) FAIL: g++.dg/cpp0x/auto27.C -std=c++11 std (test for errors, line 3) FAIL: g++.dg/cpp0x/auto27.C -std=c++11 auto (test for errors, line 3) FAIL: g++.dg/cpp0x/auto27.C -std=c++11 no type (test for errors, line 3) PASS: g++.dg/cpp0x/auto27.C -std=c++11 (test for excess errors) auto27.C : auto main()->int // { dg-error "std=" "std" { target c++98 } } // { dg-error "auto" "auto" { target c++98 } 3 } // { dg-error "no type" "no type" { target c++98 } 3 } { } I don't understand if DejaGNU tells me that the test is OK or KO ... When I use -std=c++98 option, I get the 3 expected errors and when I use -std=c++11, I get no error. That seems to be the expected result but I don't understand why the word FAIL appears in the log... Should I ignore the FAILs when the comment contains '(test for errors' and consider that those tests are parts of a larger test with comment '(test for excess errors' ? Regards, Selim
RE: cpp0x test suite PASS/FAIL
I have exactly the same behaviour than my native linux compiler. I don't understand why DejaGnu exp files print such FAIL. 3 errors has to be printed when using -std=c++98 and 0 errors has to be printed when using -std=c++11. That's what my compiler does. The selector 'target c++98' (in { dg-error "std=" "std" { target c++98 } } for example) do not prevent the FAIL to be printed when -std=c++11 options is used. Only the last 'test for excess errors' seems to understand that no errors has to be printed when using -std=c++11 Here is the DejaGnu log : Running gcc-4.7.3/gcc/testsuite/g++.dg/dg.exp ... ALWAYS_CXXFLAGS set to additional_flags= ldflags= additional_flags=-fmessage-length=0 Executing on host: prism-g++ gcc-4.7.3/gcc/testsuite/g++.dg/cpp0x/auto27.C -fmessage-length=0 -std=c++98 -pedantic-errors -Wno-long-long -S -o auto27.s (timeout = 300) gcc-4.7.3/gcc/testsuite/g++.dg/cpp0x/auto27.C:3:14: error: ISO C++ forbids declaration of 'main' with no type [-pedantic] gcc-4.7.3/gcc/testsuite/g++.dg/cpp0x/auto27.C:3:14: error: top-level declaration of 'main' specifies 'auto' gcc-4.7.3/gcc/testsuite/g++.dg/cpp0x/auto27.C:3:14: error: trailing return type only available with -std=c++11 or -std=gnu++11 compiler exited with status 1 output is: gcc-4.7.3/gcc/testsuite/g++.dg/cpp0x/auto27.C:3:14: error: ISO C++ forbids declaration of 'main' with no type [-pedantic] gcc-4.7.3/gcc/testsuite/g++.dg/cpp0x/auto27.C:3:14: error: top-level declaration of 'main' specifies 'auto' gcc-4.7.3/gcc/testsuite/g++.dg/cpp0x/auto27.C:3:14: error: trailing return type only available with -std=c++11 or -std=gnu++11 PASS: g++.dg/cpp0x/auto27.C -std=c++98 std (test for errors, line 3) PASS: g++.dg/cpp0x/auto27.C -std=c++98 auto (test for errors, line 3) PASS: g++.dg/cpp0x/auto27.C -std=c++98 no type (test for errors, line 3) PASS: g++.dg/cpp0x/auto27.C -std=c++98 (test for excess errors) Executing on host: prism-g++ gcc-4.7.3/gcc/testsuite/g++.dg/cpp0x/auto27.C -fmessage-length=0 -std=c++11 -pedantic-errors -Wno-long-long -S -DSIGNAL_SUPPRESS -DNO_TRAMPOLINES -DSTACK_SIZE=0x4800 -o auto27.s(timeout = 300) FAIL: g++.dg/cpp0x/auto27.C -std=c++11 std (test for errors, line 3) FAIL: g++.dg/cpp0x/auto27.C -std=c++11 auto (test for errors, line 3) FAIL: g++.dg/cpp0x/auto27.C -std=c++11 no type (test for errors, line 3) PASS: g++.dg/cpp0x/auto27.C -std=c++11 (test for excess errors) -Message d'origine- De : Joseph Myers [mailto:jos...@codesourcery.com] Envoyé : mardi 10 décembre 2013 18:22 À : BELBACHIR Selim Cc : gcc@gcc.gnu.org Objet : Re: cpp0x test suite PASS/FAIL On Tue, 10 Dec 2013, BELBACHIR Selim wrote: > FAIL: g++.dg/cpp0x/auto27.C -std=c++11 std (test for errors, line 3) > FAIL: g++.dg/cpp0x/auto27.C -std=c++11 auto (test for errors, line 3) > FAIL: g++.dg/cpp0x/auto27.C -std=c++11 no type (test for errors, line > 3) That means that the desired result is an error message on that line, and either there was no such error message or the error message did not match what the testcase expected. > Should I ignore the FAILs when the comment contains '(test for errors' > and consider that those tests are parts of a larger test with comment > '(test for excess errors' ? No, FAILs indicate a bug in either the compiler or the testcase (or in your test environment, etc.); don't ignore them. -- Joseph S. Myers jos...@codesourcery.com
RE: cpp0x test suite PASS/FAIL
Ok so it's a problem local to my environment that I must fix. I've downloaded the lastest dejagnu 1.5.1 but it doesn't solve the problem. I found in no documentation the selector 'target c++98' but it should exist somewhere because about 20 c++11 tests use it and FAIL the same way. I'll try to investigate further (tcl is a pain for me :) ) Selim -Message d'origine- De : Joseph Myers [mailto:jos...@codesourcery.com] Envoyé : mardi 10 décembre 2013 18:57 À : BELBACHIR Selim Cc : gcc@gcc.gnu.org Objet : RE: cpp0x test suite PASS/FAIL On Tue, 10 Dec 2013, BELBACHIR Selim wrote: > The selector 'target c++98' (in { dg-error "std=" "std" { target c++98 > } } for example) do not prevent the FAIL to be printed when -std=c++11 > options is used. Well, that would be a bug in one of (a) the test harness code, (b) the way the selector is used, (c) your DejaGnu installation. In none of those cases is ignoring the FAIL appropriate; both (a) and (c) could well cause other problems with inaccurate test results elsewhere in the testsuite. You'll need to investigate why DejaGnu isn't behaving as intended on your system. -- Joseph S. Myers jos...@codesourcery.com
RE: cpp0x test suite PASS/FAIL
I found a potential problem in "dejagnu-1.5.1/lib/framework.exp" (or previous version) As I said before, in my case, the selector 'target std=c++98' doesn't seems to prevent the FAIL when -std=c++11 options is used in compiler flags. I noticed that -std=c++11 is my last compiler flag and in function "check_conditional_xfail" from dejagnu-1.5.1/lib/framework.exp (called by check-flags from gcc-4.7.3/gcc/testsuite/lib/target-supports-dg.exp) I saw the following lines : verbose "Looking for $opt to exclude in the compiler flags" 2 foreach j "$opt" { if {[string match "* $j *" $compiler_flags]} { verbose "Found $j to exclude in the compiler flags" 2 incr excl_hit } } 'string match' uses "* $j *" , i.e. a white space is required after each option in order to be properly matched. When an option is the last compiler flag then it cannot be matched because it is not followed by a white space. This explains why the dg-error is not ignored when compiler with -std=c++11 even if selector 'target c++98' is used. I may be the only one to meet this exact problem because for some reasons -std=c++xx options is my last flag AND some tests use a selector on this particular flag. But, imho the problem can be met on any other flag as far as it is the last compiler flag. Answer : (a) bug in the test harness code Am I right ? Selim -Message d'origine- De : Joseph Myers [mailto:jos...@codesourcery.com] Envoyé : mardi 10 décembre 2013 18:57 À : BELBACHIR Selim Cc : gcc@gcc.gnu.org Objet : RE: cpp0x test suite PASS/FAIL On Tue, 10 Dec 2013, BELBACHIR Selim wrote: > The selector 'target c++98' (in { dg-error "std=" "std" { target c++98 > } } for example) do not prevent the FAIL to be printed when -std=c++11 > options is used. Well, that would be a bug in one of (a) the test harness code, (b) the way the selector is used, (c) your DejaGnu installation. In none of those cases is ignoring the FAIL appropriate; both (a) and (c) could well cause other problems with inaccurate test results elsewhere in the testsuite. You'll need to investigate why DejaGnu isn't behaving as intended on your system. -- Joseph S. Myers jos...@codesourcery.com
Why __builtin_sqrt do not totally replace sqrt in asm
Hi, When the standard pattern 'sqrtm2' is defined I don't understand why calls to sqrt or __builtin_sqrt is always followed by a comparison of the result with itself (checking the NaN ?) and a conditional branch to sqrt symbol (so linking with libm is always mandatory). - mov $FP0,$FP1 fsqrt $FP0, $FP0<< the builtin_sqrt fcompare $FP0,$FP0 << strange compare of the result of builtin_sqrt jmp.ifEQUAL .L2 mov $FP1,$FP0 branch sqrt<< branch to sqrt symbol if $FP0 != $FP0 .L2 - Is there a way to tell GCC that sqrt function is totally handled by __builtin_sqrt ? Regards, Selim
lto testsuite may erase mathlib variable
Hi, I noticed a problem in gcc/testsuite/g++.dg/lto/lto.exp If the target does not support LTO (check_effective_target_lto) a brutal return is performed so the mathlib variable modified in lto_init will not be restored properly by lto_finish at the end of the script. Subsequent testsuites will found an empty mathlib. Regards, Selim patch Description: patch
wrong assertion in caller-save.c
Hi, I think I found a bug in gcc 4.7.3 in gcc/caller-save.c at line 158 : gcc_assert (cached_reg_save_code[reg][mode]); should be : gcc_assert (cached_reg_save_code[reg][mode] != -1); because cached_reg_save_code contains INSN_CODES that can be equal to 0 (see attached patch) In my backend movdi pattern has unfortunately code '0' (depends on pattern declaration order). When gcc tried to determine if my DI regs can be saved and restore as 'caller saves' (in caller-save.c::init_caller_save()) it failed on this wrong assertion. Regards, Selim caller-save.patch Description: caller-save.patch
type argument in FUNCTION_ARG macro
Hi, I'm working on an architecture where the calling convention depends on the type of the parameter (i.e. pointers are passed into $C regs and non-pointers are passed into $R regs). I've implemented this difference by using the POINTER_TYPE_P() macro on the 'type' argument of the FUNCTION_ARG macro. I'm having a problem with this approach with calls to libgcc function like _Unwind_SjLj_Register(struct foo * ). As this function is invoked as a library function, the 'type' argument to the FUNCTION_ARG() macro is NULL. Thus, the pointer parameter is not passed as pointer but the function body expects a pointer. Any ideas on how to get around this problem? Regards, Selim
RE: type argument in FUNCTION_ARG macro
That's the only option ? Is there a more general method to do this ? -Message d'origine- De : amyl...@spamcop.net [mailto:amyl...@spamcop.net] Envoyé : vendredi 4 mai 2012 15:48 À : BELBACHIR Selim Cc : gcc@gcc.gnu.org Objet : Re: type argument in FUNCTION_ARG macro Quoting BELBACHIR Selim : > Any ideas on how to get around this problem? You can look at the name of library functions.
RE: type argument in FUNCTION_ARG macro
Ok thanks, I'll keep on with plan B (INIT_CUMULATIVE_LIBCALL_ARGS with special libcall handling) Selim -Message d'origine- De : Ian Lance Taylor [mailto:i...@google.com] Envoyé : vendredi 4 mai 2012 15:58 À : BELBACHIR Selim Cc : gcc@gcc.gnu.org Objet : Re: type argument in FUNCTION_ARG macro BELBACHIR Selim writes: > I'm working on an architecture where the calling convention depends on the > type of the parameter (i.e. pointers are passed into $C regs and non-pointers > are passed into $R regs). I've implemented this difference by using the > POINTER_TYPE_P() macro on the 'type' argument of the FUNCTION_ARG macro. > > I'm having a problem with this approach with calls to libgcc function > like _Unwind_SjLj_Register(struct foo * ). As this function is invoked as a > library function, the 'type' argument to the FUNCTION_ARG() macro is NULL. > Thus, the pointer parameter is not passed as pointer but the function body > expects a pointer. > > Any ideas on how to get around this problem? If possible, avoid using SJLJ exceptions. DWARF exceptions are better. I see three ways to go. Change the middle-end to avoid using emit_library_call when calling _Unwind_SjLj_Register. There is no particular reason for making this a special library call. But this is probably a bit painful to implement. Define INIT_CUMULATIVE_LIBCALL_ARGS for your target, and check the function. If it's _Unwind_SjLj_Register, apply special handling. This option is nice because you only have to change your backend. Change the implementation of _Unwind_SjLj_Register to take a parameter of type uintptr_t, and cast it to struct SjLj_Function_Context *. Ian
ADA runtime System.Address type
Hi, I'm working on a gcc/gnat port for a private target (gcc 4.5.2, gnat 6.4.2). On this target, scalar values shall be stored in $R registers whereas pointer values shall be stored in $C registers. My current ABI for procedure/function calls uses $R and $C registers depending on arguments and return values type (scalar or pointer). I need an ABI of this kind for performance reasons (the instruction set does not allow $R and $C everywhere and copying $R in $C for each procedure calls is too expensive). I tested this ABI through GCC C and C++ torture suite and everything is ok (after solving special cases for implicit calls) During my tests I tried to mix ADA and C sources code using the 'pragma import/export'. For example I tried to implement the "__gnat_malloc" expected by the ZFP runtime by an ADA function and 'pragma export' : function Gnat_Malloc (Size : in Integer) return System.Address is begin -- implementation end Gnat_Malloc; pragma Export (C, Gnat_Malloc, "__gnat_malloc"); Here is my problem : * the caller of __gnat_malloc expects that return value of type pointer to be in a $C register (as defined in the ABI) * the called function Gnat_Malloc return a value of type system.address in $R register because system.address is considered as a scalar value (system.ads: type Address is mod Memory_Size;) ==> caller and callee return values doesn't match, the ABI is broken I tried to modified system.ads so that system.address arguments become pointers (using access keyword) but I can't figure out how to do this because the System package is 'pragma Pure' ... Is there a way to modify something somewhere (runtime, backend, frontend ...) so that arguments of type system.address are seen as pointers and not scalar values ? Regards, Selim Belbachir