===================================================================
@@ -41,6 +41,12 @@
(ior (match_operand 0 "arith_operand")
(match_operand 0 "lui_operand")))
+(define_predicate "movcc_operand"
+ (if_then_else (match_test "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV
+ || TARGET_ZICOND_LIKE")
+ (match_operand 0 "sfb_alu_operand")
+ (match_operand 0 "arith_operand")))
+
(define_predicate "const_csr_operand"
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 0, 31)")))
===================================================================
@@ -4099,7 +4099,9 @@ riscv_expand_conditional_move (rtx dest,
rtx op0 = XEXP (op, 0);
rtx op1 = XEXP (op, 1);
- if ((TARGET_ZICOND_LIKE && GET_MODE_CLASS (mode) == MODE_INT)
+ if (((TARGET_ZICOND_LIKE
+ || (arith_operand (cons, mode) && arith_operand (alt, mode)))
+ && (GET_MODE_CLASS (mode) == MODE_INT))
|| TARGET_SFB_ALU || TARGET_XTHEADCONDMOV)
{
machine_mode mode0 = GET_MODE (op0);
@@ -4113,6 +4115,15 @@ riscv_expand_conditional_move (rtx dest,
|| (mode1 != word_mode && mode1 != VOIDmode))
return false;
+ /* In the fallback generic case use MODE rather than WORD_MODE for
+ the output of the SCC instruction, to match the mode of the NEG
+ operation below. The output of SCC is 0 or 1 boolean, so it is
+ valid for input in any scalar integer mode. */
+ rtx tmp = gen_reg_rtx ((TARGET_ZICOND_LIKE
+ || TARGET_SFB_ALU || TARGET_XTHEADCONDMOV)
+ ? word_mode : mode);
+ bool invert = false;
+
/* Canonicalize the comparison. It must be an equality comparison
of integer operands, or with SFB it can be any comparison of
integer operands. If it isn't, then emit an SCC instruction
@@ -4121,7 +4132,6 @@ riscv_expand_conditional_move (rtx dest,
|| !INTEGRAL_MODE_P (mode0))
{
bool *invert_ptr = nullptr;
- bool invert = false;
/* If riscv_expand_int_scc inverts the condition, then it will
flip the value of INVERT. We need to know where so that
@@ -4129,11 +4139,9 @@ riscv_expand_conditional_move (rtx dest,
if (code == LE || code == LEU || code == GE || code == GEU)
invert_ptr = &invert;
- /* Emit an scc like instruction into a temporary
- so that we can use an EQ/NE comparison. */
- rtx tmp = gen_reg_rtx (word_mode);
-
- /* We can support both FP and integer conditional moves. */
+ /* Emit an SCC-like instruction into a temporary so that we can
+ use an EQ/NE comparison. We can support both FP and integer
+ conditional moves. */
if (INTEGRAL_MODE_P (mode0))
riscv_expand_int_scc (tmp, code, op0, op1, invert_ptr);
else if (FLOAT_MODE_P (mode0)
@@ -4149,6 +4157,8 @@ riscv_expand_conditional_move (rtx dest,
op0 = XEXP (op, 0);
op1 = XEXP (op, 1);
}
+ else if (!TARGET_ZICOND_LIKE && !TARGET_SFB_ALU && !TARGET_XTHEADCONDMOV)
+ riscv_expand_int_scc (tmp, code, op0, op1, &invert);
if (TARGET_SFB_ALU || TARGET_XTHEADCONDMOV)
{
@@ -4166,6 +4176,23 @@ riscv_expand_conditional_move (rtx dest,
cons, alt)));
return true;
}
+ else if (!TARGET_ZICOND_LIKE)
+ {
+ if (invert)
+ std::swap (cons, alt);
+
+ rtx reg1 = gen_reg_rtx (mode);
+ rtx reg2 = gen_reg_rtx (mode);
+ rtx reg3 = gen_reg_rtx (mode);
+ rtx reg4 = gen_reg_rtx (mode);
+
+ riscv_emit_unary (NEG, reg1, tmp);
+ riscv_emit_binary (AND, reg2, reg1, cons);
+ riscv_emit_unary (NOT, reg3, reg1);
+ riscv_emit_binary (AND, reg4, reg3, alt);
+ riscv_emit_binary (IOR, dest, reg2, reg4);
+ return true;
+ }
/* 0, reg or 0, imm */
else if (cons == CONST0_RTX (mode)
&& (REG_P (alt)
===================================================================
@@ -2658,9 +2658,10 @@
(define_expand "mov<mode>cc"
[(set (match_operand:GPR 0 "register_operand")
(if_then_else:GPR (match_operand 1 "comparison_operator")
- (match_operand:GPR 2 "sfb_alu_operand")
- (match_operand:GPR 3 "sfb_alu_operand")))]
- "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND_LIKE"
+ (match_operand:GPR 2 "movcc_operand")
+ (match_operand:GPR 3 "movcc_operand")))]
+ "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND_LIKE
+ || TARGET_MOVCC"
{
if (riscv_expand_conditional_move (operands[0], operands[1],
operands[2], operands[3]))
===================================================================
@@ -460,6 +460,10 @@ misa-spec=
Target RejectNegative Joined Enum(isa_spec_class) Var(riscv_isa_spec) Init(TARGET_DEFAULT_ISA_SPEC)
Set the version of RISC-V ISA spec.
+mmovcc
+Target Var(TARGET_MOVCC)
+Enable conditional moves unconditionally.
+
minline-atomics
Target Var(TARGET_INLINE_SUBWORD_ATOMIC) Init(1)
Always inline subword atomic operations.
===================================================================
@@ -1242,6 +1242,7 @@ See RS/6000 and PowerPC Options.
-mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{reg}
-mstack-protector-guard-offset=@var{offset}
-mcsr-check -mno-csr-check
+-mmovcc -mno-movcc
-minline-atomics -mno-inline-atomics
-minline-strlen -mno-inline-strlen
-minline-strcmp -mno-inline-strcmp
@@ -29586,6 +29587,14 @@ Do or don't use smaller but slower prolo
library function calls. The default is to use fast inline prologues and
epilogues.
+@opindex mmovcc
+@item -mmovcc
+@itemx -mno-movcc
+Do or don't produce branchless conditional-move code sequences even with
+targets that do not have specific instructions for conditional operations.
+If enabled, sequences of ALU operations are produced using base integer
+ISA instructions where profitable.
+
@opindex minline-atomics
@item -minline-atomics
@itemx -mno-inline-atomics
===================================================================
@@ -15,4 +15,4 @@ foo(const long long B, int a)
/* { dg-final { scan-assembler-times "bext\t" 1 } } */
/* { dg-final { scan-assembler-not {\mbset} } } */
-/* { dg-final { scan-assembler-not {\mand} } } */
+/* { dg-final { scan-assembler-not {\msll} } } */