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 "add<mode>3"
[(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<modesuffix>%/ %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.