[RFC] When adding an offset to a lo_sum containing a symbol, check it is in range of the symbol's alignment
Hi, In MIPS (and similarly for other RISC architectures) to load an absolute address of an object requires a two instruction sequence: one instruction to load the high part of the object's address, and one instruction to load the low part of the object's address. Typically the result from the calculation of the high part of the address will only be used by one instruction to load the low part of the address. However, in certain situations (for example when loading or storing double word values) the result of computing the high part of the address can be used by multiple instructions to load the low parts of an address at different offsets. Lets show this with an example C program. struct { short s; unsigned long long l; } h; void foo (void) { h.l = 0; } When this is compiled for MIPS it produces the following assembly: lui $2,%hi(h+8) sw $0,%lo(h+8)($2) jr $31 sw $0,%lo(h+12)($2) ... .globl h .section.bss,"aw",@nobits .align 3 .type h, @object .size h, 16 h: .space 16 Notice here that the high part of the address of object h is loaded into register $2, and this is then used as part of the low part calculation by two the sw instructions which each have different offsets. In MIPS the value of a low part calculation is treated as a signed value. It is therefore valid to use the result of a high part calculation with multiple low part calculations containing different offsets so long as when adding the result of the high part to the each of the sign extended low parts we get valid addresses. However, if we add the packed attribute to the h structure, the fields of the structure will not be naturally aligned and we can break the previous condition. Lets explain this in more detail with the following C program. struct __attribute__((packed)) { short s; unsigned long long l; } h; void foo (void) { h.l = 0; } When this is compiled for MIPS it produces the following assembly: lui $2,%hi(h) addiu $4,$2,%lo(h+2) addiu $3,$2,%lo(h+6) swl $0,3($4) swr $0,%lo(h+2)($2) swl $0,3($3) jr $31 swr $0,%lo(h+6)($2) ... .globl h .section.bss,"aw",@nobits .align 2 .type h, @object .size h, 10 h: .space 10 There are two things to highlight here. Firstly the alignment of the h structure has decreased from 8 bytes to 4 bytes. Secondly we have a low part calculation which adds an offset of 6 to the address of the h structure which is greater than its alignment. When the MIPS linker resolves a HI relocation (i.e. %hi(h)) it finds the next LO relocation (i.e. %lo(h+2)) in the relocation table and using the information from both of these relocations it computes the object's address and extracts its high part. Then, when the MIPS linker resolves a LO relocation it adds the offset to the object's address and then extracts the low part. Lets assume that object h has an address of 0x80007ffc. When the MIPS linker resolves the value of the HI relocation for object h, it will also use the value of the LO relocation for object h with an offset of 2. The high part value is therefore: HIGH (0x80007ffc + 2) = HIGH (0x80007ffe) = 0x8000 Then the MIPS linker resolves the value of LO relocation for object h with an offset of 2: LO (0x80007ffc + 2) = LO (0x80007ffe) = 0x7ffe Finally the MIPS linker resolves the value of the LO relocation for object h with an offset of 6: LO (0x80007ffc + 6) = LO (0x80008002) = 0x8002 In MIPS the value of a LO relocation is treated as a signed value, so when the program is run the address of h+6 will be 0x7fff8002 when it should be 0x80008002. The place in the GCC middle end where the invalid RTX is generated is in the adjust_address_1 function in emit-rtl.c, when it adjusts the offset of an address which is a MEM rtx containing a LO_SUM, by producing a new LO_SUM containing the offset. In the case where the original LO_SUM contains a SYMBOL_REF this is only valid if the alignment of the object is less than the offset. The potential fix (shown below) is to perform this check. Before I produce a formal patch and testcase for this issue I wanted to discuss it with the GCC community to ensure this is the best place to fix such a problem. So, if required please feel free to suggest improvements or other more appropriate places to apply this fix. Many thanks, Andrew diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 3041b9e..b20de6f 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -2036,12 +2036,30 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset, if (adjust_address) { + unsigned HOST_WIDE_INT symbol_alignment; + + symbol_alignment = GET_MODE_ALIGNMENT (GET_MODE (memref)) /
RE: [RFC] When adding an offset to a lo_sum containing a symbol, check it is in range of the symbol's alignment
> It almost sounds like you need to be preventing the compiler from > considering a lo_sum (whatever) as an offsettable memory address when > the underlying object has had its alignment decreased from its natural > alignment. > > I wouldn't be at all surprised if you do this you won't see the calls > into adjust_address_1 occurring in the first place. This would be a little heavy handed as the issue only happens in the case where a high part calculation is used by multiple low part calculations. So far I have found that this happens when we have to lower a DI mode load/store into two SI mode load/stores where different offsets are applied to each load/store. I have found a case in the MIPS backend where this occurs, and also when we are expanding a bitfield load/store to RTL, but I am sure there are others. My worry is that it could be hard to track down all cases that generate invalid lo_sums, and therefore it could be easier to just perform the fixup in adjust_address_1. Regards, Andrew
RE: Autotuning parameters/heuristics within gcc - best place to start?
> -Original Message- > From: gcc-ow...@gcc.gnu.org [mailto:gcc-ow...@gcc.gnu.org] On Behalf Of Gary > Funck > Sent: 28 September 2014 20:02 > To: Andi Kleen > Cc: Robert Stevenson; gcc@gcc.gnu.org > Subject: Re: Autotuning parameters/heuristics within gcc - best place to > start? > > On 09/26/14 07:47:05, Andi Kleen wrote: > > One example of an existing autotuner is the gccflags tuner in opentuner. > > Although dated, ACOVEA might offer up some ideas. > http://stderr.org/doc/acovea/html/acovea_4.html The Milepost project might also be of interest: http://ctuning.org/wiki/index.php/CTools:MilepostGCC Regards, Andrew
RE: gcc testsuite
> 3. To run the testsuite :- sourcedir.../gcc-4.4.5/gcc > make check > > It generates lot of failures What kind of failures are you seeing? If possible could you have a look at the *.log files in the testsuite directory and summarise the errors you are seeing. > Thanks & regards > Mappy Many thanks, Andrew
RE: gcc testsuite
> Hi, > These kinds of failures > This failure is repeating again and again > > FAIL: gcc.c-torture/compile/990625-1.c -O0 (test for excess errors) > Excess errors: > /home/ash/rpm-root/packages/BUILD/gcc-4.4.5/gcc/testsuite/gcc.c- > torture/compile/990625-1.c:2:20: > error: string.h: No such file or directory > > I have also attached the log file with this mail. > > Please find the attachment for gcc.log and also site.exp It looks like you have not built and installed a C library for your target (which looks like PowerPC). I would check that newlib is in the GCC source directory, and that it has been correctly built. Regards, Andrew
RE: gcc testsuite
> Hi, >I couldn't find newlib in my source gcc-4.5.5 directory. I download > and try to install it, i think it is not completed > when i run make install ...it ends quickly with the message shown below > > make[2]: Leaving directory /gcc-4.4/build_newlib/etc' > make[1]: Nothing to be done for `install-target' I would check that firstly you have placed the newlib source directory within the root of the gcc source tree, and secondly that it is called newlib. Then try running make (you might have to re-configure again) from where you built gcc originally. Regards, Andrew
Is the check performed on the return value from force_const_mem in the plus_constant function correct?
Hi, I am debugging a segmentation fault when compiling some code for MIPS. The segmentation fault occurs in the plus_constant function in explow.c when it tries to update a constant pool value. The offending code is below: case MEM: /* If this is a reference to the constant pool, try replacing it with a reference to a new constant. If the resulting address isn't valid, don't return it because we have no way to validize it. */ if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0))) { tem = plus_constant (mode, get_pool_constant (XEXP (x, 0)), c); tem = force_const_mem (GET_MODE (x), tem); if (memory_address_p (GET_MODE (tem), XEXP (tem, 0))) return tem; } The code fails for MIPS because its cannot_force_const_mem target function does not allow constants (so that the move expanders can deal with them later on), this then causes the force_const_mem function to return a NULL_RTX. What I can't understand is why the memory_address_p function is used to check the result from force_const_mem? From looking at the return values from force_const_mem the only possibilies are what looks like a valid memory rtx, or a NULL_RTX. Also there is no other instances in the code where this happens. I was therefore wondering is anyone knew why the check is done in this manner? I think the fix should be to just check that the tem variable is not a NULL_RTX. I was also wondering if anyone had any issues/objections to checking the result in this manner? Many thanks, Andrew
RE: mips64vr-elf fails to build
Hi Nick, Many thanks for reporting this. This has previously been reported as pr56942 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56942). A patch has been submitted to fix this. Please see: http://gcc.gnu.org/ml/gcc-patches/2013-04/msg01173.html. Regards, Andrew > -Original Message- > From: gcc-ow...@gcc.gnu.org [mailto:gcc-ow...@gcc.gnu.org] On Behalf Of > Nick Clifton > Sent: 21 April 2013 12:08 > To: echri...@gmail.com; rdsandif...@googlemail.com > Cc: gcc@gcc.gnu.org > Subject: mips64vr-elf fails to build > > Hi Eric, Hi Richard, > > The mips64vr-elf target currently fails to build in FSF mainline > because: > > libgcc/unwind-dw2.c:1159:1: internal compiler error: in output_555, at > config/mips/mips.md:6024 > > which is here: > > (define_insn "casesi_internal_mips16_" > [(set (pc) >(if_then_else > (leu (match_operand:SI 0 "register_operand" "d") > (match_operand:SI 1 "arith_operand" "dI")) > (unspec:P > [(match_dup 0) > (label_ref (match_operand 2 "" ""))] > UNSPEC_CASESI_DISPATCH) > (label_ref (match_operand 3 "" "" > (clobber (match_scratch:P 4 "=d")) > (clobber (match_scratch:P 5 "=d")) > (clobber (reg:SI MIPS16_T_REGNUM))] > "TARGET_MIPS16_SHORT_JUMP_TABLES" > { > rtx diff_vec = PATTERN (next_real_insn (operands[2])); > > => gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); > > I am not sure of the best way to fix this, so I am punting to you > guys. :-) > > Cheers > Nick >
Changing the MIPS ISA for the Loongson 3A from MIPS64 to MIPS64r2
Hi, I have noticed that a patch was placed in bugzilla to do this change, but it does not appear to have been pushed. I was wondering if anyone could comment why this is the case? The bugzilla URL is the following: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57754 Many thanks, Andrew Andrew Bennett Software Design Engineer, MIPS Processor IP Imagination Technologies Limited t: +44 (0)113 2429814 www.imgtec.com