From: Juzhe-Zhong <juzhe.zh...@rivai.ai> PR 108270
Fix bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108270. Consider the following testcase: void f (void * restrict in, void * restrict out, int l, int n, int m) { for (int i = 0; i < l; i++){ for (int j = 0; j < m; j++){ for (int k = 0; k < n; k++) { vint8mf8_t v = __riscv_vle8_v_i8mf8 (in + i + j, 17); __riscv_vse8_v_i8mf8 (out + i + j, v, 17); } } } } Compile option: -O3 Before this patch: mv a7,a2 mv a6,a0 mv t1,a1 mv a2,a3 vsetivli zero,17,e8,mf8,ta,ma ... After this patch: mv a7,a2 mv a6,a0 mv t1,a1 mv a2,a3 ble a7,zero,.L1 ble a4,zero,.L1 ble a3,zero,.L1 add a1,a0,a4 li a0,0 vsetivli zero,17,e8,mf8,ta,ma ... It will produce potential bug when: int main () { vsetivli zero, 100,..... f (in, out, 0,0,0) asm volatile ("csrr a0,vl":::"memory"); // Before this patch the a0 is 17. (Wrong). // After this patch the a0 is 100. (Correct). ... } gcc/ChangeLog: * config/riscv/riscv-vsetvl.cc (vector_infos_manager::all_empty_predecessor_p): New function. (pass_vsetvl::backward_demand_fusion): Fix bug. * config/riscv/riscv-vsetvl.h: New function declare. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/vsetvl/imm_bb_prop-1.c: Adapt test. * gcc.target/riscv/rvv/vsetvl/imm_conflict-3.c: Adapt test. * gcc.target/riscv/rvv/vsetvl/pr108270.c: New test. --- gcc/config/riscv/riscv-vsetvl.cc | 24 +++++++++++++++++++ gcc/config/riscv/riscv-vsetvl.h | 2 ++ .../riscv/rvv/vsetvl/imm_bb_prop-1.c | 2 +- .../riscv/rvv/vsetvl/imm_conflict-3.c | 4 ++-- .../gcc.target/riscv/rvv/vsetvl/pr108270.c | 19 +++++++++++++++ 5 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr108270.c diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc index b5f5301ea43..4948e5d4c5e 100644 --- a/gcc/config/riscv/riscv-vsetvl.cc +++ b/gcc/config/riscv/riscv-vsetvl.cc @@ -2361,6 +2361,21 @@ vector_infos_manager::all_same_ratio_p (sbitmap bitdata) const return true; } +bool +vector_infos_manager::all_empty_predecessor_p (const basic_block cfg_bb) const +{ + hash_set<basic_block> pred_cfg_bbs = get_all_predecessors (cfg_bb); + for (const basic_block pred_cfg_bb : pred_cfg_bbs) + { + const auto &pred_block_info = vector_block_infos[pred_cfg_bb->index]; + if (!pred_block_info.local_dem.valid_or_dirty_p () + && !pred_block_info.reaching_out.valid_or_dirty_p ()) + continue; + return false; + } + return true; +} + bool vector_infos_manager::all_same_avl_p (const basic_block cfg_bb, sbitmap bitdata) const @@ -3118,6 +3133,14 @@ pass_vsetvl::backward_demand_fusion (void) if (!backward_propagate_worthwhile_p (cfg_bb, curr_block_info)) continue; + /* Fix PR108270: + + bb 0 -> bb 1 + We don't need to backward fuse VL/VTYPE info from bb 1 to bb 0 + if bb 1 is not inside a loop and all predecessors of bb 0 are empty. */ + if (m_vector_manager->all_empty_predecessor_p (cfg_bb)) + continue; + edge e; edge_iterator ei; /* Backward propagate to each predecessor. */ @@ -3131,6 +3154,7 @@ pass_vsetvl::backward_demand_fusion (void) continue; if (e->src->index == ENTRY_BLOCK_PTR_FOR_FN (cfun)->index) continue; + /* If prop is demand of vsetvl instruction and reaching doesn't demand AVL. We don't backward propagate since vsetvl instruction has no side effects. */ diff --git a/gcc/config/riscv/riscv-vsetvl.h b/gcc/config/riscv/riscv-vsetvl.h index 237381f7026..eec03d35071 100644 --- a/gcc/config/riscv/riscv-vsetvl.h +++ b/gcc/config/riscv/riscv-vsetvl.h @@ -450,6 +450,8 @@ public: /* Return true if all expression set in bitmap are same ratio. */ bool all_same_ratio_p (sbitmap) const; + bool all_empty_predecessor_p (const basic_block) const; + void release (void); void create_bitmap_vectors (void); void free_bitmap_vectors (void); diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/imm_bb_prop-1.c b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/imm_bb_prop-1.c index cd4ee7dd0d3..ed32a40f5e7 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/imm_bb_prop-1.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/imm_bb_prop-1.c @@ -29,4 +29,4 @@ void f (int8_t * restrict in, int8_t * restrict out, int n, int cond) } } -/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*5,\s*e8,\s*mf8,\s*tu,\s*m[au]} 1 { target { no-opts "-O0" no-opts "-g" no-opts "-funroll-loops" } } } } */ +/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*5,\s*e8,\s*mf8,\s*tu,\s*m[au]} 2 { target { no-opts "-O0" no-opts "-g" no-opts "-funroll-loops" } } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/imm_conflict-3.c b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/imm_conflict-3.c index 1f7c0f036a2..2fa29c01dbc 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/imm_conflict-3.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/imm_conflict-3.c @@ -20,7 +20,7 @@ void f (int8_t * restrict in, int8_t * restrict out, int n, int cond) } } -/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*5,\s*e8,\s*mf8,\s*tu,\s*m[au]} 1 { target { no-opts "-O0" no-opts "-g" no-opts "-funroll-loops" } } } } */ +/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*5,\s*e8,\s*mf8,\s*t[au],\s*m[au]} 2 { target { no-opts "-O0" no-opts "-g" no-opts "-funroll-loops" } } } } */ /* { dg-final { scan-assembler-times {vsetvli\s+[a-x0-9]+,\s*zero,\s*e8,\s*mf8,\s*t[au],\s*m[au]} 1 { target { no-opts "-O0" no-opts "-funroll-loops" no-opts "-g" } } } } */ -/* { dg-final { scan-assembler-times {vsetivli} 1 { target { no-opts "-O0" no-opts "-funroll-loops" no-opts "-g" } } } } */ +/* { dg-final { scan-assembler-times {vsetivli} 2 { target { no-opts "-O0" no-opts "-funroll-loops" no-opts "-g" } } } } */ /* { dg-final { scan-assembler-times {vsetvli} 1 { target { no-opts "-O0" no-opts "-funroll-loops" no-opts "-g" } } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr108270.c b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr108270.c new file mode 100644 index 00000000000..d2ae43bf263 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/pr108270.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gcv -mabi=ilp32 -fno-tree-vectorize -fno-schedule-insns -fno-schedule-insns2" } */ + +#include "riscv_vector.h" + +void f (void * restrict in, void * restrict out, int l, int n, int m) +{ + for (int i = 0; i < l; i++){ + for (int j = 0; j < m; j++){ + for (int k = 0; k < n; k++) + { + vint8mf8_t v = __riscv_vle8_v_i8mf8 (in + i + j, 17); + __riscv_vse8_v_i8mf8 (out + i + j, v, 17); + } + } + } +} + +/* { dg-final { scan-assembler-not {mv\s+[a-x0-9]+,[a-x0-9]+\s+mv\s+[a-x0-9]+,[a-x0-9]+\s+mv\s+[a-x0-9]+,[a-x0-9]+\s+mv\s+[a-x0-9]+,[a-x0-9]+\s+mv\s+[a-x0-9]+,[a-x0-9]+\s+vsetivli} } } */ -- 2.36.1