real.h: REAL_VALUE_TO_TARGET_DOUBLE
Hi All, Shouldn't this macro: #define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \ real_to_target (OUT, &(IN), mode_for_size (64, MODE_FLOAT, 0)) be using DOUBLE_TYPE_SIZE instead of the hard coded '64'? Am I missing something here? In the target I am currently working, DOUBLE_TYPE_SIZE is defined as 32-bit, so the hard-coded '64' is causing trouble. I am planning on doing this change on my local source tree, but wanted to discuss with the community to see if there is some implementations details somewhere that I need to consider as well. Best regards, -Omar
Re: real.h: REAL_VALUE_TO_TARGET_DOUBLE
On Thu, Oct 2, 2008 at 11:59 PM, Ian Lance Taylor <[EMAIL PROTECTED]> wrote: > "Omar Torres" <[EMAIL PROTECTED]> writes: > >> Shouldn't this macro: >> #define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \ >> real_to_target (OUT, &(IN), mode_for_size (64, MODE_FLOAT, 0)) >> >> be using DOUBLE_TYPE_SIZE instead of the hard coded '64'? Am I missing >> something here? > > That would certainly be more logical. In order to make that change, > you would have to consider each use of the macro to confirm that the > change would be valid. > > >> In the target I am currently working, DOUBLE_TYPE_SIZE is defined as >> 32-bit, so the hard-coded '64' is causing trouble. I am planning on >> doing this change on my local source tree, but wanted to discuss with >> the community to see if there is some implementations details somewhere >> that I need to consider as well. > > As far as I can see, all but one use of this macro is in target > dependent code. Are you having trouble from the single target > independent use? Or perhaps your target dependent code should just > use REAL_VALUE_TO_TARGET_SINGLE instead? > > Ian > Both. Yes, I can use REAL_VALUE_TO_TARGET_SINGLE in the target dependent files to work around this. I do not see a similar solution for the target independent code, since the size mismatch cause the incorrect format (encode/decode functions) to be use. Thanks, -Omar
Re: real.h: REAL_VALUE_TO_TARGET_DOUBLE
On Fri, Oct 3, 2008 at 1:49 PM, Richard Henderson <[EMAIL PROTECTED]> wrote: > The size of the C type "double" is controlled by DOUBLE_TYPE_SIZE, > not the size of the compiler mode "DFmode". This macro is referring > to the latter -- a double-precision floating point mode. > > > r~ > Richard, I do not fully understand your comments, but I will like to. So your pacience is greatly appreciated. Here are some more specific's about the target I am working with: float maps to 3 byte (TQF) and and double maps to 4 byte (SF). This is how my target/target-modes.def file looks like: FLOAT_MODE (TQF, 3, cool_float_format); RESET_FLOAT_FORMAT (SF, cool_float_format); Now, given this information, looks like the macro in question (REAL_VALUE_TO_TARGET_DOUBLE) is implicitly forcing a 64-bit (DF) encoding into my target, which do not really exists. I understand my target is an outliner, but shouldn't the DOUBLE_TYPE_SIZE be used in this macro to cover targets like mine? Thanks, -Omar
divmodsi4
Hi All, I am having trouble distinguishing div vs mod while implementing the divmodsi4 instruction. The gccint documentation states: "If an instruction that just produces a quotient or just a remainder exists and is more efficient than the instruction that produces both, write the output routine of 'divmodm4' to call find_reg_note and look for a REG_UNUSED note on the quotient or remainder and generate the appropriate instruction." The problem is that both, the quotient and reminder, registers are getting marked with a REG_UNUSED note: (insn 12 11 17 (parallel [ (set (reg:SI 1 %r3 [33]) (div:SI (reg:SI 1 %r3 [30]) (reg:SI 5 %iph [orig:31 current ] [31]))) (set (reg:SI 5 %iph [34]) (mod:SI (reg:SI 1 %r3 [30]) (reg:SI 5 %iph [orig:31 current ] [31]))) ]) 56 {*divmodsi4} (insn_list:REG_DEP_TRUE 10 (insn_list:REG_DEP_TRUE 11 (nil))) (expr_list:REG_UNUSED (reg:SI 5 %iph [34]) (expr_list:REG_UNUSED (reg:QI 2 %r2) (expr_list:REG_UNUSED (reg:QI 1 %r3) (nil) Any suggestions on how I might be able to work around this? Thanks! -Omar Here is my expander and matching patter: (define_expand "divmodsi4" [(parallel [(set (match_operand:SI 0 "register_operand" "") (div:SI (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "general_operand" ""))) (set (match_operand:SI 3 "nonimmediate_operand" "") (mod:SI (match_dup 1) (match_dup 2)))])] "" "") (define_insn "*divmodsi4" [(set (match_operand:SI 0 "register_operand" "=f") (div:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g"))) (set (match_operand:SI 3 "nonimmediate_operand" "=g") (mod:SI (match_dup 1) (match_dup 2)))] "!TARGET_SOFTLIB" "* return output_divmod (insn, operands, 1); ")
Re: divmodsi4
On Fri, Oct 10, 2008 at 10:40 AM, Dave Korn <[EMAIL PROTECTED]> wrote: > Ian Lance Taylor wrote on 10 October 2008 15:53: > >> "Omar Torres" <[EMAIL PROTECTED]> writes: >> >>> The problem is that both, the quotient and reminder, registers are >>> getting marked with a REG_UNUSED note: >>> >>> (insn 12 11 17 (parallel [ >>> (set (reg:SI 1 %r3 [33]) >>> (div:SI (reg:SI 1 %r3 [30]) >>> (reg:SI 5 %iph [orig:31 current ] [31]))) >>> (set (reg:SI 5 %iph [34]) >>> (mod:SI (reg:SI 1 %r3 [30]) >>> (reg:SI 5 %iph [orig:31 current ] [31]))) >>> ]) 56 {*divmodsi4} (insn_list:REG_DEP_TRUE 10 >>> (insn_list:REG_DEP_TRUE 11 (nil))) >>> (expr_list:REG_UNUSED (reg:SI 5 %iph [34]) >>> (expr_list:REG_UNUSED (reg:QI 2 %r2) >>> (expr_list:REG_UNUSED (reg:QI 1 %r3) >>> (nil) >>> >>> Any suggestions on how I might be able to work around this? >> >> This makes it sounds like the whole insn is useless. I wonder why it >> hasn't simply been deleted? > > Is it not unusual that the insn sets r1 in SImode, but the note says it is > unused in QImode? Does that mean only the lowest byte is unused? > >cheers, > DaveK > -- > Can't think of a witty .sigline today > > Hi, thanks for the comments. A closer look revealed that this insn is not deleted because it is needed to (partially) set (reg:SI 33). But, as Dave suggested, only the lower part of the quotient is used afterwards. Below is the src code and the corresponding basic block. I suspect that a workaround will be to look not only for the presence of the REG_UNUSED note, but check check the reg's mode as well, to successfully determine whether the quotient or remainder is needed in divmodsi4. Do you agree this will be a practical approach, or is it fundamentally flawed? Thanks, -Omar (machine's word size is 8-bits) int Resistance (int volt, int current) { return ((long) volt<<10)/current; } ;; basic block 2, loop depth 0, count 0 ;; prev block 0, next block 1 ;; pred: ENTRY [100.0%] (fallthru) ;; succ: EXIT [100.0%] (fallthru) ;; Registers live at start: 1 [%r3] 2 [%r2] 3 [%r1] 4 [%r0] 11 [%i2h] 13 [%i3h] 16 [%ap_hi] 18 [%fp_hi] (note 6 2 3 2 [bb 2] NOTE_INSN_BASIC_BLOCK) (insn 3 6 4 2 (set (reg/v:HI 26 [ volt ]) (reg:HI 1 %r3 [ volt ])) 1 {movhi} (nil) (nil)) (insn 4 3 5 2 (set (reg/v:HI 27 [ current ]) (reg:HI 3 %r1 [ current ])) 1 {movhi} (nil) (nil)) (note 5 4 8 2 NOTE_INSN_FUNCTION_BEG) (insn 8 5 9 2 (set (reg:SI 29 [ volt ]) (sign_extend:SI (reg/v:HI 26 [ volt ]))) 149 {extendhisi2} (nil) (nil)) (insn 9 8 10 2 (set (reg:SI 1 %r3) (ashift:SI (reg:SI 29 [ volt ]) (const_int 10 [0xa]))) 71 {*ashlsi3} (nil) (nil)) (insn 10 9 11 2 (set (reg:SI 30) (reg:SI 1 %r3)) 2 {movsi} (nil) (expr_list:REG_EQUAL (ashift:SI (reg:SI 29 [ volt ]) (const_int 10 [0xa])) (nil))) (insn 11 10 12 2 (set (reg:SI 31 [ current ]) (sign_extend:SI (reg/v:HI 27 [ current ]))) 149 {extendhisi2} (nil) (nil)) (insn 12 11 17 2 (parallel [ (set (reg:SI 33) (div:SI (reg:SI 30) (reg:SI 31 [ current ]))) (set (reg:SI 34) (mod:SI (reg:SI 30) (reg:SI 31 [ current ]))) ]) 56 {*divmodsi4} (nil) (nil)) (note 17 12 20 2 NOTE_INSN_FUNCTION_END) (insn 20 17 26 2 (set (reg/i:HI 1 %r3 [ ]) (subreg:HI (reg:SI 33) 2)) 1 {movhi} (insn_list:REG_DEP_TRUE 12 (nil)) (expr_list:REG_DEAD (reg:SI 33) (nil))) (insn 26 20 0 2 (use (reg/i:HI 1 %r3 [ ])) -1 (insn_list:REG_DEP_TRUE 20 (nil)) (nil)) ;; Registers live at end: 1 [%r3] 2 [%r2] 11 [%i2h] 13 [%i3h] 16 [%ap_hi] 18 [%fp_hi]
error: unable to emulate 'DI'
Hi All, I have a similar issue to what is reported here (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20143): /Applications/avr/avr-src/gcc/unwind.h:59: error: unable to emulate 'DI' As you clearly expressed by Paul, the underline issue that the target only support data types up to 32-bits, while gcc is expecting up to 64-bit support. Any suggestions on how to workaround this? Thanks, -Omar
Re: error: unable to emulate 'DI'
Hi Andrew, Looks like Paul did submitted a patch here: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20675 Can you or someone else take a look and comment on it? Thanks! -Omar On Thu, Oct 16, 2008 at 4:08 AM, Andrew Haley <[EMAIL PROTECTED]> wrote: > Omar Torres wrote: > >> I have a similar issue to what is reported here >> (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20143): >> /Applications/avr/avr-src/gcc/unwind.h:59: error: unable to emulate 'DI' >> >> As clearly expressed by Paul, the underline issue that the target >> only support data types up to 32-bits, while gcc is expecting up to >> 64-bit support. >> >> Any suggestions on how to workaround this? > > Paul Schlie said: > > "The further good news is that upon reviewing the DWARF2 spec in detail, > and GCC's implementation, it's clear that a 32-bit DWARF data structure > is sufficient to support any target with 32-bit or less data type sizes. > > "(which seems that it may be reasonably easy to support by declaring the > DWARF data structure size as a function of the size of target's the maxim > declared data type size; although possibly limited to a practical minimum > of 32-bits, which seems much more reasonable for smaller targets)" > > but no-one has ever AFAIAA submitted a patch that does this. > > Andrew. > > >
Re: error: unable to emulate 'DI'
On Thu, Oct 16, 2008 at 10:02 AM, Andrew Haley <[EMAIL PROTECTED]> wrote: > Omar Torres wrote: >> Hi Andrew, >> Looks like Paul did submitted a patch here: >> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20675 >> >> Can you or someone else take a look and comment on it? > > Oh my goodness, that is a huge patch. It's also incorrect, as > far as I can see: LONG_LONG_TYPE_SIZE is never less than 64 bits, > so this test always returns true. There's a discussion in Section > 6.2.5. of the rationale in C99 that explains why long long is defined > to be this way. > > Andrew. > LONG_LONG_TYPE_SIZE is in fact defined as 32-bit in the port I am working. I inherited this GCC port, so I do not now whether or not this is fully compliant with C99 standard. I believe the reason is to reduce code size (this is an 8-bit word target, 64-bit operations are very expensive). The core is aimed, at low-power embedded applications without an OS (an event-driven scheduler is used instead). A very old GCC port has been sucessfuly used for years, all I am trying to do is to bring that old port to a more current version of GCC. Tahnks, -Omar
Re: error: unable to emulate 'DI'
On Thu, Oct 16, 2008 at 10:42 AM, Andrew Haley <[EMAIL PROTECTED]> wrote: > >> LONG_LONG_TYPE_SIZE is in fact defined as 32-bit in the port I am >> working. I inherited this GCC port, so I do not now whether or not >> this is fully compliant with C99 standard. > > You do now. Yes, thanks. > >> I believe the reason is to reduce code size (this is an 8-bit word >> target, 64-bit operations are very expensive). > >> The core is aimed, at low-power embedded applications without an OS >> (an event-driven scheduler is used instead). A very old GCC port has >> been sucessfuly used for years, all I am trying to do is to bring that >> old port to a more current version of GCC. > > Sure, I understand that, and I also note one or two ports define > LONG_LONG_TYPE_SIZE otherwise. > I see avr port's situation: ./avr/avr.h:#define LONG_LONG_TYPE_SIZE (INT_TYPE_SIZE == 8 ? 32 : 64) I need to investigate how do they get pass the boot-strapping part of gcc... Mean while, if anyone have any insight, I am all ears. > Andrew. > Thanks, -0mar
Re: error: unable to emulate 'DI'
On Thu, Oct 16, 2008 at 11:59 AM, Andrew Haley <[EMAIL PROTECTED]> wrote: > Paul Schlie wrote: >> Andrew Haley wrote: >>> Omar Torres wrote: >>>> Hi Andrew, >>>> Looks like Paul did submitted a patch here: >>>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20675 >>>> >>>> Can you or someone else take a look and comment on it? >>> Oh my goodness, that is a huge patch. It's also incorrect, as >>> far as I can see: LONG_LONG_TYPE_SIZE is never less than 64 bits, >>> so this test always returns true. There's a discussion in Section >>> 6.2.5. of the rationale in C99 that explains why long long is defined >>> to be this way. >> >> Yes, a target port which which does not support 64 bit operations >> could not be strictly C99 compliant, however don't see any reason >> to forbid such as may be desired with this understanding; as such >> a port would remain compliant otherwise and fully useful in this >> respect, and remain fully compliant with earlier standards. > > I don't understand this. If a target will generate inefficient code > for long long, that is surely no reason not to support it, it's a > reason to avoid using it. How does the availability of long long > cause any kind of a problem? Agree, and it turns out that long long is *never* used in the intended application, so the original port author decided not to bother implementing 64-bit support. Since implementing 64-bit support for this target is out of the question in the immediate future, I am in the look for an alternative solution. Realized just now that the original port have a comment on how to work around this same issue: # We do not have DF or DI types, so fake out the libgcc2 compilation. TARGET_LIBGCC2_CFLAGS = -DDF=SF -DDI=SI -D__DF__=__SF__ -D__DI__=__SI__ Looks like GCC now sucessfuly complies my x-compiler. Now, the hard part: check that it does the "right thing". Thanks for your help! -Omar
Re: Reviving old port
Richard, Thanks a lot for the detailed explanation. I need some time to digest, since this is my first experience doing a gcc backend port. > Probably most of that was just telling you what you already knew, sorry. Not really, I am new to most of these concepts. At this stage, this is exactly the amount of details I am looking for. Thanks a lot for your patience and level of detail. > Good luck with the port, > > Richard Regards, -Omar
splitting const_int's
Hi All, Since the architecture I am working with only support byte size moves, I created a define_split break HI-move insn's into two QI-moves. For example, the following insn: (insn 84 5 9 (set (reg:HI 1 %r3) (const_int 32767 [0x7fff])) 3 {*movhi} (nil) (nil)) I split it into: (set (reg:QI 1 %r3) (const_int 127 [0x7f]) (set (reg:QI 2 %r2) (const_int 255 [0x255]) I expect that the simplified RTL will be detected by the movqi pattern: (define_insn "movqi" [(set (match_operand:QI 0 "nonimmediate_operand" "=r,m") (match_operand:QI 1 "general_operand" "g,r"))] "" "move\t%0,%1") The split split is working as I expect, but the problem is that the movqi is not recognizing the the second part of the move: error: unrecognizable insn: (insn 94 93 9 (set (reg:QI 2 %r2 [orig:1+1 ] [1]) (const_int 255 [0xff])) -1 (nil) (nil)) After further investigating this, I was able find why the movqi is not recognizing this patter. The const_int 255 fails this statement in the general_operand predicate: if (GET_CODE (op) == CONST_INT && mode != VOIDmode && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) return 0; When I debug this I can see that trunc_int_for_mode is returning -1 while the INTVAL macro returns 255. Any suggestions on how to fix this issue? Below is the complete define_split I am referring above. (define_split [(set (match_operand:HI 0 "nonimmediate_operand" "") (match_operand:HI 1 "general_operand" ""))] "reload_completed && REG_P (operands[0])" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] "{ gcc_assert (REG_P (operands[0])); operands[2] = gen_highpart(QImode, operands[0]); operands[3] = gen_lowpart (QImode, operands[0]); if (REG_P (operands[1])) { operands[4] = gen_highpart (QImode, operands[1]); operands[5] = gen_lowpart (QImode, operands[1]); } else if (MEM_P (operands[1]) || CONST == GET_CODE (operands[1])) { int ioff; rtx base, off; base = XEXP (operands[1],0); off = gen_rtx_CONST_INT (VOIDmode, 0); if (CONST == GET_CODE (base)) { base = XEXP(base,0); } if (PLUS == GET_CODE (base)) { off = XEXP (base,1); base = XEXP (base,0); } gcc_assert (REG == GET_CODE (base) && CONST_INT == GET_CODE (off)); ioff = INTVAL (off); gcc_assert (254 >= ioff && 0 <= ioff); operands[4] = gen_rtx_MEM (QImode, gen_rtx_PLUS (Pmode, base, gen_rtx_CONST_INT (QImode, ioff + 1))); operands[5] = gen_rtx_MEM (QImode, gen_rtx_PLUS (Pmode, base, gen_rtx_CONST_INT(QImode, ioff))); } else if (LABEL_REF == GET_CODE (operands[1]) || SYMBOL_REF == GET_CODE (operands[1])) { operands[4] = simplify_gen_subreg(QImode,operands[1],HImode,0); operands[5] = simplify_gen_subreg(QImode,operands[1],HImode,1); } else if (CONST_INT == GET_CODE (operands[1])) { int val = INTVAL (operands[1]); int low = val & 0xff; int high = (val>>8) & 0xff; operands[4] = gen_rtx_CONST_INT (QImode, high); operands[5] = gen_rtx_CONST_INT (QImode, low); } else { fprintf (stderr, \"\nUnrecongnized:\"); debug_rtx (operands[1]); } }") Thanks, -Omar
Re: splitting const_int's
Just correcting a typo... Omar Torres wrote: > I split it into: (set (reg:QI 1 %r3) (const_int 127 [0x7f]) (set (reg:QI 2 %r2) (const_int 255 [0xFF])
Re: splitting const_int's
Richard Sandiford wrote: > > You might as well make the first operand a register_operand and > avoid the REG_P check. I agree. I implemented this change and it works as expected. >More importantly: > >>operands[4] = simplify_gen_subreg(QImode,operands[1],HImode,0); >>operands[5] = simplify_gen_subreg(QImode,operands[1],HImode,1); > > ..this code is designed to handle REGs and CONST_INTs correctly, > and avoid the problem you were seeing. (As Eric says, gen_int_mode > is the canonical way of generating a correct CONST_INT in cases where > you do need to create one manually. In this case it's simpler to use > simplify_gen_subreg though.) I modified the code as below and now I do not have the problems I had before. else if (CONST_INT == GET_CODE (operands[1]) || REG_P (operands[1])) { operands[4] = simplify_gen_subreg(QImode,operands[1],HImode,0); operands[5] = simplify_gen_subreg(QImode,operands[1],HImode,1); } > I notice you're generating subregs of symbolic constants, > but I'm not sure that's really supported. I did this so that I can generate rtl code that I can latter trap with the define_insn's below. (define_insn "movqi_hiword" [(set (match_operand:QI 0 "register_operand" "") (subreg:QI (match_operand:HI 1 "general_operand" "") 0))] "" "move\t%0,#HIWORD(%1)" ) (define_insn "*movqi_lowword" [(set (match_operand:QI 0 "register_operand" "") (subreg:QI (match_operand:HI 1 "general_operand" "") 1))] "" "move\t%0,#LOWWORD(%1)" ) Do you recommend a better way to do this? > As far as the MEM_P case goes: [...] > > you can use: > > operands[4] = adjust_address (operands[1], QImode, 1); > operands[5] = adjust_address (operands[1], QImode, 0); > I also implemented this and it works nicely. Many thanks! > The CONST handling looks suspicious here. CONSTs aren't memory references, > but you split them into memory references. In my debugging session, all cases I say CONSTs they were used for memory. I will look at this in more detail. > Also, you need to beware of cases in which operands[1] overlaps > operands[0]. The splitter says: > > [(set (match_dup 2) (match_dup 4)) > (set (match_dup 3) (match_dup 5))] > > and operands[2] is always the highpart: > >operands[2] = gen_highpart(QImode, operands[0]); > > but consider the case in which operands[1] (and thus operands[4]) > is a memory reference that uses the high part of operands[0] as > a base register. In that case, the base register will be modified > by the first split instruction and have the wrong value in the > second split instruction. See other ports for the canonical way > of handling this. Thanks for the heads up. Could you point me to a specific target/file? Best regards, -Omar
Re: splitting const_int's
Richard Sandiford wrote: > "Omar Torres" <[EMAIL PROTECTED]> writes: > More importantly: > >>operands[4] = simplify_gen_subreg(QImode,operands[1],HImode,0); >>operands[5] = simplify_gen_subreg(QImode,operands[1],HImode,1); > > ..this code is designed to handle REGs and CONST_INTs correctly, > and avoid the problem you were seeing. (As Eric says, gen_int_mode > is the canonical way of generating a correct CONST_INT in cases where > you do need to create one manually. In this case it's simpler to use > simplify_gen_subreg though.) Now, the insn: (insn 84 5 9 (set (reg:HI 1 %r3) (const_int 32767 [0x7fff])) 3 {*movhi} (nil) (nil)) get's split into (set (reg:QI 1 %r3) (const_int 127 [0x7f]) (set (reg:QI 2 %r2) (const_int -1 [0x]) and my movqi patter is able to match both of this patterns as expected. But, now the output asm is move %r2,#0x Instead of the expected: move %r2,#0xff I am not fully familiar with how to fix this, but seems like there are at least two ways of fixing this: 1- Detect the sign in the rtl template and manipulate the operand so that the asm value is outputted. That is, use something like this: (define_insn "movqi" [(set (match_operand:QI 0 "nonimmediate_operand" "=r,m") (match_operand:QI 1 "general_operand" "g,r"))] "" "* if (CONST_INT == GET_CODE (operands[1])) { if (0 > INTVAL(operands[1])) { fprintf (stderr, \"\nOperand 1 Value: %d, %d\", INTVAL (operands[1]),0xff & INTVAL (operands[1]) ); operands[1] = gen_rtx_CONST_INT (VOIDmode, 0xff & INTVAL (operands[1])); } } return \"move.a\t%0,%1\"; ") 2- Use a special letter in the asm template, to communicate with the print_operand() function. Is there any other way of doing this? If not, is there any advantage of using one option over the other above? Thanks, -Omar
Re: splitting const_int's
Richard Sandiford wrote: > Also, you need to beware of cases in which operands[1] overlaps > operands[0]. The splitter says: > > [(set (match_dup 2) (match_dup 4)) > (set (match_dup 3) (match_dup 5))] > > and operands[2] is always the highpart: > >operands[2] = gen_highpart(QImode, operands[0]); > > but consider the case in which operands[1] (and thus operands[4]) > is a memory reference that uses the high part of operands[0] as > a base register. In that case, the base register will be modified > by the first split instruction and have the wrong value in the > second split instruction. See other ports for the canonical way > of handling this. > > Richard By looking at other ports, I learned that I can detect when this happens by using the reg_overlap_mentioned_p(). Here is one case: (insn 43 115 74 (set (reg:HI 7 %i0h) (mem/s/j:HI (plus:HI (reg/f:HI 7 %i0h [orig:39 source ] [39]) (const_int 2 [0x2])) [0 .r+0 S2 A8])) 3 {*movhi} (nil) (nil)) I need to tell the compiler not to use as destination the same base register when doing index operations. Any suggestions on how do I that? Thanks for your help. -Omar
How to post to GCC lists?
Dear All, I recently started working in a GCC backend, and as a result I expect to be actively participating in the ML. That said, I have questions on how to properly and efficiently do a post. I want to remove the annoyances that at the end just unnecessary waste everyone's time. 1- I noticed that when I reply to posts, the "References" are not preserved, which leads to messages in the same threat not to be linked together. I am using Thunderbird as my email client. When I go to View>Headers>All the References field looks accurate. Is there a trick to make this work? Should I use instead a different email client better suit for GCC ML? 2- Currently, (1) is the only thing I have run cross. I am sure there are other issues that those of you with more experience have already discovered and solve. Any other Dos/Don'ts or tips/tricks when posting to GCC ML? Thanks, -Omar
Re: Few question regarding the implementation of splitting HImode patterns
Mohamed Shafi wrote: > Hello Omar, > > I saw your mail to gcc mailing list regarding splitting of HImode > patterns into QImode patterns. I am also involved in porting. My > problem is similar to yours. But i have to split SImode patterns into > HImode patterns. > > I am sure that you have modified your define_split patterns after > receiving the suggestions from the mailing list. Could you just mail > me the finalized define_split pattern of HImode. > > One thing that i noticed in your split pattern is that you are not > handling cases where operand[0] is memory, i.e store patterns. How > are you handling this? Do you have a define_insn for this case? > > I hope you don't mind me asking these questions. > > Thank you for your time. > > Regards, > Shafi > > Hi Mohamed, I added the gcc mailing list to the threat. My current implementation looks like this: ;; movhi (define_expand "movhi" [(set (match_operand:HI 0 "nonimmediate_operand" "") (match_operand:HI 1 "general_operand" ""))] "" { if (c816_expand_move (HImode, operands)) { DONE; } }) ;; =&r creates an early clobber. ;; It prevent insn where the target register ;; is the same as the base register used for memory addressing... ;; This is needed so that the split produce correct code. (define_insn "*movhi" [(set (match_operand:HI 0 "nonimmediate_operand" "=&r,m") (match_operand:HI 1 "general_operand" "g,r"))] "" "#") (define_split [(set (match_operand:HI 0 "nonimmediate_operand" "") (match_operand:HI 1 "general_operand" ""))] "reload_completed" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] "{ gcc_assert (REG_P (operands[0]) || MEM_P (operands[0])); #ifdef DEBUG_OVERLAP if (reg_overlap_mentioned_p(operands[0], operands[1])){ fprintf (stderr, \"\nOperands Overlap:\n\"); debug_rtx (curr_insn); } #endif if (REG_P (operands[0])) { operands[2] = gen_highpart(QImode, operands[0]); operands[3] = gen_lowpart (QImode, operands[0]); } else if (MEM_P (operands[0])) { operands[2] = adjust_address (operands[0], QImode, 0); operands[3] = adjust_address (operands[0], QImode, 1); } if (MEM_P (operands[1])) {// || CONST == GET_CODE (operands[1])) { operands[4] = adjust_address (operands[1], QImode, 0); operands[5] = adjust_address (operands[1], QImode, 1); } else if (LABEL_REF == GET_CODE (operands[1]) || SYMBOL_REF == GET_CODE (operands[1])) {// operands[4] = simplify_gen_subreg(QImode, operands[1], HImode, 0); operands[5] = simplify_gen_subreg(QImode, operands[1], HImode, 1); } else if (CONST_INT == GET_CODE (operands[1]) || REG_P (operands[1])) { operands[4] = simplify_gen_subreg(QImode, operands[1], HImode, 0); operands[5] = simplify_gen_subreg(QImode, operands[1], HImode, 1); } else { error(\"Unrecognized code in operands[1]\"); fputs(\"\nrtx code is: \", stderr); debug_rtx(curr_insn); abort(); } }") The purpose of the expand is to load Label or Symbol references into base registers for index addressing. I decided to use the expand since the force_reg() was failing when I called from the split. The c816_expand_move() is implemented as follows: bool c816_expand_move (enum machine_mode mode, rtx *operands) { if (!no_new_pseudos) { int i; for (i = 0; i < 2; i++) { if (MEM_P (operands[i]) || CONST == GET_CODE (operands[i])) { rtx base = XEXP (operands[i],0); if (CONST == GET_CODE(base)) { base = XEXP (base,0); } if (PLUS == GET_CODE (base)) { rtx off = XEXP (base,1); base = XEXP (base,0); if (SYMBOL_REF == GET_CODE (base) || LABEL_REF == GET_CODE (base)) { rtx newreg = force_reg (Pmode, base); operands[i] = gen_rtx_MEM (mode, gen_rtx_PLUS (Pmode, newreg, off)); } } else if (SYMBOL_REF == GET_CODE (base) || LABEL_REF == GET_CODE(base)) { rtx newreg = force_reg (Pmode, base); operands[i] = gen_rtx_MEM (mode, newreg); } }// if MEM_P }// for }// if !no_new_pseudos return false; } In your case, you might want to look at other gcc ports for 16-bit machines. One I have look from time to time is the MSP430 port (http://mspgcc.sourceforge.net/). Hope this helps. Good Luck, -Omar
insn does not satisfy its constraints
Hi All, I am getting the error message bellow while hacking my gcc backend. Any suggestions on how to fix this? error: insn does not satisfy its constraints: (insn 25 50 26 2 (set (reg:HI 1 %r0 [33]) (plus:HI (mem/s/j:HI (plus:HI (reg:HI 3 %r2) (reg/v/f:HI 11 %i2h [orig:28 cell ] [28])) [0 .dod S2 A8]) (reg:HI 1 %r0 [43]))) 8 {*addhi3} (insn_list:REG_DEP_TRUE 3 (insn_list:REG_DEP_TRUE 24 (nil))) (nil)) The md description for this instruction is: ;; addhi3 (define_expand "addhi3" [(set (match_operand:HI 0 "register_operand" "") (plus:HI (match_operand:HI 1 "cool_addhi_operand" "") (match_operand:HI 2 "cool_addhi_operand" "")))] "" "") (define_insn "*addhi3" [(set (match_operand:HI 0 "register_operand""=r ,r ,r") (plus:HI (match_operand:HI 1 "cool_addhi_operand" "%0 ,rim,r") (match_operand:HI 2 "cool_addhi_operand" "rim,0 ,r")))] "" { operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 1); operands[4] = simplify_gen_subreg (QImode, operands[0], HImode, 0); operands[5] = simplify_gen_subreg (QImode, operands[1], HImode, 1); operands[6] = simplify_gen_subreg (QImode, operands[1], HImode, 0); operands[7] = simplify_gen_subreg (QImode, operands[2], HImode, 1); operands[8] = simplify_gen_subreg (QImode, operands[2], HImode, 0); if (!which_alternative) return "ADD\t%3,%7\n\tADDC\t%4,%8"; else if (1 == which_alternative) return "ADD\t%3,%5\n\tADDC\t%4,%6"; else return "ADD\t%3,%5,%8\n\tADDC\t%4,%5,%8"; }) Regards, -Omar
Re: insn does not satisfy its constraints
shafi wrote: >Operand 0 is a register >Operand 1 is a memory >Operand 2 is a register > > >> The md description for this instruction is: >> >> ;; addhi3 >> (define_expand "addhi3" >> [(set (match_operand:HI 0 "register_operand" "") >> (plus:HI (match_operand:HI 1 "cool_addhi_operand" "") >> (match_operand:HI 2 "cool_addhi_operand" "")))] >> "" >> "") >> >> (define_insn "*addhi3" >> [(set (match_operand:HI 0 "register_operand""=r ,r ,r") >> (plus:HI (match_operand:HI 1 "cool_addhi_operand" "%0 ,rim,r") >> (match_operand:HI 2 "cool_addhi_operand" "rim,0 ,r")))] >> "" >> > >Do you have an option where operand 0 is reg and operand 1 is mem and > operand 2 is reg? > My purpose is to describe the three possible scenarios: 1) Operand 0 is a register Operand 1 is the same register as operand 0 Operand 2 is a register, immediate or memory 2) Operand 0 is a register Operand 1 is a register, immediate or memory Operand 2 is the same register as operand 0 3) Operand 0 is a register Operand 2 is a register Operand 3 is also a register >I am not sure what rim is for? > rim = is a short cut for r, m, i. I think is is allow to mix several constrains like this, right? Thanks, -Omar