}
}
+/* Return TRUE if the rouding mode is dynamic. */
+
+static bool
+riscv_dynamic_frm_mode_p (int mode)
+{
+ return mode == riscv_vector::FRM_DYN
+ || mode == riscv_vector::FRM_DYN_CALL
+ || mode == riscv_vector::FRM_DYN_EXIT;
+}
+
+/* Implement TARGET_MODE_CONFLUENCE. */
+
+static int
+riscv_mode_confluence (int entity, int mode1, int mode2)
+{
+ switch (entity)
+ {
+ case RISCV_VXRM:
+ return VXRM_MODE_NONE;
+ case RISCV_FRM:
+ {
+ /* FRM_DYN, FRM_DYN_CALL and FRM_DYN_EXIT are all compatible.
+ Although we already try to set the mode needed to FRM_DYN after a
+ function call, there are still some corner cases where both FRM_DYN
+ and FRM_DYN_CALL may appear on incoming edges. */
+ if (riscv_dynamic_frm_mode_p (mode1)
+ && riscv_dynamic_frm_mode_p (mode2))
+ return riscv_vector::FRM_DYN;
+ return riscv_vector::FRM_NONE;
+ }
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* Return TRUE that an insn is asm. */
static bool
#define TARGET_MODE_EMIT riscv_emit_mode_set
#undef TARGET_MODE_NEEDED
#define TARGET_MODE_NEEDED riscv_mode_needed
+#undef TARGET_MODE_CONFLUENCE
+#define TARGET_MODE_CONFLUENCE riscv_mode_confluence
#undef TARGET_MODE_AFTER
#define TARGET_MODE_AFTER riscv_mode_after
#undef TARGET_MODE_ENTRY
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gcv -mabi=lp64 -ffast-math" } */
+
+struct ac {
+ ~ac();
+ void u();
+};
+struct ae {
+ int s;
+ float *ag;
+};
+
+float c;
+
+void ak(ae *al, int n) {
+ ac d;
+ for (int i;i<n;++i) {
+ float a = 0;
+ for (long j; j < al[i].s; j++)
+ a += al[i].ag[j];
+ c = a;
+ d.u();
+ }
+}
+
+/* { dg-final { scan-assembler-not "frrm\t" } } */
+/* { dg-final { scan-assembler-not "fsrm\t" } } */