This allows to use COND_EXEC patterns on nvptx. The backend is mostly ready for that, although I had to slightly fix nvptx_print_operand. I've also opted to make calls predicable to make the uniform-simt patch simpler, and to that end I need a small fixup in nvptx_output_call_insn.
RTL optimization won't emit COND_EXEC insns, because it's done only after reload, and register allocation is not done. I need this patch to create COND_EXEC patterns in the backend during reorg. * config/nvptx/nvptx.c (nvptx_output_call_insn): Handle COND_EXEC patterns. Emit instruction predicate. (nvptx_print_operand): Unbreak handling of instruction predicates. * config/nvptx/nvptx.md (predicable): New attribute. Generate predicated forms via define_cond_exec. (br_true): Mark as not predicable. (br_false): Ditto. (br_true_uni): Ditto. (br_false_uni): Ditto. (return): Ditto. (trap_if_true): Ditto. (trap_if_false): Ditto. (nvptx_fork): Ditto. (nvptx_forked): Ditto. (nvptx_joining): Ditto. (nvptx_join): Ditto. (nvptx_barsync): Ditto. --- gcc/config/nvptx/nvptx.c | 12 +++++++----- gcc/config/nvptx/nvptx.md | 43 +++++++++++++++++++++++++++++++------------ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c index 19445ad..2dad3e2 100644 --- a/gcc/config/nvptx/nvptx.c +++ b/gcc/config/nvptx/nvptx.c @@ -1905,6 +1905,8 @@ nvptx_assemble_undefined_decl (FILE *file, const char *name, const_tree decl) fprintf (file, ";\n\n"); } +static void nvptx_print_operand (FILE *, rtx, int); + /* Output INSN, which is a call to CALLEE with result RESULT. For ptx, this involves writing .param declarations and in/out copies into them. For indirect calls, also write the .callprototype. */ @@ -1916,6 +1918,8 @@ nvptx_output_call_insn (rtx_insn *insn, rtx result, rtx callee) static int labelno; bool needs_tgt = register_operand (callee, Pmode); rtx pat = PATTERN (insn); + if (GET_CODE (pat) == COND_EXEC) + pat = COND_EXEC_CODE (pat); int arg_end = XVECLEN (pat, 0); tree decl = NULL_TREE; @@ -1975,6 +1979,7 @@ nvptx_output_call_insn (rtx_insn *insn, rtx result, rtx callee) } } + nvptx_print_operand (asm_out_file, NULL_RTX, '.'); fprintf (asm_out_file, "\t\tcall "); if (result != NULL_RTX) fprintf (asm_out_file, "(%%retval_in), "); @@ -2032,8 +2037,6 @@ nvptx_print_operand_punct_valid_p (unsigned char c) return c == '.' || c== '#'; } -static void nvptx_print_operand (FILE *, rtx, int); - /* Subroutine of nvptx_print_operand; used to print a memory reference X to FILE. */ static void @@ -2098,11 +2101,10 @@ nvptx_print_operand (FILE *file, rtx x, int code) if (x) { unsigned int regno = REGNO (XEXP (x, 0)); - fputs ("[", file); + fputs ("@", file); if (GET_CODE (x) == EQ) fputs ("!", file); - fputs (reg_names [regno], file); - fputs ("]", file); + fprintf (file, "%%r%d", regno); } return; } diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md index 7930f8d..5ce7a89 100644 --- a/gcc/config/nvptx/nvptx.md +++ b/gcc/config/nvptx/nvptx.md @@ -226,6 +226,17 @@ (define_predicate "call_operation" return true; }) +(define_attr "predicable" "false,true" + (const_string "true")) + +(define_cond_exec + [(match_operator 0 "predicate_operator" + [(match_operand:BI 1 "nvptx_register_operand" "") + (match_operand:BI 2 "const0_operand" "")])] + "" + "" + ) + (define_constraint "P0" "An integer with the value 0." (and (match_code "const_int") @@ -821,7 +832,8 @@ (define_insn "br_true" (label_ref (match_operand 1 "" "")) (pc)))] "" - "%j0\\tbra\\t%l1;") + "%j0\\tbra\\t%l1;" + [(set_attr "predicable" "false")]) (define_insn "br_false" [(set (pc) @@ -830,7 +842,8 @@ (define_insn "br_false" (label_ref (match_operand 1 "" "")) (pc)))] "" - "%J0\\tbra\\t%l1;") + "%J0\\tbra\\t%l1;" + [(set_attr "predicable" "false")]) ;; unified conditional branch (define_insn "br_true_uni" @@ -839,7 +852,8 @@ (define_insn "br_true_uni" UNSPEC_BR_UNIFIED) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] "" - "%j0\\tbra.uni\\t%l1;") + "%j0\\tbra.uni\\t%l1;" + [(set_attr "predicable" "false")]) (define_insn "br_false_uni" [(set (pc) (if_then_else @@ -847,7 +861,8 @@ (define_insn "br_false_uni" UNSPEC_BR_UNIFIED) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] "" - "%J0\\tbra.uni\\t%l1;") + "%J0\\tbra.uni\\t%l1;" + [(set_attr "predicable" "false")]) (define_expand "cbranch<mode>4" [(set (pc) @@ -1239,7 +1254,8 @@ (define_insn "return" "" { return nvptx_output_return (); -}) +} + [(set_attr "predicable" "false")]) (define_expand "epilogue" [(clobber (const_int 0))] @@ -1319,14 +1335,16 @@ (define_insn "trap_if_true" (const_int 0)) (const_int 0))] "" - "%j0 trap;") + "%j0 trap;" + [(set_attr "predicable" "false")]) (define_insn "trap_if_false" [(trap_if (eq (match_operand:BI 0 "nvptx_register_operand" "R") (const_int 0)) (const_int 0))] "" - "%J0 trap;") + "%J0 trap;" + [(set_attr "predicable" "false")]) (define_expand "ctrap<mode>4" [(trap_if (match_operator 0 "nvptx_comparison_operator" @@ -1375,28 +1393,28 @@ (define_insn "nvptx_fork" UNSPECV_FORK)] "" "// fork %0;" -) + [(set_attr "predicable" "false")]) (define_insn "nvptx_forked" [(unspec_volatile:SI [(match_operand:SI 0 "const_int_operand" "")] UNSPECV_FORKED)] "" "// forked %0;" -) + [(set_attr "predicable" "false")]) (define_insn "nvptx_joining" [(unspec_volatile:SI [(match_operand:SI 0 "const_int_operand" "")] UNSPECV_JOINING)] "" "// joining %0;" -) + [(set_attr "predicable" "false")]) (define_insn "nvptx_join" [(unspec_volatile:SI [(match_operand:SI 0 "const_int_operand" "")] UNSPECV_JOIN)] "" "// join %0;" -) + [(set_attr "predicable" "false")]) (define_expand "oacc_fork" [(set (match_operand:SI 0 "nvptx_nonmemory_operand" "") @@ -1558,4 +1576,5 @@ (define_insn "nvptx_barsync" [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "")] UNSPECV_BARSYNC)] "" - "\\tbar.sync\\t%0;") + "\\tbar.sync\\t%0;" + [(set_attr "predicable" "false")])