df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
FOR_EACH_INSN_INFO_DEF (def, insn_info)
- /* If the def is to only part of the reg, it does
- not kill the other defs that reach here. */
- if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
- {
- unsigned int dregno = DF_REF_REGNO (def);
- bitmap_set_bit (&bb_info->def, dregno);
+ {
+ /* If the definition is to only part of the register, it will
+ usually have a corresponding use. For example, stores to one
+ word of a multiword register R have both a use and a partial
+ definition of R.
+
+ In those cases, the LR confluence function:
+
+ IN = (OUT & ~DEF) | USE
+
+ is unaffected by whether we count the partial definition or not.
+ However, it's more convenient for consumers if DEF contains
+ *all* the registers defined in a block.
+
+ The only current case in which we record a partial definition
+ without a corresponding use is if the destination is the
+ multi-register subreg of a hard register. An artificial
+ example of this is:
+
+ (set (subreg:TI (reg:V8HI x0) 0) (const_int -1))
+
+ on AArch64. This is described as a DF_REF_PARTIAL
+ definition of x0 and x1 with no corresponding uses.
+ In previous versions of GCC, the instruction had no
+ effect on LR (that is, LR acted as though the instruction
+ didn't exist).
+
+ It seems suspect that this case is treated differently.
+ Either the instruction should be a full definition of x0 and x1,
+ or the definition should be treated in the same way as other
+ partial definitions, such as strict_lowparts or subregs that
+ satisfy read_modify_subreg_p.
+
+ Fortunately, multi-register subregs of hard registers should
+ be rare. They should be folded into a plain REG if the target
+ allows that (as AArch64 does for example above).
+
+ Here we treat the cases alike by forcing a use even in the rare
+ case that no DF_REF_REG_USE is recorded. That is, we model all
+ partial definitions as both a use and a definition of the
+ register. */
+ unsigned int dregno = DF_REF_REGNO (def);
+ bitmap_set_bit (&bb_info->def, dregno);
+ if (DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL))
+ bitmap_set_bit (&bb_info->use, dregno);
+ else
bitmap_clear_bit (&bb_info->use, dregno);
- }
+ }
FOR_EACH_INSN_INFO_USE (use, insn_info)
/* Add use to set of uses in this BB. */
--- /dev/null
+/* { dg-additional-options "-O -fdump-rtl-cse1-all" } */
+
+__int128 __RTL (startwith ("vregs")) foo (void)
+{
+(function "foo"
+ (insn-chain
+ (block 2
+ (edge-from entry (flags "FALLTHRU"))
+ (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (cnote 2 NOTE_INSN_FUNCTION_BEG)
+ (cinsn 3 (set (subreg:TI (reg:V8HI x0) 0) (const_int -1)))
+ (edge-to exit (flags "FALLTHRU"))
+ )
+ )
+ (crtl (return_rtx (reg/i:TI x0)))
+)
+}
+
+/* { dg-final { scan-rtl-dump {(?n)lr *def.*\[x0\].*\[x1\]} cse1 } } */