Re: [PATCH 2/2] ARC: Use intrinsics for __builtin_sub_overflow*()

2024-04-19 Thread Shahab Vahedi
Hi Claudiu,

On 9/7/23 12:15, Claudiu Zissulescu Ianculescu wrote:
> OK,
> 
> Thank you for your contribution,
> Claudiu

Could you commit this patch?

> 
> On Wed, Sep 6, 2023 at 3:50 PM Shahab Vahedi  
> wrote:
>>
>> This patch covers signed and unsigned subtractions.  The generated code
>> would be something along these lines:
>>
>> signed:
>>   sub.f   r0, r1, r2
>>   b.v @label
>>
>> unsigned:
>>   sub.f   r0, r1, r2
>>   b.c @label
>>
>> gcc/ChangeLog:
>>
>> * config/arc/arc.md (subsi3_v): New insn.
>> (subvsi4): New expand.
>> (subsi3_c): New insn.
>>     (usubvsi4): New expand.
>>
>> gcc/testsuite/ChangeLog:
>>
>> * gcc.target/arc/overflow-2.c: New.
>>
>> Signed-off-by: Shahab Vahedi 
>> ---
>>  gcc/config/arc/arc.md | 48 +++
>>  gcc/testsuite/gcc.target/arc/overflow-2.c | 97 +++
>>  2 files changed, 145 insertions(+)
>>  create mode 100644 gcc/testsuite/gcc.target/arc/overflow-2.c
>>
>> diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
>> index 9d011f6b4a9..34e9e1a7f1d 100644
>> --- a/gcc/config/arc/arc.md
>> +++ b/gcc/config/arc/arc.md
>> @@ -2973,6 +2973,54 @@ archs4x, archs4xd"
>>(set_attr "cpu_facility" "*,cd,*,*,*,*,*,*,*,*")
>>])
>>
>> +(define_insn "subsi3_v"
>> +  [(set (match_operand:SI  0 "register_operand"  "=r,r,r,  r")
>> +   (minus:SI (match_operand:SI 1 "register_operand"   "r,r,0,  r")
>> + (match_operand:SI 2 "nonmemory_operand"  "r,L,I,C32")))
>> +   (set (reg:CC_V CC_REG)
>> +   (compare:CC_V (sign_extend:DI (minus:SI (match_dup 1)
>> +   (match_dup 2)))
>> + (minus:DI (sign_extend:DI (match_dup 1))
>> +   (sign_extend:DI (match_dup 2)]
>> +   ""
>> +   "sub.f\\t%0,%1,%2"
>> +   [(set_attr "cond"   "set")
>> +(set_attr "type"   "compare")
>> +(set_attr "length" "4,4,4,8")])
>> +
>> +(define_expand "subvsi4"
>> + [(match_operand:SI 0 "register_operand")
>> +  (match_operand:SI 1 "register_operand")
>> +  (match_operand:SI 2 "nonmemory_operand")
>> +  (label_ref (match_operand 3 "" ""))]
>> +  ""
>> +  "emit_insn (gen_subsi3_v (operands[0], operands[1], operands[2]));
>> +   arc_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
>> +   DONE;")
>> +
>> +(define_insn "subsi3_c"
>> +  [(set (match_operand:SI  0 "register_operand"  "=r,r,r,  r")
>> +   (minus:SI (match_operand:SI 1 "register_operand"   "r,r,0,  r")
>> + (match_operand:SI 2 "nonmemory_operand"  "r,L,I,C32")))
>> +   (set (reg:CC_C CC_REG)
>> +   (compare:CC_C (match_dup 1)
>> + (match_dup 2)))]
>> +   ""
>> +   "sub.f\\t%0,%1,%2"
>> +   [(set_attr "cond"   "set")
>> +(set_attr "type"   "compare")
>> +(set_attr "length" "4,4,4,8")])
>> +
>> +(define_expand "usubvsi4"
>> +  [(match_operand:SI 0 "register_operand")
>> +   (match_operand:SI 1 "register_operand")
>> +   (match_operand:SI 2 "nonmemory_operand")
>> +   (label_ref (match_operand 3 "" ""))]
>> +   ""
>> +   "emit_insn (gen_subsi3_c (operands[0], operands[1], operands[2]));
>> +arc_gen_unlikely_cbranch (LTU, CC_Cmode, operands[3]);
>> +DONE;")
>> +
>>  (define_expand "subdi3"
>>[(set (match_operand:DI 0 "register_operand" "")
>> (minus:DI (match_operand:DI 1 "register_operand" "")
>> diff --git a/gcc/testsuite/gcc.target/arc/overflow-2.c 
>> b/gcc/testsuite/gcc.target/arc/overflow-2.c
>> new file mode 100644
>> index 000..b4de8c03b22
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/arc/overflow-2.c
>> @@ -0,0 +1,97 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O1" } */
>> +
>> +#include 
>> +#include 
>> +
>> +/*
>> + * sub.f  r0,r0,r1
>> + * st_s   r

Re: [PATCH 1/2] ARC: Use intrinsics for __builtin_add_overflow*()

2024-04-19 Thread Shahab Vahedi
Hi Clauudiu,

On 9/7/23 12:15, Claudiu Zissulescu Ianculescu wrote:
> Ok.
> 
> Thank you for your contribution,
> Claudiu

Could you commit this patch?

> 
> On Wed, Sep 6, 2023 at 3:50 PM Shahab Vahedi  
> wrote:
>>
>> This patch covers signed and unsigned additions.  The generated code
>> would be something along these lines:
>>
>> signed:
>>   add.f   r0, r1, r2
>>   b.v @label
>>
>> unsigned:
>>   add.f   r0, r1, r2
>>   b.c @label
>>
>> gcc/ChangeLog:
>>
>> * config/arc/arc-modes.def: Add CC_V mode.
>> * config/arc/predicates.md (proper_comparison_operator): Handle
>> E_CC_Vmode.
>> (equality_comparison_operator): Exclude CC_Vmode from eq/ne.
>> (cc_set_register): Handle CC_Vmode.
>> (cc_use_register): Likewise.
>> * config/arc/arc.md (addsi3_v): New insn.
>> (addvsi4): New expand.
>> (addsi3_c): New insn.
>> (uaddvsi4): New expand.
>> * config/arc/arc-protos.h (arc_gen_unlikely_cbranch): New.
>> * config/arc/arc.cc (arc_gen_unlikely_cbranch): New.
>> (get_arc_condition_code): Handle E_CC_Vmode.
>> (arc_init_reg_tables): Handle CC_Vmode.
>>
>> gcc/testsuite/ChangeLog:
>>
>> * gcc.target/arc/overflow-1.c: New.
>>
>> Signed-off-by: Shahab Vahedi 
>> ---
>>  gcc/config/arc/arc-modes.def  |   1 +
>>  gcc/config/arc/arc-protos.h   |   1 +
>>  gcc/config/arc/arc.cc |  26 +-
>>  gcc/config/arc/arc.md |  49 +++
>>  gcc/config/arc/predicates.md  |  14 ++-
>>  gcc/testsuite/gcc.target/arc/overflow-1.c | 100 ++
>>  6 files changed, 187 insertions(+), 4 deletions(-)
>>  create mode 100644 gcc/testsuite/gcc.target/arc/overflow-1.c
>>
>> diff --git a/gcc/config/arc/arc-modes.def b/gcc/config/arc/arc-modes.def
>> index 763e880317d..69eeec5935a 100644
>> --- a/gcc/config/arc/arc-modes.def
>> +++ b/gcc/config/arc/arc-modes.def
>> @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
>>
>>  CC_MODE (CC_ZN);
>>  CC_MODE (CC_Z);
>> +CC_MODE (CC_V);
>>  CC_MODE (CC_C);
>>  CC_MODE (CC_FP_GT);
>>  CC_MODE (CC_FP_GE);
>> diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
>> index 4f2db7ffb59..bc78fb0b370 100644
>> --- a/gcc/config/arc/arc-protos.h
>> +++ b/gcc/config/arc/arc-protos.h
>> @@ -50,6 +50,7 @@ extern bool arc_check_mov_const (HOST_WIDE_INT );
>>  extern bool arc_split_mov_const (rtx *);
>>  extern bool arc_can_use_return_insn (void);
>>  extern bool arc_split_move_p (rtx *);
>> +extern void arc_gen_unlikely_cbranch (enum rtx_code, machine_mode, rtx);
>>  #endif /* RTX_CODE */
>>
>>  extern bool arc_ccfsm_branch_deleted_p (void);
>> diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc
>> index f8c9bf17e2c..ec93d40aeb9 100644
>> --- a/gcc/config/arc/arc.cc
>> +++ b/gcc/config/arc/arc.cc
>> @@ -1538,6 +1538,13 @@ get_arc_condition_code (rtx comparison)
>> case GEU : return ARC_CC_NC;
>> default : gcc_unreachable ();
>> }
>> +case E_CC_Vmode:
>> +  switch (GET_CODE (comparison))
>> +   {
>> +   case EQ : return ARC_CC_NV;
>> +   case NE : return ARC_CC_V;
>> +   default : gcc_unreachable ();
>> +   }
>>  case E_CC_FP_GTmode:
>>if (TARGET_ARGONAUT_SET && TARGET_SPFP)
>> switch (GET_CODE (comparison))
>> @@ -1868,7 +1875,7 @@ arc_init_reg_tables (void)
>>   /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
>>  we must explicitly check for them here.  */
>>   if (i == (int) CCmode || i == (int) CC_ZNmode || i == (int) 
>> CC_Zmode
>> - || i == (int) CC_Cmode
>> + || i == (int) CC_Cmode || i == (int) CC_Vmode
>>   || i == CC_FP_GTmode || i == CC_FP_GEmode || i == CC_FP_ORDmode
>>   || i == CC_FPUmode || i == CC_FPUEmode || i == CC_FPU_UNEQmode)
>> arc_mode_class[i] = 1 << (int) C_MODE;
>> @@ -11852,6 +11859,23 @@ arc_libm_function_max_error (unsigned cfn, 
>> machine_mode mode,
>>return default_libm_function_max_error (cfn, mode, boundary_p);
>>  }
>>
>> +/* Generate RTL for conditional branch with rtx comparison CODE in mode
>> +   CC_MODE.  */
>> +
>> +void
>> +arc_gen_unlikely_cbranch (enum rtx_code cm

[PATCH 2/2] ARC: Use intrinsics for __builtin_sub_overflow*()

2023-09-06 Thread Shahab Vahedi via Gcc-patches
This patch covers signed and unsigned subtractions.  The generated code
would be something along these lines:

signed:
  sub.f   r0, r1, r2
  b.v @label

unsigned:
  sub.f   r0, r1, r2
  b.c @label

gcc/ChangeLog:

* config/arc/arc.md (subsi3_v): New insn.
(subvsi4): New expand.
(subsi3_c): New insn.
(usubvsi4): New expand.

gcc/testsuite/ChangeLog:

* gcc.target/arc/overflow-2.c: New.

Signed-off-by: Shahab Vahedi 
---
 gcc/config/arc/arc.md | 48 +++
 gcc/testsuite/gcc.target/arc/overflow-2.c | 97 +++
 2 files changed, 145 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/arc/overflow-2.c

diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 9d011f6b4a9..34e9e1a7f1d 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -2973,6 +2973,54 @@ archs4x, archs4xd"
   (set_attr "cpu_facility" "*,cd,*,*,*,*,*,*,*,*")
   ])
 
+(define_insn "subsi3_v"
+  [(set (match_operand:SI  0 "register_operand"  "=r,r,r,  r")
+   (minus:SI (match_operand:SI 1 "register_operand"   "r,r,0,  r")
+ (match_operand:SI 2 "nonmemory_operand"  "r,L,I,C32")))
+   (set (reg:CC_V CC_REG)
+   (compare:CC_V (sign_extend:DI (minus:SI (match_dup 1)
+   (match_dup 2)))
+ (minus:DI (sign_extend:DI (match_dup 1))
+   (sign_extend:DI (match_dup 2)]
+   ""
+   "sub.f\\t%0,%1,%2"
+   [(set_attr "cond"   "set")
+(set_attr "type"   "compare")
+(set_attr "length" "4,4,4,8")])
+
+(define_expand "subvsi4"
+ [(match_operand:SI 0 "register_operand")
+  (match_operand:SI 1 "register_operand")
+  (match_operand:SI 2 "nonmemory_operand")
+  (label_ref (match_operand 3 "" ""))]
+  ""
+  "emit_insn (gen_subsi3_v (operands[0], operands[1], operands[2]));
+   arc_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
+   DONE;")
+
+(define_insn "subsi3_c"
+  [(set (match_operand:SI  0 "register_operand"  "=r,r,r,  r")
+   (minus:SI (match_operand:SI 1 "register_operand"   "r,r,0,  r")
+ (match_operand:SI 2 "nonmemory_operand"  "r,L,I,C32")))
+   (set (reg:CC_C CC_REG)
+   (compare:CC_C (match_dup 1)
+ (match_dup 2)))]
+   ""
+   "sub.f\\t%0,%1,%2"
+   [(set_attr "cond"   "set")
+(set_attr "type"   "compare")
+(set_attr "length" "4,4,4,8")])
+
+(define_expand "usubvsi4"
+  [(match_operand:SI 0 "register_operand")
+   (match_operand:SI 1 "register_operand")
+   (match_operand:SI 2 "nonmemory_operand")
+   (label_ref (match_operand 3 "" ""))]
+   ""
+   "emit_insn (gen_subsi3_c (operands[0], operands[1], operands[2]));
+arc_gen_unlikely_cbranch (LTU, CC_Cmode, operands[3]);
+DONE;")
+
 (define_expand "subdi3"
   [(set (match_operand:DI 0 "register_operand" "")
(minus:DI (match_operand:DI 1 "register_operand" "")
diff --git a/gcc/testsuite/gcc.target/arc/overflow-2.c 
b/gcc/testsuite/gcc.target/arc/overflow-2.c
new file mode 100644
index 000..b4de8c03b22
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/overflow-2.c
@@ -0,0 +1,97 @@
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+#include 
+#include 
+
+/*
+ * sub.f  r0,r0,r1
+ * st_s   r0,[r2]
+ * mov_s  r0,1
+ * j_s.d  [blink]
+ * mov.nv r0,0
+ */
+bool sub_overflow (int32_t a, int32_t b, int32_t *res)
+{
+  return __builtin_sub_overflow (a, b, res);
+}
+
+/*
+ * sub.f  r0,r0,-1234
+ * st_s   r0,[r1]
+ * mov_s  r0,1
+ * j_s.d  [blink]
+ * mov.nv r0,0
+ */
+bool subi_overflow (int32_t a, int32_t *res)
+{
+  return __builtin_sub_overflow (a, -1234, res);
+}
+
+/*
+ * sub.f  r3,r0,r1
+ * st_s   r3,[r2]
+ * j_s.d  [blink]
+ * setlo  r0,r0,r1
+ */
+bool usub_overflow (uint32_t a, uint32_t b, uint32_t *res)
+{
+  return __builtin_sub_overflow (a, b, res);
+}
+
+/*
+ * sub.f  r2,r0,4321
+ * seths  r0,4320,r0
+ * j_s.d  [blink]
+ * st_s   r2,[r1]
+ */
+bool usubi_overflow (uint32_t a, uint32_t *res)
+{
+  return __builtin_sub_overflow (a, 4321, res);
+}
+
+/*
+ * sub.f  r0,r0,r1
+ * mov_s  r0,1
+ * j_s.d  [blink]
+ * mov.nv r0,0
+ */
+bool sub_overflow_p (int32_t a, int32_t b, int32_t res)
+{
+  return __builtin_sub_overflow_p (a, b, res);
+}
+
+/*
+ * sub.f  r0,r0,-1000
+ * mov_s  r0,1
+ * j_s.d  [blink]
+ * mov.nv r0,0
+ */
+bool subi_overflow_p (int32_t a, int32_t res)
+{
+  return __builtin_sub_overflow_p (a, -1000, res);
+}
+
+/*
+ * j_s.

[PATCH 1/2] ARC: Use intrinsics for __builtin_add_overflow*()

2023-09-06 Thread Shahab Vahedi via Gcc-patches
This patch covers signed and unsigned additions.  The generated code
would be something along these lines:

signed:
  add.f   r0, r1, r2
  b.v @label

unsigned:
  add.f   r0, r1, r2
  b.c @label

gcc/ChangeLog:

* config/arc/arc-modes.def: Add CC_V mode.
* config/arc/predicates.md (proper_comparison_operator): Handle
E_CC_Vmode.
(equality_comparison_operator): Exclude CC_Vmode from eq/ne.
(cc_set_register): Handle CC_Vmode.
(cc_use_register): Likewise.
* config/arc/arc.md (addsi3_v): New insn.
(addvsi4): New expand.
(addsi3_c): New insn.
(uaddvsi4): New expand.
* config/arc/arc-protos.h (arc_gen_unlikely_cbranch): New.
* config/arc/arc.cc (arc_gen_unlikely_cbranch): New.
(get_arc_condition_code): Handle E_CC_Vmode.
(arc_init_reg_tables): Handle CC_Vmode.

gcc/testsuite/ChangeLog:

* gcc.target/arc/overflow-1.c: New.

Signed-off-by: Shahab Vahedi 
---
 gcc/config/arc/arc-modes.def  |   1 +
 gcc/config/arc/arc-protos.h   |   1 +
 gcc/config/arc/arc.cc |  26 +-
 gcc/config/arc/arc.md |  49 +++
 gcc/config/arc/predicates.md  |  14 ++-
 gcc/testsuite/gcc.target/arc/overflow-1.c | 100 ++
 6 files changed, 187 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arc/overflow-1.c

diff --git a/gcc/config/arc/arc-modes.def b/gcc/config/arc/arc-modes.def
index 763e880317d..69eeec5935a 100644
--- a/gcc/config/arc/arc-modes.def
+++ b/gcc/config/arc/arc-modes.def
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 
 CC_MODE (CC_ZN);
 CC_MODE (CC_Z);
+CC_MODE (CC_V);
 CC_MODE (CC_C);
 CC_MODE (CC_FP_GT);
 CC_MODE (CC_FP_GE);
diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index 4f2db7ffb59..bc78fb0b370 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -50,6 +50,7 @@ extern bool arc_check_mov_const (HOST_WIDE_INT );
 extern bool arc_split_mov_const (rtx *);
 extern bool arc_can_use_return_insn (void);
 extern bool arc_split_move_p (rtx *);
+extern void arc_gen_unlikely_cbranch (enum rtx_code, machine_mode, rtx);
 #endif /* RTX_CODE */
 
 extern bool arc_ccfsm_branch_deleted_p (void);
diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc
index f8c9bf17e2c..ec93d40aeb9 100644
--- a/gcc/config/arc/arc.cc
+++ b/gcc/config/arc/arc.cc
@@ -1538,6 +1538,13 @@ get_arc_condition_code (rtx comparison)
case GEU : return ARC_CC_NC;
default : gcc_unreachable ();
}
+case E_CC_Vmode:
+  switch (GET_CODE (comparison))
+   {
+   case EQ : return ARC_CC_NV;
+   case NE : return ARC_CC_V;
+   default : gcc_unreachable ();
+   }
 case E_CC_FP_GTmode:
   if (TARGET_ARGONAUT_SET && TARGET_SPFP)
switch (GET_CODE (comparison))
@@ -1868,7 +1875,7 @@ arc_init_reg_tables (void)
  /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
 we must explicitly check for them here.  */
  if (i == (int) CCmode || i == (int) CC_ZNmode || i == (int) CC_Zmode
- || i == (int) CC_Cmode
+ || i == (int) CC_Cmode || i == (int) CC_Vmode
  || i == CC_FP_GTmode || i == CC_FP_GEmode || i == CC_FP_ORDmode
  || i == CC_FPUmode || i == CC_FPUEmode || i == CC_FPU_UNEQmode)
arc_mode_class[i] = 1 << (int) C_MODE;
@@ -11852,6 +11859,23 @@ arc_libm_function_max_error (unsigned cfn, 
machine_mode mode,
   return default_libm_function_max_error (cfn, mode, boundary_p);
 }
 
+/* Generate RTL for conditional branch with rtx comparison CODE in mode
+   CC_MODE.  */
+
+void
+arc_gen_unlikely_cbranch (enum rtx_code cmp, machine_mode cc_mode, rtx label)
+{
+  rtx cc_reg, x;
+
+  cc_reg = gen_rtx_REG (cc_mode, CC_REG);
+  label = gen_rtx_LABEL_REF (VOIDmode, label);
+
+  x = gen_rtx_fmt_ee (cmp, VOIDmode, cc_reg, const0_rtx);
+  x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label, pc_rtx);
+
+  emit_unlikely_jump (gen_rtx_SET (pc_rtx, x));
+}
+
 #undef TARGET_USE_ANCHORS_FOR_SYMBOL_P
 #define TARGET_USE_ANCHORS_FOR_SYMBOL_P arc_use_anchors_for_symbol_p
 
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index d37ecbf4292..9d011f6b4a9 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -2725,6 +2725,55 @@ archs4x, archs4xd"
  }
   ")
 
+(define_insn "addsi3_v"
+ [(set (match_operand:SI 0 "register_operand"  "=r,r,r,  r")
+   (plus:SI (match_operand:SI 1 "register_operand"   "r,r,0,  r")
+   (match_operand:SI 2 "nonmemory_operand"  "r,L,I,C32")))
+  (set (reg:CC_V CC_REG)
+   (compare:CC_V (sign_extend:DI (plus:SI (match_dup 1)
+ (match_dup 2)))
+(plus:DI (sign_extend:DI (match_dup 1))
+

[PATCH] [ARC] Pass along -mcode-density flag to the assembler

2019-09-03 Thread Shahab Vahedi
From: Shahab Vahedi 

This change makes sure that if the driver is invoked with
"-mcode-density" flag, then the assembler will receive it
too.

gcc/
2019-09-03  Sahahb Vahedi  

* config/arc/arc.h (ASM_SPEC): pass -mcode-density
* gcc.target/arc/code-density-flag.c: New test.

Signed-off-by: Shahab Vahedi 
---
 gcc/config/arc/arc.h  |  5 +--
 .../gcc.target/arc/code-density-flag.c| 34 +++
 2 files changed, 37 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arc/code-density-flag.c

diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index 8dca0d2c4b2..05fba539295 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -96,8 +96,9 @@ extern const char *arc_cpu_to_as (int argc, const char 
**argv);
 #endif
 
 #undef ASM_SPEC
-#define ASM_SPEC  "%{mbig-endian|EB:-EB} %{EL} "   \
-  "%:cpu_to_as(%{mcpu=*:%*}) %{mspfp*} %{mdpfp*} %{mfpu=fpuda*:-mfpuda}"
+#define ASM_SPEC  "%{mbig-endian|EB:-EB} %{EL} "   \
+  "%:cpu_to_as(%{mcpu=*:%*}) %{mspfp*} %{mdpfp*} " \
+  "%{mfpu=fpuda*:-mfpuda} %{mcode-density}"
 
 #define OPTION_DEFAULT_SPECS   \
   {"cpu", "%{!mcpu=*:%{!mARC*:%{!marc*:%{!mA7:%{!mA6:-mcpu=%(VALUE)}" }
diff --git a/gcc/testsuite/gcc.target/arc/code-density-flag.c 
b/gcc/testsuite/gcc.target/arc/code-density-flag.c
new file mode 100644
index 000..1ecf1a2ca29
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/code-density-flag.c
@@ -0,0 +1,34 @@
+/* Produce code-dense instructions  and  the assembler must *
+ * be okay with it. An example would be:*
+ *  *
+ * sub_s  r3, r1, r3*
+ *  *
+ * While generally for  _short instructions_ ,  it  is  not *
+ * allowed to have different registers  as  the  first  and *
+ * second operands, the code-dense mode allows it.  *
+ * This test is about the fact that if  "-mcode-density" is *
+ * passed to gcc driver as the flag,  "as"  must receive it *
+ * as well, else it is going to choke on such encodings.*/
+
+/* { dg-do assemble }   */
+/* { dg-skip-if "" { ! { clmcpu } } }   */
+/* { dg-options "-mcpu=em_mini -mcode-density" }*/
+
+typedef long long uint64_t;
+
+uint64_t f1(void)
+{
+  return 1;
+}
+
+void f2(void)
+{
+  uint64_t start_us = 0;
+  while ((f1() - start_us) < 2);
+}
+
+/* This is a tricky check, because  it  hardcodes  register *
+ * numbers. Nevertheless, it is easier than coming up  with *
+ * a regular expression that the first two operands  should *
+ * not be the same. */
+/* { dg-final { scan-assembler "sub_s\\s+r3,r1,r3" } }  */
-- 
2.23.0