A problem with LRA

2017-04-17 Thread comp

Hi all,
I recently have a problem with LRA.
1 The Bug use case
int a=10;
float c=2.0,d;
main()
{
        float b;
        *(int*)&b=a;
        d=b+c;
}
 
2 The problem description
In the pass LRA, curr_insn_transform () deal with the addition statement d = b 
+ c, the corresponding rtx expression in register allocation is as follows:
(gdb) pr curr_insn
(insn 9 8 10 2 (set (reg:SF 73 [ d ])
        (plus:SF (reg:SF 79 [ c ])
            (subreg:SF (reg:SI 77 [ a ]) 0))) test.c:7 121 {addsf3}
     (expr_list:REG_DEAD (reg:SF 79 [ c ])
        (expr_list:REG_DEAD (reg:SI 77 [ a ])
            (nil
The corresponding addsf3 template in the .md file is defined as follows:
(define_insn "add3"
  [(set (match_operand:FMODE 0 "register_operand" "=f")
        (plus:FMODE (match_operand:FMODE 1 "reg_or_0_operand" "%fG")
                    (match_operand:FMODE 2 "reg_or_0_operand" "fG")))]
  "TARGET_FP"
  "fadd%/ %R1,%R2,%0"
  [(set_attr "type" "fadd"))
 
curr_insn_transform() calls process_alt_operands() for matching constraints, 
the matching of operands 0, 1, and 2 are all successful, where the main 
matching processes of the second operand, i.e.(subreg: SF (reg: SI 77 [a]) 0) 
are as follows:
op = no_subreg_reg_operand[nop], where nop=2;
Here get op: (reg:SI 77 [ a ])
mode = curr_operand_mode[nop];
Here get mode: SFmode
cl = reg_class_for_constraint (cn)
Here get cn: CONSTRAINT_f£¬and cl:FLOAT_REGS
 
FLOAT_REGS is defined as the ability to allocate all hard registers in the 
REG_CLASS_CONTENTS macro that describes the processor¡¯s registers in the 
machine description. so that the matching key function in_hard_reg_set_p 
(this_alternative_set, mode, hard_regno [nop]) returns true, where psudo reg 77 
is assigned $1 hard reg in the pass IRA.i.e. hard_regno[nop]=1. The hardware 
register $1 belongs to FLOAT_REGS and also belongs to GENERAL_REGS, but it was 
derived from the integer a, so the before matched instruction that generated $1 
as the destination register is an integer kind load instruction ldw. Thus the d 
= b + c statement generates the instruction:
fadds $ 48, $ 1, $ 48, where c is assigned to $48, b is assigned to $1, and the 
result d lies in $48. The result is the following instructions:
ldw $1,a($1)
flds $48,c($2)
fadds $48,$1,$48
The problem lies in the second source operand of the floating-point addition 
fadds instruction , $48 is obtained by floating-point load instruction flds, 
but $1 is obtained by the integer load instruction ldw, so the result is wrong, 
we hope that the process_alt_operands() results a match failure, and a reload 
may generate that turns ldw to flds instruction.
 
3 The comparative test
In contrast, if the $1 in the REG_CLASS_CONTENTS register category is defined 
as not belonging to FLOAT_REGS, the above process_alt_operands () returns false 
when the second operand is matched(in_hard_reg_set_p (this_alternative_set, 
mode, hard_regno [nop]) returns fail), and so a reload is triggered, an ifmovs 
instruction will generate to move the contents of the integer register to the 
floating point register. the following instructions is correct:
ldw $1,a($1)
flds $f11,c($2)
ifmovs $1,$f10
fadds $f11,$f10,$f11
 
Thanks.

Re:Re: A problem with LRA

2017-04-23 Thread comp
It does not work when -fno-strict-aliasing is specified.
At 2017-04-18 21:02:45, "Segher Boessenkool"  wrote:
>Hi,
>
>On Mon, Apr 17, 2017 at 09:11:56PM +0800, comp wrote:
>>         float b;
>>         *(int*)&b=a;
>
>This is undefined behaviour.  Try with -fno-strict-aliasing, does it
>then work as you expect?
>
>
>Segher


Re:RE: A problem with LRA

2017-04-23 Thread comp
a unified hard register set 0~63 is permitted to hold either interger or float 
value.Thanks.
At 2017-04-18 21:45:54, "Matthew Fortune"  wrote:
>comp  writes:
>> Hi all,
>> I recently have a problem with LRA.
>> 1 The Bug use case
>> int a=10;
>> float c=2.0,d;
>> main()
>> {
>>         float b;
>>         *(int*)&b=a;
>>         d=b+c;
>> }
>> 
>> 2 The problem description
>> In the pass LRA, curr_insn_transform () deal with the addition statement d = 
>> b + c, the
>> corresponding rtx expression in register allocation is as follows:
>> (gdb) pr curr_insn
>> (insn 9 8 10 2 (set (reg:SF 73 [ d ])
>>         (plus:SF (reg:SF 79 [ c ])
>>             (subreg:SF (reg:SI 77 [ a ]) 0))) test.c:7 121 {addsf3}
>>      (expr_list:REG_DEAD (reg:SF 79 [ c ])
>>         (expr_list:REG_DEAD (reg:SI 77 [ a ])
>>             (nil
>> The corresponding addsf3 template in the .md file is defined as follows:
>> (define_insn "add3"
>>   [(set (match_operand:FMODE 0 "register_operand" "=f")
>>         (plus:FMODE (match_operand:FMODE 1 "reg_or_0_operand" "%fG")
>>                     (match_operand:FMODE 2 "reg_or_0_operand" "fG")))]
>>   "TARGET_FP"
>>   "fadd%/ %R1,%R2,%0"
>>   [(set_attr "type" "fadd"))
>> 
>> curr_insn_transform() calls process_alt_operands() for matching constraints, 
>> the matching
>> of operands 0, 1, and 2 are all successful, where the main matching 
>> processes of the
>> second operand, i.e.(subreg: SF (reg: SI 77 [a]) 0) are as follows:
>> op = no_subreg_reg_operand[nop], where nop=2;
>> Here get op: (reg:SI 77 [ a ])
>> mode = curr_operand_mode[nop];
>> Here get mode: SFmode
>> cl = reg_class_for_constraint (cn)
>> Here get cn: CONSTRAINT_f£¬and cl:FLOAT_REGS
>> 
>> FLOAT_REGS is defined as the ability to allocate all hard registers in the
>> REG_CLASS_CONTENTS macro that describes the processor¡¯s registers in the 
>> machine
>> description. so that the matching key function in_hard_reg_set_p 
>> (this_alternative_set,
>> mode, hard_regno [nop]) returns true, where psudo reg 77 is assigned $1 hard 
>> reg in the
>> pass IRA.i.e. hard_regno[nop]=1. The hardware register $1 belongs to 
>> FLOAT_REGS and also
>> belongs to GENERAL_REGS, but it was derived from the integer a, so the 
>> before matched
>> instruction that generated $1 as the destination register is an integer kind 
>> load
>> instruction ldw. Thus the d = b + c statement generates the instruction:
>> fadds $ 48, $ 1, $ 48, where c is assigned to $48, b is assigned to $1, and 
>> the result d
>> lies in $48. The result is the following instructions:
>> ldw $1,a($1)
>> flds $48,c($2)
>> fadds $48,$1,$48
>> The problem lies in the second source operand of the floating-point addition 
>> fadds
>> instruction , $48 is obtained by floating-point load instruction flds, but 
>> $1 is obtained
>> by the integer load instruction ldw, so the result is wrong, we hope that the
>> process_alt_operands() results a match failure, and a reload may generate 
>> that turns ldw
>> to flds instruction.
>
>Isn't this a CANNOT_CHANGE_MODE_CLASS issue then? I.e. don't allow it to be 
>reinterpreted
>from integer mode to floating point mode.
>
>> 3 The comparative test
>> In contrast, if the $1 in the REG_CLASS_CONTENTS register category is 
>> defined as not
>> belonging to FLOAT_REGS, the above process_alt_operands () returns false 
>> when the second
>> operand is matched(in_hard_reg_set_p (this_alternative_set, mode, hard_regno 
>> [nop])
>> returns fail), and so a reload is triggered, an ifmovs instruction will 
>> generate to move
>> the contents of the integer register to the floating point register. the 
>> following
>> instructions is correct:
>> ldw $1,a($1)
>> flds $f11,c($2)
>> ifmovs $1,$f10
>> fadds $f11,$f10,$f11
>
>This is not consistent with the previous example code as the floating point 
>registers now
>have 'f' prefixes but did not before.
>
>You will need to explain more about what registers are available and how they 
>can be used
>(or not as the case may be).
>
>If this issue ends up anywhere near subreg handling inside LRA then please 
>keep me on CC. I
>think this is likely to just be a backend issue from the description so far 
>though.
>
>Thanks,
>Matthew