On Fri, May 20, 2011 at 4:39 PM, Georg-Johann Lay <a...@gjlay.de> wrote:
> Ilya Lesokhin schrieb: > > On Thu, May 19, 2011 at 6:43 PM, Georg-Johann Lay <a...@gjlay.de> wrote: > > > >> Ilya Lesokhin schrieb: > >> > >> Hi, > >>> I would like to split a movhi instruction from an immediate to a const > >>> address to 2 movqi instructions. > >>> (I'm using gcc 4.5.3 but i dont think it matters in this case) > >>> > >> The current development version is 4.7.0. > >> > >> It won't help to provida a patch against an old version. So you need an > >> up-to-date version anyway. This includes also the testsuite. Patches > must > >> pass the testsuite without regressions. > >> > >> > > > > I'm doing it for myself at the moment, i dont think i've reached the > stage i > > can contribute to the mainline branch yet, So i dont really care what the > > development branch is. > > > > > >> My motivation is the following: > >>> Code in the form: > >>> OCR2RA = 1; > >>> > >>> compiles to: > >>> > >>> ldi r24, 0x01 ; 1 > >>> ldi r25, 0x00 ; 0 > >>> sts 0x00F7, r25 > >>> sts 0x00F6, r24 > >>> > >>> instead of > >>> > > > > ldi r24, 0x01 ; 1 > > sts 0x00F7, __zero_reg__ > > sts 0x00F6, r24 > > > > > > > >> I'm pretty sure its caused by the following code: > >>> (define_expand "movhi" > >>> [(set (match_operand:HI 0 "nonimmediate_operand" "") > >>> (match_operand:HI 1 "general_operand" ""))] > >>> "" > >>> " > >>> { > >>> /* One of the ops has to be in a register. */ > >>> if (!register_operand(operand0, HImode) > >>> && !(register_operand(operand1, HImode) || const0_rtx == operands[1])) > >>> { > >>> operands[1] = copy_to_mode_reg(HImode, operand1); > >>> } > >>> }") > >>> > >>> i would like to fix it but i know very little about gcc internals. > >>> > >>> i tried to do something like: > >>> > >>> (define_expand "movhi" > >>> [(set (match_operand:HI 0 "nonimmediate_operand" "") > >>> (match_operand:HI 1 "general_operand" ""))] > >>> "" > >>> " > >>> { > >>> rtx base = XEXP (operands[0], 0); > >>> if (GET_CODE (operands[1]) == CONST_INT > >>> && CONSTANT_ADDRESS_P (base)) > >>> { > >>> short value = INTVAL (operands[1]); > >>> short address = INTVAL (base); > >>> > >> base is a constant, but not necessarily a CONST_INT, it can also be a > >> SYMBOL_REF or a CONST. If you add support for storing zero-extended > values, > >> I see no reason why to excluse some flavours of address. > > > >> emit_move_insn(gen_rtx_MEM(QImode,address+1), GEN_INT(value >> 8)); > >>> emit_move_insn(gen_rtx_MEM(QImode,address), GEN_INT(value & 0xff)); > >>> > >> address+1 is wrong, because address in general is not a CONST_INT > >> Maybe plus_constant is what you looking for. > >> > > > > OK, thank you for pointing those things out. > > > >> Moreover, there is no point in expanding some stuff if there is no insn > >> that will handle it. > >> > >> > > it seems its handles correcly by movqi and other relevet patterns. > > That's because splitting a volatile mem is not appropriate. You would > have to volatile QI accesses instead of one volatile HI access. This > means the two parts could move far away from each other. GCC is > conservative about volatiles, so should be a backend. > i haven't thought about that, thank you. i just noticed that writing: OCR2RAH= 0; OCR2RAL=1; generates better code, and i thought its better the compiler handles it, rather then making the code uglier. but as i now see it doesn't guarantee the right behavior with respect to volatile. > >> DONE; > >>> } > >>> else /* One of the ops has to be in a register. */ > >>> if (!register_operand(operand0, HImode) > >>> && !(register_operand(operand1, HImode) || const0_rtx == operands[1])) > >>> { > >>> operands[1] = copy_to_mode_reg(HImode, operand1); > >>> } > >>> }") > >>> > >>> but then i get Segmentation fault when trying to compile code. > >>> > >> You move expansion cannot work because you need at least a QI register > >> (except in the case when you like to store 0, which is already handled > in > >> the implementation. > >> > >> Presumably, you want code like this: > >> > >> (set (reg:QI n) > >> (const_int m)) > >> (set (mem:HI (const_addr:P)) > >> (zero_extend:HI (reg:QI n))) > >> > >> You can do it in expand, but note that expand is called at different > stages > >> of compilation. You need an intermediate register, so you must be sure > you > >> can actually get one, i.e. can_create_pseudo_p is true. > >> > >> As an alternative, you can hook in after insn combine. > >> combine will synthesize such insns, so you can supply a combiner pattern > >> that matches and split it prior to register allocation by means of a > split > >> pattern. > >> > >> Yet an other alternative is to extend zero_extendqihi to accept memory > >> operand in dest. Note that there is different handlich for volatiles. > > > > > > i belive that spliting the instruction into 2 instractions is supperior > > No, splitting a volatile access is not appropriate. > > > since its also hadles the cases where the low byte is zero or when the > low > > byte and the high byte are equal as suppose to zero_extend. > > I don't think it's a point trading marginal efficiency against > volatile correctness. > > So an implementation will look like this: > > In movhi expander: > > if (optimize > && can_create_pseudo_p() > && MEM_P (operands[0]) > && satisfies_constraint_M (operands[1]) > && const0_rtx != operands[1]) > { > rtx val = GEN_INT (trunc_int_for_mode (INTVAL (operands[1], QImode)); > rtx reg = copy_to_mode_reg (QImode, val); > emit_insn (gen_store_zeroextendqihi2 (operands[0], reg); > DONE; > } > > And > > (define_insn "store_zeroextendqihi2" > [(set (match_operand:HI 0 "memory_operand" "=Qm") > (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))] > "" > { > return out_movhi_mr_zerox_r (insn, operands, NULL); > }) > > where out_movhi_mr_zerox_r is similar to out_movhi_mr_r but adapted > for your purposes. > > Moreover, you will have to fix length computation in adjust_insn_length. > > This approach is appropriate for volatile mems, too. And it does not > make restrictions to the address involved. Why exclude indirect > addressing...? > > i wanted to exclude indirect addressing since splitting in that case may generate worse code because then the compiler wont be able to use post-increment/pre-decrement, but as you've kindly explained splitting is not the right solution :( > > also what do you mean by handlich for volatiles? > > > > > > anyway, thanks for all your help, you've been the most helpful so far. > > > > unfortently, the task seems alot more complicated the i first thought. > > Yes, that's GCC. Don't say you didn't know before ;-) > > > OCR0SA = 1u; > > is at first converted to and indirect memory acces: > > ... > > (const_int 1 [0x1])) -1 (nil)) > > (set (mem/v:HI (reg/f:HI 43) [2 S2 A8]) > > (reg:HI 44)) -1 (nil)) > > > > and only after the IRA phase its converted to something with a const > address > > ... > > (set (mem/v:HI (const_int 210 [0xd2]) [2 S2 A8]) > > (reg:HI 24 r24 [44])) 10 {*movhi} (expr_list:REG_EQUAL (const_int 1 > > [0x1] (nil))) > > It's a (post)reload optimization. > when i used -fdump-rtl-all i got the impression form the numbering of the files that the IRA phase is before reload, did i get the convention wrong? also i wont be able to use copy_to_mode_reg(...) after reload, right? so i cant do it after reload even if i wanted to. > > which is the form that i tried to fix. so i think ill have to try > > a different approch. > > I already explained why doing it post-reload is inferior and rather a > last-resort hack. > > Johann > i still want to handle the case where the low byte is zero, so i'm thinking its better to create a pattern that receives a HI memory operand and 2 QI reg operands, and the movhi expander will just use this pattern sending zero_reg or copy_to_mode_reg(...) according to the value. do you see a problem with this solution? also the costs of copy_to_mode_reg(...) are calculated when the value is moved to the reg, right? so my new pattern wont have to care if the argument it gets i a zero reg or a different reg. thanks again for all your help.
_______________________________________________ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org https://lists.nongnu.org/mailman/listinfo/avr-gcc-list