* [PATCH 2/7] [ARC] Define ADDITIONAL_REGISTER_NAMES.
2017-06-01 13:37 [PATCH 0/7] [ARC] Bug fixing, add support for naked functions Claudiu Zissulescu
@ 2017-06-01 13:37 ` Claudiu Zissulescu
2017-06-16 19:37 ` Andrew Burgess
2017-06-01 13:37 ` [PATCH 3/7] [ARC] [LRA] Fix tests asm constraints Claudiu Zissulescu
` (5 subsequent siblings)
6 siblings, 1 reply; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-06-01 13:37 UTC (permalink / raw)
To: gcc-patches; +Cc: Claudiu.Zissulescu, Francois.Bedard, andrew.burgess
This macro is needed to be used with -ffixed-<reg> option, and inline asm.
gcc/
2017-01-09 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/arc.h (ADDITIONAL_REGISTER_NAMES): Define.
---
gcc/config/arc/arc.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index 16d5319..585e98c 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -1262,6 +1262,13 @@ extern char rname56[], rname57[], rname58[], rname59[];
"lp_start", "lp_end" \
}
+#define ADDITIONAL_REGISTER_NAMES \
+{ \
+ {"ilink", 29}, \
+ {"r29", 29}, \
+ {"r30", 30} \
+}
+
/* Entry to the insn conditionalizer. */
#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
arc_final_prescan_insn (INSN, OPVEC, NOPERANDS)
--
1.9.1
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 2/7] [ARC] Define ADDITIONAL_REGISTER_NAMES.
2017-06-01 13:37 ` [PATCH 2/7] [ARC] Define ADDITIONAL_REGISTER_NAMES Claudiu Zissulescu
@ 2017-06-16 19:37 ` Andrew Burgess
2017-07-10 13:57 ` Claudiu Zissulescu
0 siblings, 1 reply; 27+ messages in thread
From: Andrew Burgess @ 2017-06-16 19:37 UTC (permalink / raw)
To: Claudiu Zissulescu; +Cc: gcc-patches, Francois.Bedard
* Claudiu Zissulescu <Claudiu.Zissulescu@synopsys.com> [2017-06-01 15:34:52 +0200]:
> This macro is needed to be used with -ffixed-<reg> option, and inline asm.
>
> gcc/
> 2017-01-09 Claudiu Zissulescu <claziss@synopsys.com>
>
> * config/arc/arc.h (ADDITIONAL_REGISTER_NAMES): Define.
This looks fine and could be applied straight away I think.
Thanks,
Andrew
> ---
> gcc/config/arc/arc.h | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
> index 16d5319..585e98c 100644
> --- a/gcc/config/arc/arc.h
> +++ b/gcc/config/arc/arc.h
> @@ -1262,6 +1262,13 @@ extern char rname56[], rname57[], rname58[], rname59[];
> "lp_start", "lp_end" \
> }
>
> +#define ADDITIONAL_REGISTER_NAMES \
> +{ \
> + {"ilink", 29}, \
> + {"r29", 29}, \
> + {"r30", 30} \
> +}
> +
> /* Entry to the insn conditionalizer. */
> #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
> arc_final_prescan_insn (INSN, OPVEC, NOPERANDS)
> --
> 1.9.1
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: [PATCH 2/7] [ARC] Define ADDITIONAL_REGISTER_NAMES.
2017-06-16 19:37 ` Andrew Burgess
@ 2017-07-10 13:57 ` Claudiu Zissulescu
0 siblings, 0 replies; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-07-10 13:57 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gcc-patches, Francois.Bedard
> > gcc/
> > 2017-01-09 Claudiu Zissulescu <claziss@synopsys.com>
> >
> > * config/arc/arc.h (ADDITIONAL_REGISTER_NAMES): Define.
>
> This looks fine and could be applied straight away I think.
>
> Thanks,
> Andrew
Committed. Thank you for your review,
Claudiu
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 3/7] [ARC] [LRA] Fix tests asm constraints.
2017-06-01 13:37 [PATCH 0/7] [ARC] Bug fixing, add support for naked functions Claudiu Zissulescu
2017-06-01 13:37 ` [PATCH 2/7] [ARC] Define ADDITIONAL_REGISTER_NAMES Claudiu Zissulescu
@ 2017-06-01 13:37 ` Claudiu Zissulescu
2017-06-16 19:37 ` Andrew Burgess
2017-06-01 13:37 ` [PATCH 4/7] [ARC] [LRA] Avoid emitting COND_EXEC during expand Claudiu Zissulescu
` (4 subsequent siblings)
6 siblings, 1 reply; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-06-01 13:37 UTC (permalink / raw)
To: gcc-patches; +Cc: Claudiu.Zissulescu, Francois.Bedard, andrew.burgess
LRA doesn't like the 'X' constraint as used in our tests, remove it.
gcc/testsuite
2017-01-09 Claudiu Zissulescu <claziss@synopsys.com>
* gcc.target/arc/mulsi3_highpart-1.c: Remove 'X' constraint.
* gcc.target/arc/mulsi3_highpart-2.c: Likewise.
---
gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c | 2 +-
gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
index 57cb95b..5fd6c36 100644
--- a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
+++ b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
@@ -7,7 +7,7 @@
static int
id (int i)
{
- asm ("": "+Xr" (i));
+ asm ("": "+r" (i));
return i;
}
diff --git a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
index 287d96d..6ec4bc5 100644
--- a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
+++ b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
@@ -9,7 +9,7 @@
static int
id (int i)
{
- asm ("": "+Xr" (i));
+ asm ("": "+r" (i));
return i;
}
--
1.9.1
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 3/7] [ARC] [LRA] Fix tests asm constraints.
2017-06-01 13:37 ` [PATCH 3/7] [ARC] [LRA] Fix tests asm constraints Claudiu Zissulescu
@ 2017-06-16 19:37 ` Andrew Burgess
2017-07-10 13:56 ` Claudiu Zissulescu
0 siblings, 1 reply; 27+ messages in thread
From: Andrew Burgess @ 2017-06-16 19:37 UTC (permalink / raw)
To: Claudiu Zissulescu; +Cc: gcc-patches, Francois.Bedard
* Claudiu Zissulescu <Claudiu.Zissulescu@synopsys.com> [2017-06-01 15:34:53 +0200]:
> LRA doesn't like the 'X' constraint as used in our tests, remove it.
>
> gcc/testsuite
> 2017-01-09 Claudiu Zissulescu <claziss@synopsys.com>
>
> * gcc.target/arc/mulsi3_highpart-1.c: Remove 'X' constraint.
> * gcc.target/arc/mulsi3_highpart-2.c: Likewise.
This looks fine and could be applied straight away I think.
Thanks,
Andrew
> ---
> gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c | 2 +-
> gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
> index 57cb95b..5fd6c36 100644
> --- a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
> +++ b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
> @@ -7,7 +7,7 @@
> static int
> id (int i)
> {
> - asm ("": "+Xr" (i));
> + asm ("": "+r" (i));
> return i;
> }
>
> diff --git a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
> index 287d96d..6ec4bc5 100644
> --- a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
> +++ b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
> @@ -9,7 +9,7 @@
> static int
> id (int i)
> {
> - asm ("": "+Xr" (i));
> + asm ("": "+r" (i));
> return i;
> }
>
> --
> 1.9.1
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: [PATCH 3/7] [ARC] [LRA] Fix tests asm constraints.
2017-06-16 19:37 ` Andrew Burgess
@ 2017-07-10 13:56 ` Claudiu Zissulescu
0 siblings, 0 replies; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-07-10 13:56 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gcc-patches, Francois.Bedard
> > gcc/testsuite
> > 2017-01-09 Claudiu Zissulescu <claziss@synopsys.com>
> >
> > * gcc.target/arc/mulsi3_highpart-1.c: Remove 'X' constraint.
> > * gcc.target/arc/mulsi3_highpart-2.c: Likewise.
>
> This looks fine and could be applied straight away I think.
>
> Thanks,
> Andrew
>
Committed. Thank you for your review,
Claudiu
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 4/7] [ARC] [LRA] Avoid emitting COND_EXEC during expand.
2017-06-01 13:37 [PATCH 0/7] [ARC] Bug fixing, add support for naked functions Claudiu Zissulescu
2017-06-01 13:37 ` [PATCH 2/7] [ARC] Define ADDITIONAL_REGISTER_NAMES Claudiu Zissulescu
2017-06-01 13:37 ` [PATCH 3/7] [ARC] [LRA] Fix tests asm constraints Claudiu Zissulescu
@ 2017-06-01 13:37 ` Claudiu Zissulescu
2017-07-13 11:38 ` Andrew Burgess
2017-06-01 13:38 ` [PATCH 7/7] [ARC] Consolidate PIC implementation Claudiu Zissulescu
` (3 subsequent siblings)
6 siblings, 1 reply; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-06-01 13:37 UTC (permalink / raw)
To: gcc-patches; +Cc: Claudiu.Zissulescu, Francois.Bedard, andrew.burgess
Emmitting COND_EXEC rtxes during expand does not always work.
gcc/
2017-01-10 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/arc.md (clzsi2): Expand to an arc_clzsi2 instruction
that also clobbers the CC register. The old expand code is moved
to ...
(*arc_clzsi2): ... here.
(ctzsi2): Expand to an arc_ctzsi2 instruction that also clobbers
the CC register. The old expand code is moved to ...
(arc_ctzsi2): ... here.
---
gcc/config/arc/arc.md | 41 ++++++++++++++++++++++++++++++++++-------
1 file changed, 34 insertions(+), 7 deletions(-)
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 39bcc26..928feb1 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -4533,9 +4533,21 @@
(set_attr "type" "two_cycle_core,two_cycle_core")])
(define_expand "clzsi2"
- [(set (match_operand:SI 0 "dest_reg_operand" "")
- (clz:SI (match_operand:SI 1 "register_operand" "")))]
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (clz:SI (match_operand:SI 1 "register_operand" "")))
+ (clobber (match_dup 2))])]
+ "TARGET_NORM"
+ "operands[2] = gen_rtx_REG (CC_ZNmode, CC_REG);")
+
+(define_insn_and_split "*arc_clzsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (clz:SI (match_operand:SI 1 "register_operand" "r")))
+ (clobber (reg:CC_ZN CC_REG))]
"TARGET_NORM"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
{
emit_insn (gen_norm_f (operands[0], operands[1]));
emit_insn
@@ -4552,9 +4564,23 @@
})
(define_expand "ctzsi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (ctz:SI (match_operand:SI 1 "register_operand" "")))]
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "register_operand" "")]
"TARGET_NORM"
+ "
+ emit_insn (gen_arc_ctzsi2 (operands[0], operands[1]));
+ DONE;
+")
+
+(define_insn_and_split "arc_ctzsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ctz:SI (match_operand:SI 1 "register_operand" "r")))
+ (clobber (reg:CC_ZN CC_REG))
+ (clobber (match_scratch:SI 2 "=&r"))]
+ "TARGET_NORM"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
{
rtx temp = operands[0];
@@ -4562,10 +4588,10 @@
|| (REGNO (temp) < FIRST_PSEUDO_REGISTER
&& !TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS],
REGNO (temp))))
- temp = gen_reg_rtx (SImode);
+ temp = operands[2];
emit_insn (gen_addsi3 (temp, operands[1], constm1_rtx));
emit_insn (gen_bic_f_zn (temp, temp, operands[1]));
- emit_insn (gen_clrsbsi2 (temp, temp));
+ emit_insn (gen_clrsbsi2 (operands[0], temp));
emit_insn
(gen_rtx_COND_EXEC
(VOIDmode,
@@ -4575,7 +4601,8 @@
(gen_rtx_COND_EXEC
(VOIDmode,
gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
- gen_rtx_SET (operands[0], gen_rtx_MINUS (SImode, GEN_INT (31), temp))));
+ gen_rtx_SET (operands[0], gen_rtx_MINUS (SImode, GEN_INT (31),
+ operands[0]))));
DONE;
})
--
1.9.1
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 4/7] [ARC] [LRA] Avoid emitting COND_EXEC during expand.
2017-06-01 13:37 ` [PATCH 4/7] [ARC] [LRA] Avoid emitting COND_EXEC during expand Claudiu Zissulescu
@ 2017-07-13 11:38 ` Andrew Burgess
2017-07-13 12:54 ` Claudiu Zissulescu
2017-07-17 13:02 ` Claudiu Zissulescu
0 siblings, 2 replies; 27+ messages in thread
From: Andrew Burgess @ 2017-07-13 11:38 UTC (permalink / raw)
To: Claudiu Zissulescu; +Cc: gcc-patches, Francois.Bedard
* Claudiu Zissulescu <Claudiu.Zissulescu@synopsys.com> [2017-06-01 15:34:54 +0200]:
> Emmitting COND_EXEC rtxes during expand does not always work.
>
> gcc/
> 2017-01-10 Claudiu Zissulescu <claziss@synopsys.com>
>
> * config/arc/arc.md (clzsi2): Expand to an arc_clzsi2 instruction
> that also clobbers the CC register. The old expand code is moved
> to ...
> (*arc_clzsi2): ... here.
> (ctzsi2): Expand to an arc_ctzsi2 instruction that also clobbers
> the CC register. The old expand code is moved to ...
> (arc_ctzsi2): ... here.
This seems fine, your description "....does not always work." is a bit
of a tease :) it would be nice to know _why_ it doesn't work, or at
least a description of what problem you're seeing.
Also we seem to be missing a test, would it be possible to find one?
If not then I guess we live without, but we should note that in the
commit message.
Thanks,
Andrew
> ---
> gcc/config/arc/arc.md | 41 ++++++++++++++++++++++++++++++++++-------
> 1 file changed, 34 insertions(+), 7 deletions(-)
>
> diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
> index 39bcc26..928feb1 100644
> --- a/gcc/config/arc/arc.md
> +++ b/gcc/config/arc/arc.md
> @@ -4533,9 +4533,21 @@
> (set_attr "type" "two_cycle_core,two_cycle_core")])
>
> (define_expand "clzsi2"
> - [(set (match_operand:SI 0 "dest_reg_operand" "")
> - (clz:SI (match_operand:SI 1 "register_operand" "")))]
> + [(parallel
> + [(set (match_operand:SI 0 "register_operand" "")
> + (clz:SI (match_operand:SI 1 "register_operand" "")))
> + (clobber (match_dup 2))])]
> + "TARGET_NORM"
> + "operands[2] = gen_rtx_REG (CC_ZNmode, CC_REG);")
> +
> +(define_insn_and_split "*arc_clzsi2"
> + [(set (match_operand:SI 0 "register_operand" "=r")
> + (clz:SI (match_operand:SI 1 "register_operand" "r")))
> + (clobber (reg:CC_ZN CC_REG))]
> "TARGET_NORM"
> + "#"
> + "reload_completed"
> + [(const_int 0)]
> {
> emit_insn (gen_norm_f (operands[0], operands[1]));
> emit_insn
> @@ -4552,9 +4564,23 @@
> })
>
> (define_expand "ctzsi2"
> - [(set (match_operand:SI 0 "register_operand" "")
> - (ctz:SI (match_operand:SI 1 "register_operand" "")))]
> + [(match_operand:SI 0 "register_operand" "")
> + (match_operand:SI 1 "register_operand" "")]
> "TARGET_NORM"
> + "
> + emit_insn (gen_arc_ctzsi2 (operands[0], operands[1]));
> + DONE;
> +")
> +
> +(define_insn_and_split "arc_ctzsi2"
> + [(set (match_operand:SI 0 "register_operand" "=r")
> + (ctz:SI (match_operand:SI 1 "register_operand" "r")))
> + (clobber (reg:CC_ZN CC_REG))
> + (clobber (match_scratch:SI 2 "=&r"))]
> + "TARGET_NORM"
> + "#"
> + "reload_completed"
> + [(const_int 0)]
> {
> rtx temp = operands[0];
>
> @@ -4562,10 +4588,10 @@
> || (REGNO (temp) < FIRST_PSEUDO_REGISTER
> && !TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS],
> REGNO (temp))))
> - temp = gen_reg_rtx (SImode);
> + temp = operands[2];
> emit_insn (gen_addsi3 (temp, operands[1], constm1_rtx));
> emit_insn (gen_bic_f_zn (temp, temp, operands[1]));
> - emit_insn (gen_clrsbsi2 (temp, temp));
> + emit_insn (gen_clrsbsi2 (operands[0], temp));
> emit_insn
> (gen_rtx_COND_EXEC
> (VOIDmode,
> @@ -4575,7 +4601,8 @@
> (gen_rtx_COND_EXEC
> (VOIDmode,
> gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
> - gen_rtx_SET (operands[0], gen_rtx_MINUS (SImode, GEN_INT (31), temp))));
> + gen_rtx_SET (operands[0], gen_rtx_MINUS (SImode, GEN_INT (31),
> + operands[0]))));
> DONE;
> })
>
> --
> 1.9.1
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: [PATCH 4/7] [ARC] [LRA] Avoid emitting COND_EXEC during expand.
2017-07-13 11:38 ` Andrew Burgess
@ 2017-07-13 12:54 ` Claudiu Zissulescu
2017-07-17 13:02 ` Claudiu Zissulescu
1 sibling, 0 replies; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-07-13 12:54 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gcc-patches, Francois.Bedard
> This seems fine, your description "....does not always work." is a bit
> of a tease :) it would be nice to know _why_ it doesn't work, or at
> least a description of what problem you're seeing.
>
As far as I can see, LRA doesn't handle very well the conditional execution patterns, as it expects conditional execution to happen after this step. Thus, some of those instructions are marked dead and removed later on.
> Also we seem to be missing a test, would it be possible to find one?
> If not then I guess we live without, but we should note that in the
> commit message.
This error is found by executing dg.exp testsuite with our port and -mlra option on. As we speak, I am on the last 100m of testing our port having the LRA on. This bug being found like that.
I'll add this discussion to the commit message body.
Thank you,
Claudiu
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: [PATCH 4/7] [ARC] [LRA] Avoid emitting COND_EXEC during expand.
2017-07-13 11:38 ` Andrew Burgess
2017-07-13 12:54 ` Claudiu Zissulescu
@ 2017-07-17 13:02 ` Claudiu Zissulescu
1 sibling, 0 replies; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-07-17 13:02 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gcc-patches, Francois.Bedard
> This seems fine, your description "....does not always work." is a bit
> of a tease :) it would be nice to know _why_ it doesn't work, or at
> least a description of what problem you're seeing.
Committed with additional comments. Thank you,
Claudiu
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 7/7] [ARC] Consolidate PIC implementation.
2017-06-01 13:37 [PATCH 0/7] [ARC] Bug fixing, add support for naked functions Claudiu Zissulescu
` (2 preceding siblings ...)
2017-06-01 13:37 ` [PATCH 4/7] [ARC] [LRA] Avoid emitting COND_EXEC during expand Claudiu Zissulescu
@ 2017-06-01 13:38 ` Claudiu Zissulescu
2017-07-13 13:31 ` Andrew Burgess
2017-06-01 13:38 ` [PATCH 6/7] [ARC] Deprecate mexpand-adddi option Claudiu Zissulescu
` (2 subsequent siblings)
6 siblings, 1 reply; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-06-01 13:38 UTC (permalink / raw)
To: gcc-patches; +Cc: Claudiu.Zissulescu, Francois.Bedard, andrew.burgess
This patch refactors a number of functions and compiler hooks into using a
single function which checks if a rtx is suited for pic or not. Removed
functions are arc_legitimate_pc_offset_p and arc_legitimate_pic_operand_p
beeing replaced by calls to arc_legitimate_pic_addr_p. Thus we have an
unitary way of checking a rtx beeing pic.
gcc/
2017-02-24 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/arc-protos.h (arc_legitimate_pc_offset_p): Remove
proto.
(arc_legitimate_pic_operand_p): Likewise.
* config/arc/arc.c (arc_legitimate_pic_operand_p): Remove
function.
(arc_needs_pcl_p): Likewise.
(arc_legitimate_pc_offset_p): Likewise.
(arc_legitimate_pic_addr_p): Remove LABEL_REF case, as this
function is also used in constrains.md.
(arc_legitimate_constant_p): Use arc_legitimate_pic_addr_p to
validate pic constants. Handle CONST_INT, CONST_DOUBLE, MINUS and
PLUS. Only return true/false in known cases, otherwise assert.
(arc_legitimate_address_p): Remove arc_legitimate_pic_addr_p as it
is already called in arc_legitimate_constant_p.
* config/arc/arc.h (CONSTANT_ADDRESS_P): Consider also LABEL for
pic addresses.
(LEGITIMATE_PIC_OPERAND_P): Use
arc_raw_symbolic_reference_mentioned_p function.
* config/arc/constraints.md (Cpc): Use arc_legitimate_pic_addr_p
function.
(Cal): Likewise.
(C32): Likewise.
gcc/testsuite
2017-02-24 Claudiu Zissulescu <claziss@synopsys.com>
* gcc.target/arc/pr9000674901.c: New file.
* gcc.target/arc/pic-1.c: Likewise.
* gcc.target/arc/pr9001191897.c: Likewise.
---
gcc/config/arc/arc-protos.h | 2 -
gcc/config/arc/arc.c | 150 +++++++++-------------------
gcc/config/arc/arc.h | 11 +-
gcc/config/arc/constraints.md | 6 +-
gcc/testsuite/gcc.target/arc/pic-1.c | 11 ++
gcc/testsuite/gcc.target/arc/pr9000674901.c | 58 +++++++++++
gcc/testsuite/gcc.target/arc/pr9001191897.c | 10 ++
7 files changed, 136 insertions(+), 112 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/arc/pic-1.c
create mode 100644 gcc/testsuite/gcc.target/arc/pr9000674901.c
create mode 100644 gcc/testsuite/gcc.target/arc/pr9001191897.c
diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index b436dbe..850795a 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -60,10 +60,8 @@ extern rtx arc_return_addr_rtx (int , rtx);
extern bool check_if_valid_regno_const (rtx *, int);
extern bool check_if_valid_sleep_operand (rtx *, int);
extern bool arc_legitimate_constant_p (machine_mode, rtx);
-extern bool arc_legitimate_pc_offset_p (rtx);
extern bool arc_legitimate_pic_addr_p (rtx);
extern bool arc_raw_symbolic_reference_mentioned_p (rtx, bool);
-extern bool arc_legitimate_pic_operand_p (rtx);
extern bool arc_is_longcall_p (rtx);
extern bool arc_is_shortcall_p (rtx);
extern bool valid_brcc_with_delay_p (rtx *);
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 7dfc68e..89de6cd 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -249,7 +249,6 @@ static rtx arc_expand_builtin (tree, rtx, rtx, machine_mode, int);
static int branch_dest (rtx);
static void arc_output_pic_addr_const (FILE *, rtx, int);
-bool arc_legitimate_pic_operand_p (rtx);
static bool arc_function_ok_for_sibcall (tree, tree);
static rtx arc_function_value (const_tree, const_tree, bool);
const char * output_shift (rtx *);
@@ -5152,57 +5151,6 @@ arc_rtx_costs (rtx x, machine_mode mode, int outer_code,
}
}
-/* Helper used by arc_legitimate_pc_offset_p. */
-
-static bool
-arc_needs_pcl_p (rtx x)
-{
- register const char *fmt;
- register int i, j;
-
- if ((GET_CODE (x) == UNSPEC)
- && (XVECLEN (x, 0) == 1)
- && (GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF))
- switch (XINT (x, 1))
- {
- case ARC_UNSPEC_GOT:
- case ARC_UNSPEC_GOTOFFPC:
- case UNSPEC_TLS_GD:
- case UNSPEC_TLS_IE:
- return true;
- default:
- break;
- }
-
- fmt = GET_RTX_FORMAT (GET_CODE (x));
- for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- if (arc_needs_pcl_p (XEXP (x, i)))
- return true;
- }
- else if (fmt[i] == 'E')
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if (arc_needs_pcl_p (XVECEXP (x, i, j)))
- return true;
- }
-
- return false;
-}
-
-/* Return true if ADDR is an address that needs to be expressed as an
- explicit sum of pcl + offset. */
-
-bool
-arc_legitimate_pc_offset_p (rtx addr)
-{
- if (GET_CODE (addr) != CONST)
- return false;
-
- return arc_needs_pcl_p (addr);
-}
-
/* Return true if ADDR is a valid pic address.
A valid pic address on arc should look like
const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
@@ -5210,8 +5158,6 @@ arc_legitimate_pc_offset_p (rtx addr)
bool
arc_legitimate_pic_addr_p (rtx addr)
{
- if (GET_CODE (addr) == LABEL_REF)
- return true;
if (GET_CODE (addr) != CONST)
return false;
@@ -5915,16 +5861,6 @@ arc_return_addr_rtx (int count, ATTRIBUTE_UNUSED rtx frame)
return get_hard_reg_initial_val (Pmode , RETURN_ADDR_REGNUM);
}
-/* Nonzero if the constant value X is a legitimate general operand
- when generating PIC code. It is given that flag_pic is on and
- that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
-
-bool
-arc_legitimate_pic_operand_p (rtx x)
-{
- return !arc_raw_symbolic_reference_mentioned_p (x, true);
-}
-
/* Determine if a given RTX is a valid constant. We already know this
satisfies CONSTANT_P. */
@@ -5940,40 +5876,12 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
switch (GET_CODE (x))
{
case CONST:
- x = XEXP (x, 0);
-
- if (GET_CODE (x) == PLUS)
+ if (flag_pic)
{
- if (flag_pic
- ? GET_CODE (XEXP (x, 1)) != CONST_INT
- : !arc_legitimate_constant_p (mode, XEXP (x, 1)))
- return false;
- x = XEXP (x, 0);
- }
-
- /* Only some unspecs are valid as "constants". */
- if (GET_CODE (x) == UNSPEC)
- switch (XINT (x, 1))
- {
- case ARC_UNSPEC_PLT:
- case ARC_UNSPEC_GOTOFF:
- case ARC_UNSPEC_GOTOFFPC:
- case ARC_UNSPEC_GOT:
- case UNSPEC_TLS_GD:
- case UNSPEC_TLS_IE:
- case UNSPEC_TLS_OFF:
+ if (arc_legitimate_pic_addr_p (x))
return true;
-
- default:
- gcc_unreachable ();
- }
-
- /* We must have drilled down to a symbol. */
- if (arc_raw_symbolic_reference_mentioned_p (x, false))
- return false;
-
- /* Return true. */
- break;
+ }
+ return arc_legitimate_constant_p (mode, XEXP (x, 0));
case SYMBOL_REF:
if (SYMBOL_REF_TLS_MODEL (x))
@@ -5983,13 +5891,53 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
if (flag_pic)
return false;
/* Fall through. */
+ case CONST_INT:
+ case CONST_DOUBLE:
+ return true;
+
+ case NEG:
+ return arc_legitimate_constant_p (mode, XEXP (x, 0));
+
+ case PLUS:
+ case MINUS:
+ {
+ bool t1 = arc_legitimate_constant_p (mode, XEXP (x, 0));
+ bool t2 = arc_legitimate_constant_p (mode, XEXP (x, 1));
+
+ return (t1 && t2);
+ }
+
+ case CONST_VECTOR:
+ switch (mode)
+ {
+ case V2HImode:
+ return TARGET_PLUS_DMPY;
+ case V2SImode:
+ case V4HImode:
+ return TARGET_PLUS_QMACW;
+ default:
+ return false;
+ }
+
+ case UNSPEC:
+ switch (XINT (x, 1))
+ {
+ case UNSPEC_TLS_GD:
+ case UNSPEC_TLS_OFF:
+ case UNSPEC_TLS_IE:
+ return true;
+ default:
+ /* Any other unspec ending here are pic related, hence the above
+ constant pic address checking returned false. */
+ return false;
+ }
+ /* Fall through. */
default:
- break;
+ fatal_insn ("unrecognized supposed constant", x);
}
- /* Otherwise we handle everything else in the move patterns. */
- return true;
+ gcc_unreachable ();
}
static bool
@@ -6026,9 +5974,7 @@ arc_legitimate_address_p (machine_mode mode, rtx x, bool strict)
if ((GET_MODE_SIZE (mode) != 16) && CONSTANT_P (x))
{
- if (flag_pic ? arc_legitimate_pic_addr_p (x)
- : arc_legitimate_constant_p (Pmode, x))
- return true;
+ return arc_legitimate_constant_p (mode, x);
}
if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == PRE_INC
|| GET_CODE (x) == POST_DEC || GET_CODE (x) == POST_INC)
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index 585e98c..c7cd798 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -901,10 +901,10 @@ extern int arc_initial_elimination_offset(int from, int to);
a special predicate for the memory operand of stores, like for the SH. */
/* Recognize any constant value that is a valid address. */
-#define CONSTANT_ADDRESS_P(X) \
-(flag_pic?arc_legitimate_pic_addr_p (X): \
-(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST))
+#define CONSTANT_ADDRESS_P(X) \
+ (flag_pic ? (arc_legitimate_pic_addr_p (X) || LABEL_P (X)): \
+ (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
+ || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST))
/* Is the argument a const_int rtx, containing an exact power of 2 */
#define IS_POWEROF2_P(X) (! ( (X) & ((X) - 1)) && (X))
@@ -1083,7 +1083,8 @@ arc_select_cc_mode (OP, X, Y)
check it either. You need not define this macro if all constants
(including SYMBOL_REF) can be immediate operands when generating
position independent code. */
-#define LEGITIMATE_PIC_OPERAND_P(X) (arc_legitimate_pic_operand_p(X))
+#define LEGITIMATE_PIC_OPERAND_P(X) \
+ (!arc_raw_symbolic_reference_mentioned_p ((X), true))
/* PIC and small data don't mix on ARC because they use the same register. */
#define SDATA_BASE_REGNUM 26
diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
index edab41c..6620daf 100644
--- a/gcc/config/arc/constraints.md
+++ b/gcc/config/arc/constraints.md
@@ -403,7 +403,7 @@
(define_constraint "Cpc"
"pc-relative constant"
- (match_test "arc_legitimate_pc_offset_p (op)"))
+ (match_test "arc_legitimate_pic_addr_p (op)"))
(define_constraint "Clb"
"label"
@@ -412,12 +412,12 @@
(define_constraint "Cal"
"constant for arithmetic/logical operations"
- (match_test "immediate_operand (op, VOIDmode) && !arc_legitimate_pc_offset_p (op)"))
+ (match_test "immediate_operand (op, VOIDmode) && !arc_legitimate_pic_addr_p (op)"))
(define_constraint "C32"
"32 bit constant for arithmetic/logical operations"
(match_test "immediate_operand (op, VOIDmode)
- && !arc_legitimate_pc_offset_p (op)
+ && !arc_legitimate_pic_addr_p (op)
&& !satisfies_constraint_I (op)"))
; Note that the 'cryptic' register constraints will not make reload use the
diff --git a/gcc/testsuite/gcc.target/arc/pic-1.c b/gcc/testsuite/gcc.target/arc/pic-1.c
new file mode 100644
index 0000000..ab24763
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/pic-1.c
@@ -0,0 +1,11 @@
+/* Tests how complex pic constant expressions are handled. */
+/* { dg-do assemble } */
+/* { dg-skip-if "PIC not available for ARC6xx" { arc6xx } } */
+/* { dg-options "-mno-sdata -w -Os -fpic" } */
+
+a() {
+ char *b = "";
+ char c;
+ int d = &c - " \n\t\v\b\r\f\a/\0";
+ e(b[d]);
+}
diff --git a/gcc/testsuite/gcc.target/arc/pr9000674901.c b/gcc/testsuite/gcc.target/arc/pr9000674901.c
new file mode 100644
index 0000000..2a15c1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/pr9000674901.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! { clmcpu } } } */
+/* { dg-options "-mcpu=arc700 -O2 -fpic" } */
+
+/* Test if the compiler generates a constant address having that uses
+ a neg keyword on the pic unspec. */
+
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+typedef unsigned short int uint16_t;
+typedef unsigned long long int uint64_t;
+
+enum type {
+ t_undef = 0x01,
+ t_group = 0x02,
+ t_partition = 0x04,
+ t_spare = 0x08,
+ t_linear = 0x10,
+ t_raid0 = 0x20,
+ t_raid1 = 0x40,
+ t_raid4 = 0x80,
+ t_raid5_ls = 0x100,
+ t_raid5_rs = 0x200,
+ t_raid5_la = 0x400,
+ t_raid5_ra = 0x800,
+ t_raid6 = 0x1000,
+};
+
+struct raid_set {
+ enum type type;
+};
+
+void
+_find_factors (struct raid_set *rs, uint8_t * div, uint8_t * sub)
+{
+ struct factors {
+ const uint8_t level;
+ const uint8_t div, sub;
+ };
+ static struct factors factors[] = {
+ {0, 1, 0},
+ {1, 2, 0},
+ {2, 2, 0},
+ {5, 1, 1},
+ };
+ struct factors *f = (factors + (sizeof (factors) / sizeof (*factors)));
+
+ while (f-- > factors) {
+ if (rs->type == f->level) {
+ *div = f->div;
+ *sub = f->sub;
+ return;
+ }
+ }
+
+ *div = 1;
+ *sub = 0;
+}
diff --git a/gcc/testsuite/gcc.target/arc/pr9001191897.c b/gcc/testsuite/gcc.target/arc/pr9001191897.c
new file mode 100644
index 0000000..fc36426
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/pr9001191897.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! { clmcpu } } } */
+/* { dg-options "-mcpu=archs -Os -fpic -mno-sdata -mno-indexed-loads -w" } */
+a;
+c() {
+ static char b[25];
+ for (; a >= 0; a--)
+ if (b[a])
+ b[a] = '\0';
+}
--
1.9.1
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 7/7] [ARC] Consolidate PIC implementation.
2017-06-01 13:38 ` [PATCH 7/7] [ARC] Consolidate PIC implementation Claudiu Zissulescu
@ 2017-07-13 13:31 ` Andrew Burgess
2017-07-17 11:05 ` Claudiu Zissulescu
0 siblings, 1 reply; 27+ messages in thread
From: Andrew Burgess @ 2017-07-13 13:31 UTC (permalink / raw)
To: Claudiu Zissulescu; +Cc: gcc-patches, Francois.Bedard
* Claudiu Zissulescu <Claudiu.Zissulescu@synopsys.com> [2017-06-01 15:34:57 +0200]:
> This patch refactors a number of functions and compiler hooks into using a
> single function which checks if a rtx is suited for pic or not. Removed
> functions are arc_legitimate_pc_offset_p and arc_legitimate_pic_operand_p
> beeing replaced by calls to arc_legitimate_pic_addr_p. Thus we have an
> unitary way of checking a rtx beeing pic.
>
> gcc/
> 2017-02-24 Claudiu Zissulescu <claziss@synopsys.com>
>
> * config/arc/arc-protos.h (arc_legitimate_pc_offset_p): Remove
> proto.
> (arc_legitimate_pic_operand_p): Likewise.
> * config/arc/arc.c (arc_legitimate_pic_operand_p): Remove
> function.
> (arc_needs_pcl_p): Likewise.
> (arc_legitimate_pc_offset_p): Likewise.
> (arc_legitimate_pic_addr_p): Remove LABEL_REF case, as this
> function is also used in constrains.md.
> (arc_legitimate_constant_p): Use arc_legitimate_pic_addr_p to
> validate pic constants. Handle CONST_INT, CONST_DOUBLE, MINUS and
> PLUS. Only return true/false in known cases, otherwise assert.
> (arc_legitimate_address_p): Remove arc_legitimate_pic_addr_p as it
> is already called in arc_legitimate_constant_p.
> * config/arc/arc.h (CONSTANT_ADDRESS_P): Consider also LABEL for
> pic addresses.
> (LEGITIMATE_PIC_OPERAND_P): Use
> arc_raw_symbolic_reference_mentioned_p function.
> * config/arc/constraints.md (Cpc): Use arc_legitimate_pic_addr_p
> function.
> (Cal): Likewise.
> (C32): Likewise.
>
> gcc/testsuite
> 2017-02-24 Claudiu Zissulescu <claziss@synopsys.com>
>
> * gcc.target/arc/pr9000674901.c: New file.
> * gcc.target/arc/pic-1.c: Likewise.
> * gcc.target/arc/pr9001191897.c: Likewise.
Looks like a good clean up.
Thanks,
Andrew
> ---
> gcc/config/arc/arc-protos.h | 2 -
> gcc/config/arc/arc.c | 150 +++++++++-------------------
> gcc/config/arc/arc.h | 11 +-
> gcc/config/arc/constraints.md | 6 +-
> gcc/testsuite/gcc.target/arc/pic-1.c | 11 ++
> gcc/testsuite/gcc.target/arc/pr9000674901.c | 58 +++++++++++
> gcc/testsuite/gcc.target/arc/pr9001191897.c | 10 ++
> 7 files changed, 136 insertions(+), 112 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/arc/pic-1.c
> create mode 100644 gcc/testsuite/gcc.target/arc/pr9000674901.c
> create mode 100644 gcc/testsuite/gcc.target/arc/pr9001191897.c
>
> diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
> index b436dbe..850795a 100644
> --- a/gcc/config/arc/arc-protos.h
> +++ b/gcc/config/arc/arc-protos.h
> @@ -60,10 +60,8 @@ extern rtx arc_return_addr_rtx (int , rtx);
> extern bool check_if_valid_regno_const (rtx *, int);
> extern bool check_if_valid_sleep_operand (rtx *, int);
> extern bool arc_legitimate_constant_p (machine_mode, rtx);
> -extern bool arc_legitimate_pc_offset_p (rtx);
> extern bool arc_legitimate_pic_addr_p (rtx);
> extern bool arc_raw_symbolic_reference_mentioned_p (rtx, bool);
> -extern bool arc_legitimate_pic_operand_p (rtx);
> extern bool arc_is_longcall_p (rtx);
> extern bool arc_is_shortcall_p (rtx);
> extern bool valid_brcc_with_delay_p (rtx *);
> diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
> index 7dfc68e..89de6cd 100644
> --- a/gcc/config/arc/arc.c
> +++ b/gcc/config/arc/arc.c
> @@ -249,7 +249,6 @@ static rtx arc_expand_builtin (tree, rtx, rtx, machine_mode, int);
> static int branch_dest (rtx);
>
> static void arc_output_pic_addr_const (FILE *, rtx, int);
> -bool arc_legitimate_pic_operand_p (rtx);
> static bool arc_function_ok_for_sibcall (tree, tree);
> static rtx arc_function_value (const_tree, const_tree, bool);
> const char * output_shift (rtx *);
> @@ -5152,57 +5151,6 @@ arc_rtx_costs (rtx x, machine_mode mode, int outer_code,
> }
> }
>
> -/* Helper used by arc_legitimate_pc_offset_p. */
> -
> -static bool
> -arc_needs_pcl_p (rtx x)
> -{
> - register const char *fmt;
> - register int i, j;
> -
> - if ((GET_CODE (x) == UNSPEC)
> - && (XVECLEN (x, 0) == 1)
> - && (GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF))
> - switch (XINT (x, 1))
> - {
> - case ARC_UNSPEC_GOT:
> - case ARC_UNSPEC_GOTOFFPC:
> - case UNSPEC_TLS_GD:
> - case UNSPEC_TLS_IE:
> - return true;
> - default:
> - break;
> - }
> -
> - fmt = GET_RTX_FORMAT (GET_CODE (x));
> - for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
> - {
> - if (fmt[i] == 'e')
> - {
> - if (arc_needs_pcl_p (XEXP (x, i)))
> - return true;
> - }
> - else if (fmt[i] == 'E')
> - for (j = XVECLEN (x, i) - 1; j >= 0; j--)
> - if (arc_needs_pcl_p (XVECEXP (x, i, j)))
> - return true;
> - }
> -
> - return false;
> -}
> -
> -/* Return true if ADDR is an address that needs to be expressed as an
> - explicit sum of pcl + offset. */
> -
> -bool
> -arc_legitimate_pc_offset_p (rtx addr)
> -{
> - if (GET_CODE (addr) != CONST)
> - return false;
> -
> - return arc_needs_pcl_p (addr);
> -}
> -
> /* Return true if ADDR is a valid pic address.
> A valid pic address on arc should look like
> const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
> @@ -5210,8 +5158,6 @@ arc_legitimate_pc_offset_p (rtx addr)
> bool
> arc_legitimate_pic_addr_p (rtx addr)
> {
> - if (GET_CODE (addr) == LABEL_REF)
> - return true;
> if (GET_CODE (addr) != CONST)
> return false;
>
> @@ -5915,16 +5861,6 @@ arc_return_addr_rtx (int count, ATTRIBUTE_UNUSED rtx frame)
> return get_hard_reg_initial_val (Pmode , RETURN_ADDR_REGNUM);
> }
>
> -/* Nonzero if the constant value X is a legitimate general operand
> - when generating PIC code. It is given that flag_pic is on and
> - that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
> -
> -bool
> -arc_legitimate_pic_operand_p (rtx x)
> -{
> - return !arc_raw_symbolic_reference_mentioned_p (x, true);
> -}
> -
> /* Determine if a given RTX is a valid constant. We already know this
> satisfies CONSTANT_P. */
>
> @@ -5940,40 +5876,12 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
> switch (GET_CODE (x))
> {
> case CONST:
> - x = XEXP (x, 0);
> -
> - if (GET_CODE (x) == PLUS)
> + if (flag_pic)
> {
> - if (flag_pic
> - ? GET_CODE (XEXP (x, 1)) != CONST_INT
> - : !arc_legitimate_constant_p (mode, XEXP (x, 1)))
> - return false;
> - x = XEXP (x, 0);
> - }
> -
> - /* Only some unspecs are valid as "constants". */
> - if (GET_CODE (x) == UNSPEC)
> - switch (XINT (x, 1))
> - {
> - case ARC_UNSPEC_PLT:
> - case ARC_UNSPEC_GOTOFF:
> - case ARC_UNSPEC_GOTOFFPC:
> - case ARC_UNSPEC_GOT:
> - case UNSPEC_TLS_GD:
> - case UNSPEC_TLS_IE:
> - case UNSPEC_TLS_OFF:
> + if (arc_legitimate_pic_addr_p (x))
> return true;
> -
> - default:
> - gcc_unreachable ();
> - }
> -
> - /* We must have drilled down to a symbol. */
> - if (arc_raw_symbolic_reference_mentioned_p (x, false))
> - return false;
> -
> - /* Return true. */
> - break;
> + }
> + return arc_legitimate_constant_p (mode, XEXP (x, 0));
>
> case SYMBOL_REF:
> if (SYMBOL_REF_TLS_MODEL (x))
> @@ -5983,13 +5891,53 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
> if (flag_pic)
> return false;
> /* Fall through. */
> + case CONST_INT:
> + case CONST_DOUBLE:
> + return true;
> +
> + case NEG:
> + return arc_legitimate_constant_p (mode, XEXP (x, 0));
> +
> + case PLUS:
> + case MINUS:
> + {
> + bool t1 = arc_legitimate_constant_p (mode, XEXP (x, 0));
> + bool t2 = arc_legitimate_constant_p (mode, XEXP (x, 1));
> +
> + return (t1 && t2);
> + }
> +
> + case CONST_VECTOR:
> + switch (mode)
> + {
> + case V2HImode:
> + return TARGET_PLUS_DMPY;
> + case V2SImode:
> + case V4HImode:
> + return TARGET_PLUS_QMACW;
> + default:
> + return false;
> + }
> +
> + case UNSPEC:
> + switch (XINT (x, 1))
> + {
> + case UNSPEC_TLS_GD:
> + case UNSPEC_TLS_OFF:
> + case UNSPEC_TLS_IE:
> + return true;
> + default:
> + /* Any other unspec ending here are pic related, hence the above
> + constant pic address checking returned false. */
> + return false;
> + }
> + /* Fall through. */
>
> default:
> - break;
> + fatal_insn ("unrecognized supposed constant", x);
> }
>
> - /* Otherwise we handle everything else in the move patterns. */
> - return true;
> + gcc_unreachable ();
> }
>
> static bool
> @@ -6026,9 +5974,7 @@ arc_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>
> if ((GET_MODE_SIZE (mode) != 16) && CONSTANT_P (x))
> {
> - if (flag_pic ? arc_legitimate_pic_addr_p (x)
> - : arc_legitimate_constant_p (Pmode, x))
> - return true;
> + return arc_legitimate_constant_p (mode, x);
> }
> if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == PRE_INC
> || GET_CODE (x) == POST_DEC || GET_CODE (x) == POST_INC)
> diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
> index 585e98c..c7cd798 100644
> --- a/gcc/config/arc/arc.h
> +++ b/gcc/config/arc/arc.h
> @@ -901,10 +901,10 @@ extern int arc_initial_elimination_offset(int from, int to);
> a special predicate for the memory operand of stores, like for the SH. */
>
> /* Recognize any constant value that is a valid address. */
> -#define CONSTANT_ADDRESS_P(X) \
> -(flag_pic?arc_legitimate_pic_addr_p (X): \
> -(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
> - || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST))
> +#define CONSTANT_ADDRESS_P(X) \
> + (flag_pic ? (arc_legitimate_pic_addr_p (X) || LABEL_P (X)): \
> + (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
> + || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST))
>
> /* Is the argument a const_int rtx, containing an exact power of 2 */
> #define IS_POWEROF2_P(X) (! ( (X) & ((X) - 1)) && (X))
> @@ -1083,7 +1083,8 @@ arc_select_cc_mode (OP, X, Y)
> check it either. You need not define this macro if all constants
> (including SYMBOL_REF) can be immediate operands when generating
> position independent code. */
> -#define LEGITIMATE_PIC_OPERAND_P(X) (arc_legitimate_pic_operand_p(X))
> +#define LEGITIMATE_PIC_OPERAND_P(X) \
> + (!arc_raw_symbolic_reference_mentioned_p ((X), true))
>
> /* PIC and small data don't mix on ARC because they use the same register. */
> #define SDATA_BASE_REGNUM 26
> diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
> index edab41c..6620daf 100644
> --- a/gcc/config/arc/constraints.md
> +++ b/gcc/config/arc/constraints.md
> @@ -403,7 +403,7 @@
>
> (define_constraint "Cpc"
> "pc-relative constant"
> - (match_test "arc_legitimate_pc_offset_p (op)"))
> + (match_test "arc_legitimate_pic_addr_p (op)"))
>
> (define_constraint "Clb"
> "label"
> @@ -412,12 +412,12 @@
>
> (define_constraint "Cal"
> "constant for arithmetic/logical operations"
> - (match_test "immediate_operand (op, VOIDmode) && !arc_legitimate_pc_offset_p (op)"))
> + (match_test "immediate_operand (op, VOIDmode) && !arc_legitimate_pic_addr_p (op)"))
>
> (define_constraint "C32"
> "32 bit constant for arithmetic/logical operations"
> (match_test "immediate_operand (op, VOIDmode)
> - && !arc_legitimate_pc_offset_p (op)
> + && !arc_legitimate_pic_addr_p (op)
> && !satisfies_constraint_I (op)"))
>
> ; Note that the 'cryptic' register constraints will not make reload use the
> diff --git a/gcc/testsuite/gcc.target/arc/pic-1.c b/gcc/testsuite/gcc.target/arc/pic-1.c
> new file mode 100644
> index 0000000..ab24763
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/pic-1.c
> @@ -0,0 +1,11 @@
> +/* Tests how complex pic constant expressions are handled. */
> +/* { dg-do assemble } */
> +/* { dg-skip-if "PIC not available for ARC6xx" { arc6xx } } */
> +/* { dg-options "-mno-sdata -w -Os -fpic" } */
> +
> +a() {
> + char *b = "";
> + char c;
> + int d = &c - " \n\t\v\b\r\f\a/\0";
> + e(b[d]);
> +}
> diff --git a/gcc/testsuite/gcc.target/arc/pr9000674901.c b/gcc/testsuite/gcc.target/arc/pr9000674901.c
> new file mode 100644
> index 0000000..2a15c1c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/pr9000674901.c
> @@ -0,0 +1,58 @@
> +/* { dg-do compile } */
> +/* { dg-skip-if "" { ! { clmcpu } } } */
> +/* { dg-options "-mcpu=arc700 -O2 -fpic" } */
> +
> +/* Test if the compiler generates a constant address having that uses
> + a neg keyword on the pic unspec. */
> +
> +typedef unsigned int uint32_t;
> +typedef unsigned char uint8_t;
> +typedef unsigned short int uint16_t;
> +typedef unsigned long long int uint64_t;
> +
> +enum type {
> + t_undef = 0x01,
> + t_group = 0x02,
> + t_partition = 0x04,
> + t_spare = 0x08,
> + t_linear = 0x10,
> + t_raid0 = 0x20,
> + t_raid1 = 0x40,
> + t_raid4 = 0x80,
> + t_raid5_ls = 0x100,
> + t_raid5_rs = 0x200,
> + t_raid5_la = 0x400,
> + t_raid5_ra = 0x800,
> + t_raid6 = 0x1000,
> +};
> +
> +struct raid_set {
> + enum type type;
> +};
> +
> +void
> +_find_factors (struct raid_set *rs, uint8_t * div, uint8_t * sub)
> +{
> + struct factors {
> + const uint8_t level;
> + const uint8_t div, sub;
> + };
> + static struct factors factors[] = {
> + {0, 1, 0},
> + {1, 2, 0},
> + {2, 2, 0},
> + {5, 1, 1},
> + };
> + struct factors *f = (factors + (sizeof (factors) / sizeof (*factors)));
> +
> + while (f-- > factors) {
> + if (rs->type == f->level) {
> + *div = f->div;
> + *sub = f->sub;
> + return;
> + }
> + }
> +
> + *div = 1;
> + *sub = 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/arc/pr9001191897.c b/gcc/testsuite/gcc.target/arc/pr9001191897.c
> new file mode 100644
> index 0000000..fc36426
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/pr9001191897.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-skip-if "" { ! { clmcpu } } } */
> +/* { dg-options "-mcpu=archs -Os -fpic -mno-sdata -mno-indexed-loads -w" } */
> +a;
> +c() {
> + static char b[25];
> + for (; a >= 0; a--)
> + if (b[a])
> + b[a] = '\0';
> +}
> --
> 1.9.1
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 6/7] [ARC] Deprecate mexpand-adddi option.
2017-06-01 13:37 [PATCH 0/7] [ARC] Bug fixing, add support for naked functions Claudiu Zissulescu
` (3 preceding siblings ...)
2017-06-01 13:38 ` [PATCH 7/7] [ARC] Consolidate PIC implementation Claudiu Zissulescu
@ 2017-06-01 13:38 ` Claudiu Zissulescu
2017-07-13 13:18 ` Andrew Burgess
2017-06-01 13:38 ` [PATCH 1/7] [ARC] Add support for naked functions Claudiu Zissulescu
2017-06-01 13:38 ` [PATCH 5/7] [ARC] Enable indexed loads for elf targers Claudiu Zissulescu
6 siblings, 1 reply; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-06-01 13:38 UTC (permalink / raw)
To: gcc-patches; +Cc: Claudiu.Zissulescu, Francois.Bedard, andrew.burgess
From: claziss <claziss@synopsys.com>
Emitting subregs in the expand is not a good idea. Deprecate this
option.
gcc/
2017-04-26 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/arc.md (adddi3): Remove support for mexpand-adddi
option.
(subdi3): Likewise.
* config/arc/arc.opt (mexpand-adddi): Deprecate it.
* doc/invoke.texi (mexpand-adddi): Update text.
---
gcc/config/arc/arc.md | 39 +--------------------------------------
gcc/config/arc/arc.opt | 2 +-
gcc/doc/invoke.texi | 2 +-
3 files changed, 3 insertions(+), 40 deletions(-)
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 928feb1..f595da7 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -2649,30 +2649,7 @@
(match_operand:DI 2 "nonmemory_operand" "")))
(clobber (reg:CC CC_REG))])]
""
-{
- if (TARGET_EXPAND_ADDDI)
- {
- rtx l0 = gen_lowpart (SImode, operands[0]);
- rtx h0 = disi_highpart (operands[0]);
- rtx l1 = gen_lowpart (SImode, operands[1]);
- rtx h1 = disi_highpart (operands[1]);
- rtx l2 = gen_lowpart (SImode, operands[2]);
- rtx h2 = disi_highpart (operands[2]);
- rtx cc_c = gen_rtx_REG (CC_Cmode, CC_REG);
-
- if (CONST_INT_P (h2) && INTVAL (h2) < 0 && SIGNED_INT12 (INTVAL (h2)))
- {
- emit_insn (gen_sub_f (l0, l1, gen_int_mode (-INTVAL (l2), SImode)));
- emit_insn (gen_sbc (h0, h1,
- gen_int_mode (-INTVAL (h2) - (l1 != 0), SImode),
- cc_c));
- DONE;
- }
- emit_insn (gen_add_f (l0, l1, l2));
- emit_insn (gen_adc (h0, h1, h2));
- DONE;
- }
-})
+{})
; This assumes that there can be no strictly partial overlap between
; operands[1] and operands[2].
@@ -2911,20 +2888,6 @@
{
if (!register_operand (operands[2], DImode))
operands[1] = force_reg (DImode, operands[1]);
- if (TARGET_EXPAND_ADDDI)
- {
- rtx l0 = gen_lowpart (SImode, operands[0]);
- rtx h0 = disi_highpart (operands[0]);
- rtx l1 = gen_lowpart (SImode, operands[1]);
- rtx h1 = disi_highpart (operands[1]);
- rtx l2 = gen_lowpart (SImode, operands[2]);
- rtx h2 = disi_highpart (operands[2]);
- rtx cc_c = gen_rtx_REG (CC_Cmode, CC_REG);
-
- emit_insn (gen_sub_f (l0, l1, l2));
- emit_insn (gen_sbc (h0, h1, h2, cc_c));
- DONE;
- }
})
(define_insn_and_split "subdi3_i"
diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
index ed2b827..ad2df26 100644
--- a/gcc/config/arc/arc.opt
+++ b/gcc/config/arc/arc.opt
@@ -328,7 +328,7 @@ Target Var(TARGET_Q_CLASS)
Enable 'q' instruction alternatives.
mexpand-adddi
-Target Var(TARGET_EXPAND_ADDDI)
+Target Warn(%qs is deprecated)
Expand adddi3 and subdi3 at rtl generation time into add.f / adc etc.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 59563aa..b6cf4ce 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -14823,7 +14823,7 @@ Enable pre-reload use of the @code{cbranchsi} pattern.
@item -mexpand-adddi
@opindex mexpand-adddi
Expand @code{adddi3} and @code{subdi3} at RTL generation time into
-@code{add.f}, @code{adc} etc.
+@code{add.f}, @code{adc} etc. This option is deprecated.
@item -mindexed-loads
@opindex mindexed-loads
--
1.9.1
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 6/7] [ARC] Deprecate mexpand-adddi option.
2017-06-01 13:38 ` [PATCH 6/7] [ARC] Deprecate mexpand-adddi option Claudiu Zissulescu
@ 2017-07-13 13:18 ` Andrew Burgess
2017-07-13 13:31 ` Claudiu Zissulescu
2017-07-17 13:01 ` Claudiu Zissulescu
0 siblings, 2 replies; 27+ messages in thread
From: Andrew Burgess @ 2017-07-13 13:18 UTC (permalink / raw)
To: Claudiu Zissulescu; +Cc: gcc-patches, Francois.Bedard
* Claudiu Zissulescu <Claudiu.Zissulescu@synopsys.com> [2017-06-01 15:34:56 +0200]:
> From: claziss <claziss@synopsys.com>
>
> Emitting subregs in the expand is not a good idea. Deprecate this
> option.
>
> gcc/
> 2017-04-26 Claudiu Zissulescu <claziss@synopsys.com>
>
> * config/arc/arc.md (adddi3): Remove support for mexpand-adddi
> option.
> (subdi3): Likewise.
> * config/arc/arc.opt (mexpand-adddi): Deprecate it.
> * doc/invoke.texi (mexpand-adddi): Update text.
This looks fine, though the commit message tells me it's not a good
idea, but it would be nice to know _why_ it's not good. Might be nice
to know for future reference.
Also, there's no test. Was there an issue that revealed this as not a
good idea? Could that become a test?
Thanks,
Andrew
> ---
> gcc/config/arc/arc.md | 39 +--------------------------------------
> gcc/config/arc/arc.opt | 2 +-
> gcc/doc/invoke.texi | 2 +-
> 3 files changed, 3 insertions(+), 40 deletions(-)
>
> diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
> index 928feb1..f595da7 100644
> --- a/gcc/config/arc/arc.md
> +++ b/gcc/config/arc/arc.md
> @@ -2649,30 +2649,7 @@
> (match_operand:DI 2 "nonmemory_operand" "")))
> (clobber (reg:CC CC_REG))])]
> ""
> -{
> - if (TARGET_EXPAND_ADDDI)
> - {
> - rtx l0 = gen_lowpart (SImode, operands[0]);
> - rtx h0 = disi_highpart (operands[0]);
> - rtx l1 = gen_lowpart (SImode, operands[1]);
> - rtx h1 = disi_highpart (operands[1]);
> - rtx l2 = gen_lowpart (SImode, operands[2]);
> - rtx h2 = disi_highpart (operands[2]);
> - rtx cc_c = gen_rtx_REG (CC_Cmode, CC_REG);
> -
> - if (CONST_INT_P (h2) && INTVAL (h2) < 0 && SIGNED_INT12 (INTVAL (h2)))
> - {
> - emit_insn (gen_sub_f (l0, l1, gen_int_mode (-INTVAL (l2), SImode)));
> - emit_insn (gen_sbc (h0, h1,
> - gen_int_mode (-INTVAL (h2) - (l1 != 0), SImode),
> - cc_c));
> - DONE;
> - }
> - emit_insn (gen_add_f (l0, l1, l2));
> - emit_insn (gen_adc (h0, h1, h2));
> - DONE;
> - }
> -})
> +{})
>
> ; This assumes that there can be no strictly partial overlap between
> ; operands[1] and operands[2].
> @@ -2911,20 +2888,6 @@
> {
> if (!register_operand (operands[2], DImode))
> operands[1] = force_reg (DImode, operands[1]);
> - if (TARGET_EXPAND_ADDDI)
> - {
> - rtx l0 = gen_lowpart (SImode, operands[0]);
> - rtx h0 = disi_highpart (operands[0]);
> - rtx l1 = gen_lowpart (SImode, operands[1]);
> - rtx h1 = disi_highpart (operands[1]);
> - rtx l2 = gen_lowpart (SImode, operands[2]);
> - rtx h2 = disi_highpart (operands[2]);
> - rtx cc_c = gen_rtx_REG (CC_Cmode, CC_REG);
> -
> - emit_insn (gen_sub_f (l0, l1, l2));
> - emit_insn (gen_sbc (h0, h1, h2, cc_c));
> - DONE;
> - }
> })
>
> (define_insn_and_split "subdi3_i"
> diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
> index ed2b827..ad2df26 100644
> --- a/gcc/config/arc/arc.opt
> +++ b/gcc/config/arc/arc.opt
> @@ -328,7 +328,7 @@ Target Var(TARGET_Q_CLASS)
> Enable 'q' instruction alternatives.
>
> mexpand-adddi
> -Target Var(TARGET_EXPAND_ADDDI)
> +Target Warn(%qs is deprecated)
> Expand adddi3 and subdi3 at rtl generation time into add.f / adc etc.
>
>
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 59563aa..b6cf4ce 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -14823,7 +14823,7 @@ Enable pre-reload use of the @code{cbranchsi} pattern.
> @item -mexpand-adddi
> @opindex mexpand-adddi
> Expand @code{adddi3} and @code{subdi3} at RTL generation time into
> -@code{add.f}, @code{adc} etc.
> +@code{add.f}, @code{adc} etc. This option is deprecated.
>
> @item -mindexed-loads
> @opindex mindexed-loads
> --
> 1.9.1
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: [PATCH 6/7] [ARC] Deprecate mexpand-adddi option.
2017-07-13 13:18 ` Andrew Burgess
@ 2017-07-13 13:31 ` Claudiu Zissulescu
2017-07-17 13:01 ` Claudiu Zissulescu
1 sibling, 0 replies; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-07-13 13:31 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gcc-patches, Francois.Bedard
>
> This looks fine, though the commit message tells me it's not a good
> idea, but it would be nice to know _why_ it's not good. Might be nice
> to know for future reference.
>
Again LRA, expand time subregs are not handled by LRA, as far as I can tell. Moreover, this option is by default off, and even using the old IRA may not be a good idea to have subregs before register allocation step.
> Also, there's no test. Was there an issue that revealed this as not a
> good idea? Could that become a test?
>
This error was found while running dg for our port with LRA on and this option on. Once removed the mexpand-adddi, a test is impossible to get.
Thanks,
Claudiu
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: [PATCH 6/7] [ARC] Deprecate mexpand-adddi option.
2017-07-13 13:18 ` Andrew Burgess
2017-07-13 13:31 ` Claudiu Zissulescu
@ 2017-07-17 13:01 ` Claudiu Zissulescu
1 sibling, 0 replies; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-07-17 13:01 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gcc-patches, Francois.Bedard
> This looks fine, though the commit message tells me it's not a good
> idea, but it would be nice to know _why_ it's not good. Might be nice
> to know for future reference.
Committed with additional comments. Thank you,
Claudiu
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 1/7] [ARC] Add support for naked functions.
2017-06-01 13:37 [PATCH 0/7] [ARC] Bug fixing, add support for naked functions Claudiu Zissulescu
` (4 preceding siblings ...)
2017-06-01 13:38 ` [PATCH 6/7] [ARC] Deprecate mexpand-adddi option Claudiu Zissulescu
@ 2017-06-01 13:38 ` Claudiu Zissulescu
2017-06-16 19:36 ` Andrew Burgess
2017-06-01 13:38 ` [PATCH 5/7] [ARC] Enable indexed loads for elf targers Claudiu Zissulescu
6 siblings, 1 reply; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-06-01 13:38 UTC (permalink / raw)
To: gcc-patches; +Cc: Claudiu.Zissulescu, Francois.Bedard, andrew.burgess
gcc/
2016-12-13 Claudiu Zissulescu <claziss@synopsys.com>
Andrew Burgess <andrew.burgess@embecosm.com>
* config/arc/arc-protos.h (arc_compute_function_type): Change prototype.
(arc_return_address_register): New function.
* config/arc/arc.c (arc_handle_fndecl_attribute): New function.
(arc_handle_fndecl_attribute): Add naked attribute.
(TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS): Define.
(TARGET_WARN_FUNC_RETURN): Likewise.
(arc_allocate_stack_slots_for_args): New function.
(arc_warn_func_return): Likewise.
(machine_function): Change type fn_type.
(arc_compute_function_type): Consider new naked function type,
change function return type.
(arc_must_save_register): Adapt to handle new
arc_compute_function_type's return type.
(arc_expand_prologue): Likewise.
(arc_expand_epilogue): Likewise.
(arc_return_address_regs): Delete.
(arc_return_address_register): New function.
(arc_epilogue_uses): Use above function.
* config/arc/arc.h (arc_return_address_regs): Delete prototype.
(arc_function_type): Change encoding, add naked type.
(ARC_INTERRUPT_P): Change to handle the new encoding.
(ARC_FAST_INTERRUPT_P): Likewise.
(ARC_NORMAL_P): Define.
(ARC_NAKED_P): Likewise.
(arc_compute_function_type): Delete prototype.
* config/arc/arc.md (in_ret_delay_slot): Use
arc_return_address_register function.
(simple_return): Likewise.
(p_return_i): Likewise.
gcc/testsuite
2016-12-13 Claudiu Zissulescu <claziss@synopsys.com>
Andrew Burgess <andrew.burgess@embecosm.com>
* gcc.target/arc/naked-1.c: New file.
* gcc.target/arc/naked-2.c: Likewise.
---
gcc/config/arc/arc-protos.h | 6 +-
gcc/config/arc/arc.c | 165 ++++++++++++++++++++++++---------
gcc/config/arc/arc.h | 40 +++++---
gcc/config/arc/arc.md | 10 +-
gcc/testsuite/gcc.target/arc/naked-1.c | 18 ++++
gcc/testsuite/gcc.target/arc/naked-2.c | 26 ++++++
6 files changed, 197 insertions(+), 68 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/arc/naked-1.c
create mode 100644 gcc/testsuite/gcc.target/arc/naked-2.c
diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index 4ff8e9b..b436dbe 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -45,12 +45,10 @@ extern void arc_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
extern void arc_split_compare_and_swap (rtx *);
extern void arc_expand_compare_and_swap (rtx *);
extern bool compact_memory_operand_p (rtx, machine_mode, bool, bool);
+extern int arc_return_address_register (unsigned int);
+extern unsigned int arc_compute_function_type (struct function *);
#endif /* RTX_CODE */
-#ifdef TREE_CODE
-extern enum arc_function_type arc_compute_function_type (struct function *);
-#endif /* TREE_CODE */
-
extern bool arc_ccfsm_branch_deleted_p (void);
extern void arc_ccfsm_record_branch_deleted (void);
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index a65fc3a..7dfc68e 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -211,6 +211,7 @@ static int rgf_banked_register_count;
static int get_arc_condition_code (rtx);
static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
+static tree arc_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
/* Initialized arc_attribute_table to NULL since arc doesnot have any
machine specific supported attributes. */
@@ -229,6 +230,9 @@ const struct attribute_spec arc_attribute_table[] =
/* And these functions are always known to reside within the 21 bit
addressing range of blcc. */
{ "short_call", 0, 0, false, true, true, NULL, false },
+ /* Function which are not having the prologue and epilogue generated
+ by the compiler. */
+ { "naked", 0, 0, true, false, false, arc_handle_fndecl_attribute, false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
static int arc_comp_type_attributes (const_tree, const_tree);
@@ -513,6 +517,12 @@ static void arc_finalize_pic (void);
#define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
#define TARGET_SPILL_CLASS arc_spill_class
+#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
+#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS arc_allocate_stack_slots_for_args
+
+#undef TARGET_WARN_FUNC_RETURN
+#define TARGET_WARN_FUNC_RETURN arc_warn_func_return
+
#include "target-def.h"
#undef TARGET_ASM_ALIGNED_HI_OP
@@ -1859,6 +1869,42 @@ arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
return NULL_TREE;
}
+static tree
+arc_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute only applies to functions",
+ name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
+
+static bool
+arc_allocate_stack_slots_for_args (void)
+{
+ /* Naked functions should not allocate stack slots for arguments. */
+ unsigned int fn_type = arc_compute_function_type (cfun);
+
+ return !ARC_NAKED_P(fn_type);
+}
+
+/* Implement `TARGET_WARN_FUNC_RETURN'. */
+
+static bool
+arc_warn_func_return (tree decl)
+{
+ struct function *func = DECL_STRUCT_FUNCTION (decl);
+ unsigned int fn_type = arc_compute_function_type (func);
+
+ return !ARC_NAKED_P (fn_type);
+}
+
/* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
and two if they are nearly compatible (which causes a warning to be
generated). */
@@ -2362,7 +2408,7 @@ struct GTY (()) arc_frame_info
typedef struct GTY (()) machine_function
{
- enum arc_function_type fn_type;
+ unsigned int fn_type;
struct arc_frame_info frame_info;
/* To keep track of unalignment caused by short insns. */
int unalign;
@@ -2380,43 +2426,40 @@ typedef struct GTY (()) machine_function
The result is cached. To reset the cache at the end of a function,
call with DECL = NULL_TREE. */
-enum arc_function_type
+unsigned int
arc_compute_function_type (struct function *fun)
{
- tree decl = fun->decl;
- tree a;
- enum arc_function_type fn_type = fun->machine->fn_type;
+ tree attr, decl = fun->decl;
+ unsigned int fn_type = fun->machine->fn_type;
if (fn_type != ARC_FUNCTION_UNKNOWN)
return fn_type;
- /* Assume we have a normal function (not an interrupt handler). */
- fn_type = ARC_FUNCTION_NORMAL;
+ /* Check if it is a naked function. */
+ if (lookup_attribute ("naked", DECL_ATTRIBUTES (decl)) != NULL_TREE)
+ fn_type |= ARC_FUNCTION_NAKED;
+ else
+ fn_type |= ARC_FUNCTION_NORMAL;
/* Now see if this is an interrupt handler. */
- for (a = DECL_ATTRIBUTES (decl);
- a;
- a = TREE_CHAIN (a))
- {
- tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
-
- if (name == get_identifier ("interrupt")
- && list_length (args) == 1
- && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
- {
- tree value = TREE_VALUE (args);
-
- if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
- || !strcmp (TREE_STRING_POINTER (value), "ilink"))
- fn_type = ARC_FUNCTION_ILINK1;
- else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
- fn_type = ARC_FUNCTION_ILINK2;
- else if (!strcmp (TREE_STRING_POINTER (value), "firq"))
- fn_type = ARC_FUNCTION_FIRQ;
- else
- gcc_unreachable ();
- break;
- }
+ attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
+ if (attr != NULL_TREE)
+ {
+ tree value, args = TREE_VALUE (attr);
+
+ gcc_assert (list_length (args) == 1);
+ value = TREE_VALUE (args);
+ gcc_assert (TREE_CODE (value) == STRING_CST);
+
+ if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
+ || !strcmp (TREE_STRING_POINTER (value), "ilink"))
+ fn_type |= ARC_FUNCTION_ILINK1;
+ else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
+ fn_type |= ARC_FUNCTION_ILINK2;
+ else if (!strcmp (TREE_STRING_POINTER (value), "firq"))
+ fn_type |= ARC_FUNCTION_FIRQ;
+ else
+ gcc_unreachable ();
}
return fun->machine->fn_type = fn_type;
@@ -2436,7 +2479,7 @@ arc_compute_function_type (struct function *fun)
static bool
arc_must_save_register (int regno, struct function *func)
{
- enum arc_function_type fn_type = arc_compute_function_type (func);
+ unsigned int fn_type = arc_compute_function_type (func);
bool irq_auto_save_p = ((irq_ctrl_saved.irq_save_last_reg >= regno)
&& ARC_AUTO_IRQ_P (fn_type));
bool firq_auto_save_p = ARC_FAST_INTERRUPT_P (fn_type);
@@ -2945,7 +2988,11 @@ arc_expand_prologue (void)
Change the stack layout so that we rather store a high register with the
PRE_MODIFY, thus enabling more short insn generation.) */
int first_offset = 0;
- enum arc_function_type fn_type = arc_compute_function_type (cfun);
+ unsigned int fn_type = arc_compute_function_type (cfun);
+
+ /* Naked functions don't have prologue. */
+ if (ARC_NAKED_P (fn_type))
+ return;
/* Compute total frame size. */
size = arc_compute_frame_size ();
@@ -3052,10 +3099,7 @@ void
arc_expand_epilogue (int sibcall_p)
{
int size;
- enum arc_function_type fn_type = arc_compute_function_type (cfun);
-
- size = arc_compute_frame_size ();
-
+ unsigned int fn_type = arc_compute_function_type (cfun);
unsigned int pretend_size = cfun->machine->frame_info.pretend_size;
unsigned int frame_size;
unsigned int size_to_deallocate;
@@ -3065,6 +3109,12 @@ arc_expand_epilogue (int sibcall_p)
int millicode_p = cfun->machine->frame_info.millicode_end_reg > 0;
rtx insn;
+ /* Naked functions don't have epilogue. */
+ if (ARC_NAKED_P (fn_type))
+ return;
+
+ size = arc_compute_frame_size ();
+
size_to_deallocate = size;
frame_size = size - (pretend_size +
@@ -9886,37 +9936,60 @@ arc_can_follow_jump (const rtx_insn *follower, const rtx_insn *followee)
return true;
}
-int arc_return_address_regs[5] =
- {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM, ILINK1_REGNUM};
+/* Return the register number of the register holding the return address
+ for a function of type TYPE. */
+
+int
+arc_return_address_register (unsigned int fn_type)
+{
+ int regno = 0;
+
+ if (ARC_INTERRUPT_P (fn_type))
+ {
+ if (((fn_type & ARC_FUNCTION_ILINK1) | ARC_FUNCTION_FIRQ) != 0)
+ regno = ILINK1_REGNUM;
+ else if ((fn_type & ARC_FUNCTION_ILINK2) != 0)
+ regno = ILINK2_REGNUM;
+ else
+ gcc_unreachable ();
+ }
+ else if (ARC_NORMAL_P (fn_type) || ARC_NAKED_P (fn_type))
+ regno = RETURN_ADDR_REGNUM;
-/* Implement EPILOGUE__USES.
+ gcc_assert (regno != 0);
+ return regno;
+}
+
+/* Implement EPILOGUE_USES.
Return true if REGNO should be added to the deemed uses of the epilogue.
- We use the return address
- arc_return_address_regs[arc_compute_function_type (cfun)]. But
- also, we have to make sure all the register restore instructions
- are known to be live in interrupt functions, plus the blink
- register if it is clobbered by the isr. */
+ We have to make sure all the register restore instructions are
+ known to be live in interrupt functions, plus the blink register if
+ it is clobbered by the isr. */
bool
arc_epilogue_uses (int regno)
{
+ unsigned int fn_type;
+
if (regno == arc_tp_regno)
return true;
+
+ fn_type = arc_compute_function_type (cfun);
if (reload_completed)
{
if (ARC_INTERRUPT_P (cfun->machine->fn_type))
{
if (!fixed_regs[regno])
return true;
- return ((regno == arc_return_address_regs[cfun->machine->fn_type])
+ return ((regno == arc_return_address_register (fn_type))
|| (regno == RETURN_ADDR_REGNUM));
}
else
return regno == RETURN_ADDR_REGNUM;
}
else
- return regno == arc_return_address_regs[arc_compute_function_type (cfun)];
+ return regno == arc_return_address_register (fn_type);
}
/* Helper for EH_USES macro. */
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index fbc1195..16d5319 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -1363,10 +1363,6 @@ do { \
#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
arc_asm_output_aligned_decl_local (STREAM, DECL, NAME, SIZE, ALIGNMENT, 0)
-/* To translate the return value of arc_function_type into a register number
- to jump through for function return. */
-extern int arc_return_address_regs[5];
-
/* Debugging information. */
/* Generate DBX and DWARF debugging information. */
@@ -1502,22 +1498,38 @@ extern struct rtx_def *arc_compare_op0, *arc_compare_op1;
/* ARC function types. */
enum arc_function_type {
- ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL,
+ /* No function should have the unknown type. This value is used to
+ indicate the that function type has not yet been computed. */
+ ARC_FUNCTION_UNKNOWN = 0,
+
+ /* The normal function type indicates that the function has the
+ standard prologue and epilogue. */
+ ARC_FUNCTION_NORMAL = 1 << 0,
/* These are interrupt handlers. The name corresponds to the register
name that contains the return address. */
- ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2,
+ ARC_FUNCTION_ILINK1 = 1 << 1,
+ ARC_FUNCTION_ILINK2 = 1 << 2,
/* Fast interrupt is only available on ARCv2 processors. */
- ARC_FUNCTION_FIRQ
+ ARC_FUNCTION_FIRQ = 1 << 3,
+ /* The naked function type indicates that the function does not have
+ prologue or epilogue, and that no stack frame is available. */
+ ARC_FUNCTION_NAKED = 1 << 4
};
-#define ARC_INTERRUPT_P(TYPE) \
- (((TYPE) == ARC_FUNCTION_ILINK1) || ((TYPE) == ARC_FUNCTION_ILINK2) \
- || ((TYPE) == ARC_FUNCTION_FIRQ))
-#define ARC_FAST_INTERRUPT_P(TYPE) ((TYPE) == ARC_FUNCTION_FIRQ)
+/* Check if a function is an interrupt function. */
+#define ARC_INTERRUPT_P(TYPE) \
+ (((TYPE) & (ARC_FUNCTION_ILINK1 | ARC_FUNCTION_ILINK2 \
+ | ARC_FUNCTION_FIRQ)) != 0)
+
+/* Check if a function is a fast interrupt function. */
+#define ARC_FAST_INTERRUPT_P(TYPE) (((TYPE) & ARC_FUNCTION_FIRQ) != 0)
+
+/* Check if a function is normal, that is, has standard prologue and
+ epilogue. */
+#define ARC_NORMAL_P(TYPE) (((TYPE) & ARC_FUNCTION_NORMAL) != 0)
-/* Compute the type of a function from its DECL. Needed for EPILOGUE_USES. */
-struct function;
-extern enum arc_function_type arc_compute_function_type (struct function *);
+/* Check if a function is naked. */
+#define ARC_NAKED_P(TYPE) (((TYPE) & ARC_FUNCTION_NAKED) != 0)
/* Called by crtstuff.c to make calls to function FUNCTION that are defined in
SECTION_OP, and then to switch back to text section. */
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 9a97490..39bcc26 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -505,8 +505,8 @@
(cond [(eq_attr "in_delay_slot" "false")
(const_string "no")
(match_test "regno_clobbered_p
- (arc_return_address_regs
- [arc_compute_function_type (cfun)],
+ (arc_return_address_register
+ (arc_compute_function_type (cfun)),
insn, SImode, 1)")
(const_string "no")]
(const_string "yes")))
@@ -4859,7 +4859,8 @@
{
rtx reg
= gen_rtx_REG (Pmode,
- arc_return_address_regs[arc_compute_function_type (cfun)]);
+ arc_return_address_register (arc_compute_function_type
+ (cfun)));
if (TARGET_V2
&& ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
@@ -4908,7 +4909,8 @@
xop[0] = operands[0];
xop[1]
= gen_rtx_REG (Pmode,
- arc_return_address_regs[arc_compute_function_type (cfun)]);
+ arc_return_address_register (arc_compute_function_type
+ (cfun)));
if (TARGET_PAD_RETURN)
arc_pad_return ();
diff --git a/gcc/testsuite/gcc.target/arc/naked-1.c b/gcc/testsuite/gcc.target/arc/naked-1.c
new file mode 100644
index 0000000..e45f433f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/naked-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+/* Check that naked functions don't place arguments on the stack at
+ optimisation level '-O0'. */
+extern void bar (int);
+
+void __attribute__((naked))
+foo (int n, int m)
+{
+ bar (n + m);
+}
+/* { dg-final { scan-assembler "\tbl @bar" } } */
+
+/* Look for things that would appear in a non-naked function, but which
+ should not appear in a naked function. */
+/* { dg-final { scan-assembler-not "\tj.* \\\[blink\\\]" } } */
+/* { dg-final { scan-assembler-not "\tst.* " } } */
+/* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
diff --git a/gcc/testsuite/gcc.target/arc/naked-2.c b/gcc/testsuite/gcc.target/arc/naked-2.c
new file mode 100644
index 0000000..7b7262f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/naked-2.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+/* Check that naked functions don't place arguments on the stack at
+ optimisation level '-O0'. */
+
+#if defined(__HS__) || defined(__EM__)
+# define ILINK "ilink"
+#else
+# define ILINK "ilink1"
+#endif
+
+extern void bar (int);
+
+void __attribute__((naked, interrupt(ILINK)))
+foo (int n, int m)
+{
+ bar (n + m);
+}
+/* { dg-final { scan-assembler "\tbl @bar" } } */
+
+/* Look for things that would appear in a non-naked function, but which
+ should not appear in a naked function. */
+/* { dg-final { scan-assembler-not "\trtie" } } */
+/* { dg-final { scan-assembler-not "j.*\[ilink1\]" } } */
+/* { dg-final { scan-assembler-not "\tst.* " } } */
+/* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
--
1.9.1
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/7] [ARC] Add support for naked functions.
2017-06-01 13:38 ` [PATCH 1/7] [ARC] Add support for naked functions Claudiu Zissulescu
@ 2017-06-16 19:36 ` Andrew Burgess
2017-06-19 9:55 ` [PATCH][ARC] " Claudiu Zissulescu
0 siblings, 1 reply; 27+ messages in thread
From: Andrew Burgess @ 2017-06-16 19:36 UTC (permalink / raw)
To: Claudiu Zissulescu; +Cc: gcc-patches, Francois.Bedard
* Claudiu Zissulescu <Claudiu.Zissulescu@synopsys.com> [2017-06-01 15:34:51 +0200]:
> gcc/
> 2016-12-13 Claudiu Zissulescu <claziss@synopsys.com>
> Andrew Burgess <andrew.burgess@embecosm.com>
>
> * config/arc/arc-protos.h (arc_compute_function_type): Change prototype.
> (arc_return_address_register): New function.
> * config/arc/arc.c (arc_handle_fndecl_attribute): New function.
> (arc_handle_fndecl_attribute): Add naked attribute.
> (TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS): Define.
> (TARGET_WARN_FUNC_RETURN): Likewise.
> (arc_allocate_stack_slots_for_args): New function.
> (arc_warn_func_return): Likewise.
> (machine_function): Change type fn_type.
> (arc_compute_function_type): Consider new naked function type,
> change function return type.
> (arc_must_save_register): Adapt to handle new
> arc_compute_function_type's return type.
> (arc_expand_prologue): Likewise.
> (arc_expand_epilogue): Likewise.
> (arc_return_address_regs): Delete.
> (arc_return_address_register): New function.
> (arc_epilogue_uses): Use above function.
> * config/arc/arc.h (arc_return_address_regs): Delete prototype.
> (arc_function_type): Change encoding, add naked type.
> (ARC_INTERRUPT_P): Change to handle the new encoding.
> (ARC_FAST_INTERRUPT_P): Likewise.
> (ARC_NORMAL_P): Define.
> (ARC_NAKED_P): Likewise.
> (arc_compute_function_type): Delete prototype.
> * config/arc/arc.md (in_ret_delay_slot): Use
> arc_return_address_register function.
> (simple_return): Likewise.
> (p_return_i): Likewise.
>
> gcc/testsuite
> 2016-12-13 Claudiu Zissulescu <claziss@synopsys.com>
> Andrew Burgess <andrew.burgess@embecosm.com>
>
> * gcc.target/arc/naked-1.c: New file.
> * gcc.target/arc/naked-2.c: Likewise.
Claudiu,
Sorry it's taken me a while to look at these patches.
I tried to apply this to the current GCC head, and it looks for me
like this doesn't apply. Specifically `arc_expand_epilogue` does not
appear (in the current head) to have the code expected in this patch.
I have double checked at my end, but could you confirm that the patch
does apply cleanly for you please, then I'll spend some additional
time trying to figure out what I've done wrong :)
Thanks,
Andrew
> ---
> gcc/config/arc/arc-protos.h | 6 +-
> gcc/config/arc/arc.c | 165 ++++++++++++++++++++++++---------
> gcc/config/arc/arc.h | 40 +++++---
> gcc/config/arc/arc.md | 10 +-
> gcc/testsuite/gcc.target/arc/naked-1.c | 18 ++++
> gcc/testsuite/gcc.target/arc/naked-2.c | 26 ++++++
> 6 files changed, 197 insertions(+), 68 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/arc/naked-1.c
> create mode 100644 gcc/testsuite/gcc.target/arc/naked-2.c
>
> diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
> index 4ff8e9b..b436dbe 100644
> --- a/gcc/config/arc/arc-protos.h
> +++ b/gcc/config/arc/arc-protos.h
> @@ -45,12 +45,10 @@ extern void arc_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
> extern void arc_split_compare_and_swap (rtx *);
> extern void arc_expand_compare_and_swap (rtx *);
> extern bool compact_memory_operand_p (rtx, machine_mode, bool, bool);
> +extern int arc_return_address_register (unsigned int);
> +extern unsigned int arc_compute_function_type (struct function *);
> #endif /* RTX_CODE */
>
> -#ifdef TREE_CODE
> -extern enum arc_function_type arc_compute_function_type (struct function *);
> -#endif /* TREE_CODE */
> -
> extern bool arc_ccfsm_branch_deleted_p (void);
> extern void arc_ccfsm_record_branch_deleted (void);
>
> diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
> index a65fc3a..7dfc68e 100644
> --- a/gcc/config/arc/arc.c
> +++ b/gcc/config/arc/arc.c
> @@ -211,6 +211,7 @@ static int rgf_banked_register_count;
> static int get_arc_condition_code (rtx);
>
> static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
> +static tree arc_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
>
> /* Initialized arc_attribute_table to NULL since arc doesnot have any
> machine specific supported attributes. */
> @@ -229,6 +230,9 @@ const struct attribute_spec arc_attribute_table[] =
> /* And these functions are always known to reside within the 21 bit
> addressing range of blcc. */
> { "short_call", 0, 0, false, true, true, NULL, false },
> + /* Function which are not having the prologue and epilogue generated
> + by the compiler. */
> + { "naked", 0, 0, true, false, false, arc_handle_fndecl_attribute, false },
> { NULL, 0, 0, false, false, false, NULL, false }
> };
> static int arc_comp_type_attributes (const_tree, const_tree);
> @@ -513,6 +517,12 @@ static void arc_finalize_pic (void);
> #define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
> #define TARGET_SPILL_CLASS arc_spill_class
>
> +#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
> +#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS arc_allocate_stack_slots_for_args
> +
> +#undef TARGET_WARN_FUNC_RETURN
> +#define TARGET_WARN_FUNC_RETURN arc_warn_func_return
> +
> #include "target-def.h"
>
> #undef TARGET_ASM_ALIGNED_HI_OP
> @@ -1859,6 +1869,42 @@ arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
> return NULL_TREE;
> }
>
> +static tree
> +arc_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
> + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
> +{
> + if (TREE_CODE (*node) != FUNCTION_DECL)
> + {
> + warning (OPT_Wattributes, "%qE attribute only applies to functions",
> + name);
> + *no_add_attrs = true;
> + }
> +
> + return NULL_TREE;
> +}
> +
> +/* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
> +
> +static bool
> +arc_allocate_stack_slots_for_args (void)
> +{
> + /* Naked functions should not allocate stack slots for arguments. */
> + unsigned int fn_type = arc_compute_function_type (cfun);
> +
> + return !ARC_NAKED_P(fn_type);
> +}
> +
> +/* Implement `TARGET_WARN_FUNC_RETURN'. */
> +
> +static bool
> +arc_warn_func_return (tree decl)
> +{
> + struct function *func = DECL_STRUCT_FUNCTION (decl);
> + unsigned int fn_type = arc_compute_function_type (func);
> +
> + return !ARC_NAKED_P (fn_type);
> +}
> +
> /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
> and two if they are nearly compatible (which causes a warning to be
> generated). */
> @@ -2362,7 +2408,7 @@ struct GTY (()) arc_frame_info
>
> typedef struct GTY (()) machine_function
> {
> - enum arc_function_type fn_type;
> + unsigned int fn_type;
> struct arc_frame_info frame_info;
> /* To keep track of unalignment caused by short insns. */
> int unalign;
> @@ -2380,43 +2426,40 @@ typedef struct GTY (()) machine_function
> The result is cached. To reset the cache at the end of a function,
> call with DECL = NULL_TREE. */
>
> -enum arc_function_type
> +unsigned int
> arc_compute_function_type (struct function *fun)
> {
> - tree decl = fun->decl;
> - tree a;
> - enum arc_function_type fn_type = fun->machine->fn_type;
> + tree attr, decl = fun->decl;
> + unsigned int fn_type = fun->machine->fn_type;
>
> if (fn_type != ARC_FUNCTION_UNKNOWN)
> return fn_type;
>
> - /* Assume we have a normal function (not an interrupt handler). */
> - fn_type = ARC_FUNCTION_NORMAL;
> + /* Check if it is a naked function. */
> + if (lookup_attribute ("naked", DECL_ATTRIBUTES (decl)) != NULL_TREE)
> + fn_type |= ARC_FUNCTION_NAKED;
> + else
> + fn_type |= ARC_FUNCTION_NORMAL;
>
> /* Now see if this is an interrupt handler. */
> - for (a = DECL_ATTRIBUTES (decl);
> - a;
> - a = TREE_CHAIN (a))
> - {
> - tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
> -
> - if (name == get_identifier ("interrupt")
> - && list_length (args) == 1
> - && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
> - {
> - tree value = TREE_VALUE (args);
> -
> - if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
> - || !strcmp (TREE_STRING_POINTER (value), "ilink"))
> - fn_type = ARC_FUNCTION_ILINK1;
> - else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
> - fn_type = ARC_FUNCTION_ILINK2;
> - else if (!strcmp (TREE_STRING_POINTER (value), "firq"))
> - fn_type = ARC_FUNCTION_FIRQ;
> - else
> - gcc_unreachable ();
> - break;
> - }
> + attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
> + if (attr != NULL_TREE)
> + {
> + tree value, args = TREE_VALUE (attr);
> +
> + gcc_assert (list_length (args) == 1);
> + value = TREE_VALUE (args);
> + gcc_assert (TREE_CODE (value) == STRING_CST);
> +
> + if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
> + || !strcmp (TREE_STRING_POINTER (value), "ilink"))
> + fn_type |= ARC_FUNCTION_ILINK1;
> + else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
> + fn_type |= ARC_FUNCTION_ILINK2;
> + else if (!strcmp (TREE_STRING_POINTER (value), "firq"))
> + fn_type |= ARC_FUNCTION_FIRQ;
> + else
> + gcc_unreachable ();
> }
>
> return fun->machine->fn_type = fn_type;
> @@ -2436,7 +2479,7 @@ arc_compute_function_type (struct function *fun)
> static bool
> arc_must_save_register (int regno, struct function *func)
> {
> - enum arc_function_type fn_type = arc_compute_function_type (func);
> + unsigned int fn_type = arc_compute_function_type (func);
> bool irq_auto_save_p = ((irq_ctrl_saved.irq_save_last_reg >= regno)
> && ARC_AUTO_IRQ_P (fn_type));
> bool firq_auto_save_p = ARC_FAST_INTERRUPT_P (fn_type);
> @@ -2945,7 +2988,11 @@ arc_expand_prologue (void)
> Change the stack layout so that we rather store a high register with the
> PRE_MODIFY, thus enabling more short insn generation.) */
> int first_offset = 0;
> - enum arc_function_type fn_type = arc_compute_function_type (cfun);
> + unsigned int fn_type = arc_compute_function_type (cfun);
> +
> + /* Naked functions don't have prologue. */
> + if (ARC_NAKED_P (fn_type))
> + return;
>
> /* Compute total frame size. */
> size = arc_compute_frame_size ();
> @@ -3052,10 +3099,7 @@ void
> arc_expand_epilogue (int sibcall_p)
> {
> int size;
> - enum arc_function_type fn_type = arc_compute_function_type (cfun);
> -
> - size = arc_compute_frame_size ();
> -
> + unsigned int fn_type = arc_compute_function_type (cfun);
> unsigned int pretend_size = cfun->machine->frame_info.pretend_size;
> unsigned int frame_size;
> unsigned int size_to_deallocate;
> @@ -3065,6 +3109,12 @@ arc_expand_epilogue (int sibcall_p)
> int millicode_p = cfun->machine->frame_info.millicode_end_reg > 0;
> rtx insn;
>
> + /* Naked functions don't have epilogue. */
> + if (ARC_NAKED_P (fn_type))
> + return;
> +
> + size = arc_compute_frame_size ();
> +
> size_to_deallocate = size;
>
> frame_size = size - (pretend_size +
> @@ -9886,37 +9936,60 @@ arc_can_follow_jump (const rtx_insn *follower, const rtx_insn *followee)
> return true;
> }
>
> -int arc_return_address_regs[5] =
> - {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM, ILINK1_REGNUM};
> +/* Return the register number of the register holding the return address
> + for a function of type TYPE. */
> +
> +int
> +arc_return_address_register (unsigned int fn_type)
> +{
> + int regno = 0;
> +
> + if (ARC_INTERRUPT_P (fn_type))
> + {
> + if (((fn_type & ARC_FUNCTION_ILINK1) | ARC_FUNCTION_FIRQ) != 0)
> + regno = ILINK1_REGNUM;
> + else if ((fn_type & ARC_FUNCTION_ILINK2) != 0)
> + regno = ILINK2_REGNUM;
> + else
> + gcc_unreachable ();
> + }
> + else if (ARC_NORMAL_P (fn_type) || ARC_NAKED_P (fn_type))
> + regno = RETURN_ADDR_REGNUM;
>
> -/* Implement EPILOGUE__USES.
> + gcc_assert (regno != 0);
> + return regno;
> +}
> +
> +/* Implement EPILOGUE_USES.
> Return true if REGNO should be added to the deemed uses of the epilogue.
>
> - We use the return address
> - arc_return_address_regs[arc_compute_function_type (cfun)]. But
> - also, we have to make sure all the register restore instructions
> - are known to be live in interrupt functions, plus the blink
> - register if it is clobbered by the isr. */
> + We have to make sure all the register restore instructions are
> + known to be live in interrupt functions, plus the blink register if
> + it is clobbered by the isr. */
>
> bool
> arc_epilogue_uses (int regno)
> {
> + unsigned int fn_type;
> +
> if (regno == arc_tp_regno)
> return true;
> +
> + fn_type = arc_compute_function_type (cfun);
> if (reload_completed)
> {
> if (ARC_INTERRUPT_P (cfun->machine->fn_type))
> {
> if (!fixed_regs[regno])
> return true;
> - return ((regno == arc_return_address_regs[cfun->machine->fn_type])
> + return ((regno == arc_return_address_register (fn_type))
> || (regno == RETURN_ADDR_REGNUM));
> }
> else
> return regno == RETURN_ADDR_REGNUM;
> }
> else
> - return regno == arc_return_address_regs[arc_compute_function_type (cfun)];
> + return regno == arc_return_address_register (fn_type);
> }
>
> /* Helper for EH_USES macro. */
> diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
> index fbc1195..16d5319 100644
> --- a/gcc/config/arc/arc.h
> +++ b/gcc/config/arc/arc.h
> @@ -1363,10 +1363,6 @@ do { \
> #define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
> arc_asm_output_aligned_decl_local (STREAM, DECL, NAME, SIZE, ALIGNMENT, 0)
>
> -/* To translate the return value of arc_function_type into a register number
> - to jump through for function return. */
> -extern int arc_return_address_regs[5];
> -
> /* Debugging information. */
>
> /* Generate DBX and DWARF debugging information. */
> @@ -1502,22 +1498,38 @@ extern struct rtx_def *arc_compare_op0, *arc_compare_op1;
>
> /* ARC function types. */
> enum arc_function_type {
> - ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL,
> + /* No function should have the unknown type. This value is used to
> + indicate the that function type has not yet been computed. */
> + ARC_FUNCTION_UNKNOWN = 0,
> +
> + /* The normal function type indicates that the function has the
> + standard prologue and epilogue. */
> + ARC_FUNCTION_NORMAL = 1 << 0,
> /* These are interrupt handlers. The name corresponds to the register
> name that contains the return address. */
> - ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2,
> + ARC_FUNCTION_ILINK1 = 1 << 1,
> + ARC_FUNCTION_ILINK2 = 1 << 2,
> /* Fast interrupt is only available on ARCv2 processors. */
> - ARC_FUNCTION_FIRQ
> + ARC_FUNCTION_FIRQ = 1 << 3,
> + /* The naked function type indicates that the function does not have
> + prologue or epilogue, and that no stack frame is available. */
> + ARC_FUNCTION_NAKED = 1 << 4
> };
> -#define ARC_INTERRUPT_P(TYPE) \
> - (((TYPE) == ARC_FUNCTION_ILINK1) || ((TYPE) == ARC_FUNCTION_ILINK2) \
> - || ((TYPE) == ARC_FUNCTION_FIRQ))
>
> -#define ARC_FAST_INTERRUPT_P(TYPE) ((TYPE) == ARC_FUNCTION_FIRQ)
> +/* Check if a function is an interrupt function. */
> +#define ARC_INTERRUPT_P(TYPE) \
> + (((TYPE) & (ARC_FUNCTION_ILINK1 | ARC_FUNCTION_ILINK2 \
> + | ARC_FUNCTION_FIRQ)) != 0)
> +
> +/* Check if a function is a fast interrupt function. */
> +#define ARC_FAST_INTERRUPT_P(TYPE) (((TYPE) & ARC_FUNCTION_FIRQ) != 0)
> +
> +/* Check if a function is normal, that is, has standard prologue and
> + epilogue. */
> +#define ARC_NORMAL_P(TYPE) (((TYPE) & ARC_FUNCTION_NORMAL) != 0)
>
> -/* Compute the type of a function from its DECL. Needed for EPILOGUE_USES. */
> -struct function;
> -extern enum arc_function_type arc_compute_function_type (struct function *);
> +/* Check if a function is naked. */
> +#define ARC_NAKED_P(TYPE) (((TYPE) & ARC_FUNCTION_NAKED) != 0)
>
> /* Called by crtstuff.c to make calls to function FUNCTION that are defined in
> SECTION_OP, and then to switch back to text section. */
> diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
> index 9a97490..39bcc26 100644
> --- a/gcc/config/arc/arc.md
> +++ b/gcc/config/arc/arc.md
> @@ -505,8 +505,8 @@
> (cond [(eq_attr "in_delay_slot" "false")
> (const_string "no")
> (match_test "regno_clobbered_p
> - (arc_return_address_regs
> - [arc_compute_function_type (cfun)],
> + (arc_return_address_register
> + (arc_compute_function_type (cfun)),
> insn, SImode, 1)")
> (const_string "no")]
> (const_string "yes")))
> @@ -4859,7 +4859,8 @@
> {
> rtx reg
> = gen_rtx_REG (Pmode,
> - arc_return_address_regs[arc_compute_function_type (cfun)]);
> + arc_return_address_register (arc_compute_function_type
> + (cfun)));
>
> if (TARGET_V2
> && ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
> @@ -4908,7 +4909,8 @@
> xop[0] = operands[0];
> xop[1]
> = gen_rtx_REG (Pmode,
> - arc_return_address_regs[arc_compute_function_type (cfun)]);
> + arc_return_address_register (arc_compute_function_type
> + (cfun)));
>
> if (TARGET_PAD_RETURN)
> arc_pad_return ();
> diff --git a/gcc/testsuite/gcc.target/arc/naked-1.c b/gcc/testsuite/gcc.target/arc/naked-1.c
> new file mode 100644
> index 0000000..e45f433f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/naked-1.c
> @@ -0,0 +1,18 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0" } */
> +/* Check that naked functions don't place arguments on the stack at
> + optimisation level '-O0'. */
> +extern void bar (int);
> +
> +void __attribute__((naked))
> +foo (int n, int m)
> +{
> + bar (n + m);
> +}
> +/* { dg-final { scan-assembler "\tbl @bar" } } */
> +
> +/* Look for things that would appear in a non-naked function, but which
> + should not appear in a naked function. */
> +/* { dg-final { scan-assembler-not "\tj.* \\\[blink\\\]" } } */
> +/* { dg-final { scan-assembler-not "\tst.* " } } */
> +/* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
> diff --git a/gcc/testsuite/gcc.target/arc/naked-2.c b/gcc/testsuite/gcc.target/arc/naked-2.c
> new file mode 100644
> index 0000000..7b7262f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/naked-2.c
> @@ -0,0 +1,26 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0" } */
> +/* Check that naked functions don't place arguments on the stack at
> + optimisation level '-O0'. */
> +
> +#if defined(__HS__) || defined(__EM__)
> +# define ILINK "ilink"
> +#else
> +# define ILINK "ilink1"
> +#endif
> +
> +extern void bar (int);
> +
> +void __attribute__((naked, interrupt(ILINK)))
> +foo (int n, int m)
> +{
> + bar (n + m);
> +}
> +/* { dg-final { scan-assembler "\tbl @bar" } } */
> +
> +/* Look for things that would appear in a non-naked function, but which
> + should not appear in a naked function. */
> +/* { dg-final { scan-assembler-not "\trtie" } } */
> +/* { dg-final { scan-assembler-not "j.*\[ilink1\]" } } */
> +/* { dg-final { scan-assembler-not "\tst.* " } } */
> +/* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
> --
> 1.9.1
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH][ARC] Add support for naked functions.
2017-06-16 19:36 ` Andrew Burgess
@ 2017-06-19 9:55 ` Claudiu Zissulescu
2017-07-13 11:21 ` Andrew Burgess
0 siblings, 1 reply; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-06-19 9:55 UTC (permalink / raw)
To: gcc-patches; +Cc: Claudiu.Zissulescu, Francois.Bedard, andrew.burgess
From: claziss <claziss@synopsys.com>
Hi Andrew,
Apologizes for the disconfort, please find the patch that works on the head.
Thanks,
Claudiu
gcc/
2016-12-13 Claudiu Zissulescu <claziss@synopsys.com>
Andrew Burgess <andrew.burgess@embecosm.com>
* config/arc/arc-protos.h (arc_compute_function_type): Change prototype.
(arc_return_address_register): New function.
* config/arc/arc.c (arc_handle_fndecl_attribute): New function.
(arc_handle_fndecl_attribute): Add naked attribute.
(TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS): Define.
(TARGET_WARN_FUNC_RETURN): Likewise.
(arc_allocate_stack_slots_for_args): New function.
(arc_warn_func_return): Likewise.
(machine_function): Change type fn_type.
(arc_compute_function_type): Consider new naked function type,
change function return type.
(arc_must_save_register): Adapt to handle new
arc_compute_function_type's return type.
(arc_expand_prologue): Likewise.
(arc_expand_epilogue): Likewise.
(arc_return_address_regs): Delete.
(arc_return_address_register): New function.
(arc_epilogue_uses): Use above function.
* config/arc/arc.h (arc_return_address_regs): Delete prototype.
(arc_function_type): Change encoding, add naked type.
(ARC_INTERRUPT_P): Change to handle the new encoding.
(ARC_FAST_INTERRUPT_P): Likewise.
(ARC_NORMAL_P): Define.
(ARC_NAKED_P): Likewise.
(arc_compute_function_type): Delete prototype.
* config/arc/arc.md (in_ret_delay_slot): Use
arc_return_address_register function.
(simple_return): Likewise.
(p_return_i): Likewise.
gcc/testsuite
2016-12-13 Claudiu Zissulescu <claziss@synopsys.com>
Andrew Burgess <andrew.burgess@embecosm.com>
* gcc.target/arc/naked-1.c: New file.
* gcc.target/arc/naked-2.c: Likewise.
---
gcc/config/arc/arc-protos.h | 7 +-
gcc/config/arc/arc.c | 160 ++++++++++++++++++++++++---------
gcc/config/arc/arc.h | 40 ++++++---
gcc/config/arc/arc.md | 10 ++-
gcc/testsuite/gcc.target/arc/naked-1.c | 18 ++++
gcc/testsuite/gcc.target/arc/naked-2.c | 26 ++++++
6 files changed, 195 insertions(+), 66 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/arc/naked-1.c
create mode 100644 gcc/testsuite/gcc.target/arc/naked-2.c
diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index 93a64cf..f6bf14e 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -45,13 +45,10 @@ extern void arc_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
extern void arc_split_compare_and_swap (rtx *);
extern void arc_expand_compare_and_swap (rtx *);
extern bool compact_memory_operand_p (rtx, machine_mode, bool, bool);
+extern int arc_return_address_register (unsigned int);
+extern unsigned int arc_compute_function_type (struct function *);
#endif /* RTX_CODE */
-#ifdef TREE_CODE
-extern enum arc_function_type arc_compute_function_type (struct function *);
-#endif /* TREE_CODE */
-
-
extern unsigned int arc_compute_frame_size (int);
extern bool arc_ccfsm_branch_deleted_p (void);
extern void arc_ccfsm_record_branch_deleted (void);
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index d9ad139..4ccd304 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -211,6 +211,7 @@ static int rgf_banked_register_count;
static int get_arc_condition_code (rtx);
static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
+static tree arc_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
/* Initialized arc_attribute_table to NULL since arc doesnot have any
machine specific supported attributes. */
@@ -229,6 +230,9 @@ const struct attribute_spec arc_attribute_table[] =
/* And these functions are always known to reside within the 21 bit
addressing range of blcc. */
{ "short_call", 0, 0, false, true, true, NULL, false },
+ /* Function which are not having the prologue and epilogue generated
+ by the compiler. */
+ { "naked", 0, 0, true, false, false, arc_handle_fndecl_attribute, false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
static int arc_comp_type_attributes (const_tree, const_tree);
@@ -513,6 +517,12 @@ static void arc_finalize_pic (void);
#define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
#define TARGET_SPILL_CLASS arc_spill_class
+#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
+#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS arc_allocate_stack_slots_for_args
+
+#undef TARGET_WARN_FUNC_RETURN
+#define TARGET_WARN_FUNC_RETURN arc_warn_func_return
+
#include "target-def.h"
#undef TARGET_ASM_ALIGNED_HI_OP
@@ -1856,6 +1866,42 @@ arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
return NULL_TREE;
}
+static tree
+arc_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute only applies to functions",
+ name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
+
+static bool
+arc_allocate_stack_slots_for_args (void)
+{
+ /* Naked functions should not allocate stack slots for arguments. */
+ unsigned int fn_type = arc_compute_function_type (cfun);
+
+ return !ARC_NAKED_P(fn_type);
+}
+
+/* Implement `TARGET_WARN_FUNC_RETURN'. */
+
+static bool
+arc_warn_func_return (tree decl)
+{
+ struct function *func = DECL_STRUCT_FUNCTION (decl);
+ unsigned int fn_type = arc_compute_function_type (func);
+
+ return !ARC_NAKED_P (fn_type);
+}
+
/* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
and two if they are nearly compatible (which causes a warning to be
generated). */
@@ -2359,7 +2405,7 @@ struct GTY (()) arc_frame_info
typedef struct GTY (()) machine_function
{
- enum arc_function_type fn_type;
+ unsigned int fn_type;
struct arc_frame_info frame_info;
/* To keep track of unalignment caused by short insns. */
int unalign;
@@ -2377,43 +2423,40 @@ typedef struct GTY (()) machine_function
The result is cached. To reset the cache at the end of a function,
call with DECL = NULL_TREE. */
-enum arc_function_type
+unsigned int
arc_compute_function_type (struct function *fun)
{
- tree decl = fun->decl;
- tree a;
- enum arc_function_type fn_type = fun->machine->fn_type;
+ tree attr, decl = fun->decl;
+ unsigned int fn_type = fun->machine->fn_type;
if (fn_type != ARC_FUNCTION_UNKNOWN)
return fn_type;
- /* Assume we have a normal function (not an interrupt handler). */
- fn_type = ARC_FUNCTION_NORMAL;
+ /* Check if it is a naked function. */
+ if (lookup_attribute ("naked", DECL_ATTRIBUTES (decl)) != NULL_TREE)
+ fn_type |= ARC_FUNCTION_NAKED;
+ else
+ fn_type |= ARC_FUNCTION_NORMAL;
/* Now see if this is an interrupt handler. */
- for (a = DECL_ATTRIBUTES (decl);
- a;
- a = TREE_CHAIN (a))
- {
- tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
-
- if (name == get_identifier ("interrupt")
- && list_length (args) == 1
- && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
- {
- tree value = TREE_VALUE (args);
-
- if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
- || !strcmp (TREE_STRING_POINTER (value), "ilink"))
- fn_type = ARC_FUNCTION_ILINK1;
- else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
- fn_type = ARC_FUNCTION_ILINK2;
- else if (!strcmp (TREE_STRING_POINTER (value), "firq"))
- fn_type = ARC_FUNCTION_FIRQ;
- else
- gcc_unreachable ();
- break;
- }
+ attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
+ if (attr != NULL_TREE)
+ {
+ tree value, args = TREE_VALUE (attr);
+
+ gcc_assert (list_length (args) == 1);
+ value = TREE_VALUE (args);
+ gcc_assert (TREE_CODE (value) == STRING_CST);
+
+ if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
+ || !strcmp (TREE_STRING_POINTER (value), "ilink"))
+ fn_type |= ARC_FUNCTION_ILINK1;
+ else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
+ fn_type |= ARC_FUNCTION_ILINK2;
+ else if (!strcmp (TREE_STRING_POINTER (value), "firq"))
+ fn_type |= ARC_FUNCTION_FIRQ;
+ else
+ gcc_unreachable ();
}
return fun->machine->fn_type = fn_type;
@@ -2434,7 +2477,7 @@ arc_compute_function_type (struct function *fun)
static bool
arc_must_save_register (int regno, struct function *func)
{
- enum arc_function_type fn_type = arc_compute_function_type (func);
+ unsigned int fn_type = arc_compute_function_type (func);
bool irq_auto_save_p = ((irq_ctrl_saved.irq_save_last_reg >= regno)
&& ARC_AUTO_IRQ_P (fn_type));
bool firq_auto_save_p = ARC_FAST_INTERRUPT_P (fn_type);
@@ -2879,7 +2922,11 @@ arc_expand_prologue (void)
Change the stack layout so that we rather store a high register with the
PRE_MODIFY, thus enabling more short insn generation.) */
int first_offset = 0;
- enum arc_function_type fn_type = arc_compute_function_type (cfun);
+ unsigned int fn_type = arc_compute_function_type (cfun);
+
+ /* Naked functions don't have prologue. */
+ if (ARC_NAKED_P (fn_type))
+ return;
size = ARC_STACK_ALIGN (size);
@@ -2990,7 +3037,7 @@ void
arc_expand_epilogue (int sibcall_p)
{
int size = get_frame_size ();
- enum arc_function_type fn_type = arc_compute_function_type (cfun);
+ unsigned int fn_type = arc_compute_function_type (cfun);
size = ARC_STACK_ALIGN (size);
size = (!cfun->machine->frame_info.initialized
@@ -3006,6 +3053,10 @@ arc_expand_epilogue (int sibcall_p)
int millicode_p = cfun->machine->frame_info.millicode_end_reg > 0;
rtx insn;
+ /* Naked functions don't have epilogue. */
+ if (ARC_NAKED_P (fn_type))
+ return;
+
size_to_deallocate = size;
frame_size = size - (pretend_size +
@@ -9789,37 +9840,60 @@ arc_can_follow_jump (const rtx_insn *follower, const rtx_insn *followee)
return true;
}
-int arc_return_address_regs[5] =
- {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM, ILINK1_REGNUM};
+/* Return the register number of the register holding the return address
+ for a function of type TYPE. */
+
+int
+arc_return_address_register (unsigned int fn_type)
+{
+ int regno = 0;
+
+ if (ARC_INTERRUPT_P (fn_type))
+ {
+ if (((fn_type & ARC_FUNCTION_ILINK1) | ARC_FUNCTION_FIRQ) != 0)
+ regno = ILINK1_REGNUM;
+ else if ((fn_type & ARC_FUNCTION_ILINK2) != 0)
+ regno = ILINK2_REGNUM;
+ else
+ gcc_unreachable ();
+ }
+ else if (ARC_NORMAL_P (fn_type) || ARC_NAKED_P (fn_type))
+ regno = RETURN_ADDR_REGNUM;
+
+ gcc_assert (regno != 0);
+ return regno;
+}
-/* Implement EPILOGUE__USES.
+/* Implement EPILOGUE_USES.
Return true if REGNO should be added to the deemed uses of the epilogue.
- We use the return address
- arc_return_address_regs[arc_compute_function_type (cfun)]. But
- also, we have to make sure all the register restore instructions
- are known to be live in interrupt functions, plus the blink
- register if it is clobbered by the isr. */
+ We have to make sure all the register restore instructions are
+ known to be live in interrupt functions, plus the blink register if
+ it is clobbered by the isr. */
bool
arc_epilogue_uses (int regno)
{
+ unsigned int fn_type;
+
if (regno == arc_tp_regno)
return true;
+
+ fn_type = arc_compute_function_type (cfun);
if (reload_completed)
{
if (ARC_INTERRUPT_P (cfun->machine->fn_type))
{
if (!fixed_regs[regno])
return true;
- return ((regno == arc_return_address_regs[cfun->machine->fn_type])
+ return ((regno == arc_return_address_register (fn_type))
|| (regno == RETURN_ADDR_REGNUM));
}
else
return regno == RETURN_ADDR_REGNUM;
}
else
- return regno == arc_return_address_regs[arc_compute_function_type (cfun)];
+ return regno == arc_return_address_register (fn_type);
}
/* Helper for EH_USES macro. */
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index 5627eb4..149e876 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -1363,10 +1363,6 @@ do { \
#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
arc_asm_output_aligned_decl_local (STREAM, DECL, NAME, SIZE, ALIGNMENT, 0)
-/* To translate the return value of arc_function_type into a register number
- to jump through for function return. */
-extern int arc_return_address_regs[5];
-
/* Debugging information. */
/* Generate DBX and DWARF debugging information. */
@@ -1499,22 +1495,38 @@ extern struct rtx_def *arc_compare_op0, *arc_compare_op1;
/* ARC function types. */
enum arc_function_type {
- ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL,
+ /* No function should have the unknown type. This value is used to
+ indicate the that function type has not yet been computed. */
+ ARC_FUNCTION_UNKNOWN = 0,
+
+ /* The normal function type indicates that the function has the
+ standard prologue and epilogue. */
+ ARC_FUNCTION_NORMAL = 1 << 0,
/* These are interrupt handlers. The name corresponds to the register
name that contains the return address. */
- ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2,
+ ARC_FUNCTION_ILINK1 = 1 << 1,
+ ARC_FUNCTION_ILINK2 = 1 << 2,
/* Fast interrupt is only available on ARCv2 processors. */
- ARC_FUNCTION_FIRQ
+ ARC_FUNCTION_FIRQ = 1 << 3,
+ /* The naked function type indicates that the function does not have
+ prologue or epilogue, and that no stack frame is available. */
+ ARC_FUNCTION_NAKED = 1 << 4
};
-#define ARC_INTERRUPT_P(TYPE) \
- (((TYPE) == ARC_FUNCTION_ILINK1) || ((TYPE) == ARC_FUNCTION_ILINK2) \
- || ((TYPE) == ARC_FUNCTION_FIRQ))
-#define ARC_FAST_INTERRUPT_P(TYPE) ((TYPE) == ARC_FUNCTION_FIRQ)
+/* Check if a function is an interrupt function. */
+#define ARC_INTERRUPT_P(TYPE) \
+ (((TYPE) & (ARC_FUNCTION_ILINK1 | ARC_FUNCTION_ILINK2 \
+ | ARC_FUNCTION_FIRQ)) != 0)
+
+/* Check if a function is a fast interrupt function. */
+#define ARC_FAST_INTERRUPT_P(TYPE) (((TYPE) & ARC_FUNCTION_FIRQ) != 0)
+
+/* Check if a function is normal, that is, has standard prologue and
+ epilogue. */
+#define ARC_NORMAL_P(TYPE) (((TYPE) & ARC_FUNCTION_NORMAL) != 0)
-/* Compute the type of a function from its DECL. Needed for EPILOGUE_USES. */
-struct function;
-extern enum arc_function_type arc_compute_function_type (struct function *);
+/* Check if a function is naked. */
+#define ARC_NAKED_P(TYPE) (((TYPE) & ARC_FUNCTION_NAKED) != 0)
/* Called by crtstuff.c to make calls to function FUNCTION that are defined in
SECTION_OP, and then to switch back to text section. */
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 9aa9cd7..0d14085 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -505,8 +505,8 @@
(cond [(eq_attr "in_delay_slot" "false")
(const_string "no")
(match_test "regno_clobbered_p
- (arc_return_address_regs
- [arc_compute_function_type (cfun)],
+ (arc_return_address_register
+ (arc_compute_function_type (cfun)),
insn, SImode, 1)")
(const_string "no")]
(const_string "yes")))
@@ -4859,7 +4859,8 @@
{
rtx reg
= gen_rtx_REG (Pmode,
- arc_return_address_regs[arc_compute_function_type (cfun)]);
+ arc_return_address_register (arc_compute_function_type
+ (cfun)));
if (TARGET_V2
&& ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
@@ -4908,7 +4909,8 @@
xop[0] = operands[0];
xop[1]
= gen_rtx_REG (Pmode,
- arc_return_address_regs[arc_compute_function_type (cfun)]);
+ arc_return_address_register (arc_compute_function_type
+ (cfun)));
if (TARGET_PAD_RETURN)
arc_pad_return ();
diff --git a/gcc/testsuite/gcc.target/arc/naked-1.c b/gcc/testsuite/gcc.target/arc/naked-1.c
new file mode 100644
index 0000000..e45f433f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/naked-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+/* Check that naked functions don't place arguments on the stack at
+ optimisation level '-O0'. */
+extern void bar (int);
+
+void __attribute__((naked))
+foo (int n, int m)
+{
+ bar (n + m);
+}
+/* { dg-final { scan-assembler "\tbl @bar" } } */
+
+/* Look for things that would appear in a non-naked function, but which
+ should not appear in a naked function. */
+/* { dg-final { scan-assembler-not "\tj.* \\\[blink\\\]" } } */
+/* { dg-final { scan-assembler-not "\tst.* " } } */
+/* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
diff --git a/gcc/testsuite/gcc.target/arc/naked-2.c b/gcc/testsuite/gcc.target/arc/naked-2.c
new file mode 100644
index 0000000..7b7262f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/naked-2.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+/* Check that naked functions don't place arguments on the stack at
+ optimisation level '-O0'. */
+
+#if defined(__HS__) || defined(__EM__)
+# define ILINK "ilink"
+#else
+# define ILINK "ilink1"
+#endif
+
+extern void bar (int);
+
+void __attribute__((naked, interrupt(ILINK)))
+foo (int n, int m)
+{
+ bar (n + m);
+}
+/* { dg-final { scan-assembler "\tbl @bar" } } */
+
+/* Look for things that would appear in a non-naked function, but which
+ should not appear in a naked function. */
+/* { dg-final { scan-assembler-not "\trtie" } } */
+/* { dg-final { scan-assembler-not "j.*\[ilink1\]" } } */
+/* { dg-final { scan-assembler-not "\tst.* " } } */
+/* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
--
1.9.1
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH][ARC] Add support for naked functions.
2017-06-19 9:55 ` [PATCH][ARC] " Claudiu Zissulescu
@ 2017-07-13 11:21 ` Andrew Burgess
2017-07-17 10:47 ` Claudiu Zissulescu
0 siblings, 1 reply; 27+ messages in thread
From: Andrew Burgess @ 2017-07-13 11:21 UTC (permalink / raw)
To: Claudiu Zissulescu; +Cc: gcc-patches, Francois.Bedard
* Claudiu Zissulescu <Claudiu.Zissulescu@synopsys.com> [2017-06-19 11:52:31 +0200]:
> From: claziss <claziss@synopsys.com>
>
> Hi Andrew,
>
> Apologizes for the disconfort, please find the patch that works on the head.
>
> Thanks,
> Claudiu
>
> gcc/
> 2016-12-13 Claudiu Zissulescu <claziss@synopsys.com>
> Andrew Burgess <andrew.burgess@embecosm.com>
>
> * config/arc/arc-protos.h (arc_compute_function_type): Change prototype.
> (arc_return_address_register): New function.
> * config/arc/arc.c (arc_handle_fndecl_attribute): New function.
> (arc_handle_fndecl_attribute): Add naked attribute.
> (TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS): Define.
> (TARGET_WARN_FUNC_RETURN): Likewise.
> (arc_allocate_stack_slots_for_args): New function.
> (arc_warn_func_return): Likewise.
> (machine_function): Change type fn_type.
> (arc_compute_function_type): Consider new naked function type,
> change function return type.
> (arc_must_save_register): Adapt to handle new
> arc_compute_function_type's return type.
> (arc_expand_prologue): Likewise.
> (arc_expand_epilogue): Likewise.
> (arc_return_address_regs): Delete.
> (arc_return_address_register): New function.
> (arc_epilogue_uses): Use above function.
> * config/arc/arc.h (arc_return_address_regs): Delete prototype.
> (arc_function_type): Change encoding, add naked type.
> (ARC_INTERRUPT_P): Change to handle the new encoding.
> (ARC_FAST_INTERRUPT_P): Likewise.
> (ARC_NORMAL_P): Define.
> (ARC_NAKED_P): Likewise.
> (arc_compute_function_type): Delete prototype.
> * config/arc/arc.md (in_ret_delay_slot): Use
> arc_return_address_register function.
> (simple_return): Likewise.
> (p_return_i): Likewise.
>
> gcc/testsuite
> 2016-12-13 Claudiu Zissulescu <claziss@synopsys.com>
> Andrew Burgess <andrew.burgess@embecosm.com>
>
> * gcc.target/arc/naked-1.c: New file.
> * gcc.target/arc/naked-2.c: Likewise.
This all looks fine,
Thanks,
Andrew
> ---
> gcc/config/arc/arc-protos.h | 7 +-
> gcc/config/arc/arc.c | 160 ++++++++++++++++++++++++---------
> gcc/config/arc/arc.h | 40 ++++++---
> gcc/config/arc/arc.md | 10 ++-
> gcc/testsuite/gcc.target/arc/naked-1.c | 18 ++++
> gcc/testsuite/gcc.target/arc/naked-2.c | 26 ++++++
> 6 files changed, 195 insertions(+), 66 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/arc/naked-1.c
> create mode 100644 gcc/testsuite/gcc.target/arc/naked-2.c
>
> diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
> index 93a64cf..f6bf14e 100644
> --- a/gcc/config/arc/arc-protos.h
> +++ b/gcc/config/arc/arc-protos.h
> @@ -45,13 +45,10 @@ extern void arc_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
> extern void arc_split_compare_and_swap (rtx *);
> extern void arc_expand_compare_and_swap (rtx *);
> extern bool compact_memory_operand_p (rtx, machine_mode, bool, bool);
> +extern int arc_return_address_register (unsigned int);
> +extern unsigned int arc_compute_function_type (struct function *);
> #endif /* RTX_CODE */
>
> -#ifdef TREE_CODE
> -extern enum arc_function_type arc_compute_function_type (struct function *);
> -#endif /* TREE_CODE */
> -
> -
> extern unsigned int arc_compute_frame_size (int);
> extern bool arc_ccfsm_branch_deleted_p (void);
> extern void arc_ccfsm_record_branch_deleted (void);
> diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
> index d9ad139..4ccd304 100644
> --- a/gcc/config/arc/arc.c
> +++ b/gcc/config/arc/arc.c
> @@ -211,6 +211,7 @@ static int rgf_banked_register_count;
> static int get_arc_condition_code (rtx);
>
> static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
> +static tree arc_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
>
> /* Initialized arc_attribute_table to NULL since arc doesnot have any
> machine specific supported attributes. */
> @@ -229,6 +230,9 @@ const struct attribute_spec arc_attribute_table[] =
> /* And these functions are always known to reside within the 21 bit
> addressing range of blcc. */
> { "short_call", 0, 0, false, true, true, NULL, false },
> + /* Function which are not having the prologue and epilogue generated
> + by the compiler. */
> + { "naked", 0, 0, true, false, false, arc_handle_fndecl_attribute, false },
> { NULL, 0, 0, false, false, false, NULL, false }
> };
> static int arc_comp_type_attributes (const_tree, const_tree);
> @@ -513,6 +517,12 @@ static void arc_finalize_pic (void);
> #define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
> #define TARGET_SPILL_CLASS arc_spill_class
>
> +#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
> +#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS arc_allocate_stack_slots_for_args
> +
> +#undef TARGET_WARN_FUNC_RETURN
> +#define TARGET_WARN_FUNC_RETURN arc_warn_func_return
> +
> #include "target-def.h"
>
> #undef TARGET_ASM_ALIGNED_HI_OP
> @@ -1856,6 +1866,42 @@ arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
> return NULL_TREE;
> }
>
> +static tree
> +arc_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
> + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
> +{
> + if (TREE_CODE (*node) != FUNCTION_DECL)
> + {
> + warning (OPT_Wattributes, "%qE attribute only applies to functions",
> + name);
> + *no_add_attrs = true;
> + }
> +
> + return NULL_TREE;
> +}
> +
> +/* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
> +
> +static bool
> +arc_allocate_stack_slots_for_args (void)
> +{
> + /* Naked functions should not allocate stack slots for arguments. */
> + unsigned int fn_type = arc_compute_function_type (cfun);
> +
> + return !ARC_NAKED_P(fn_type);
> +}
> +
> +/* Implement `TARGET_WARN_FUNC_RETURN'. */
> +
> +static bool
> +arc_warn_func_return (tree decl)
> +{
> + struct function *func = DECL_STRUCT_FUNCTION (decl);
> + unsigned int fn_type = arc_compute_function_type (func);
> +
> + return !ARC_NAKED_P (fn_type);
> +}
> +
> /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
> and two if they are nearly compatible (which causes a warning to be
> generated). */
> @@ -2359,7 +2405,7 @@ struct GTY (()) arc_frame_info
>
> typedef struct GTY (()) machine_function
> {
> - enum arc_function_type fn_type;
> + unsigned int fn_type;
> struct arc_frame_info frame_info;
> /* To keep track of unalignment caused by short insns. */
> int unalign;
> @@ -2377,43 +2423,40 @@ typedef struct GTY (()) machine_function
> The result is cached. To reset the cache at the end of a function,
> call with DECL = NULL_TREE. */
>
> -enum arc_function_type
> +unsigned int
> arc_compute_function_type (struct function *fun)
> {
> - tree decl = fun->decl;
> - tree a;
> - enum arc_function_type fn_type = fun->machine->fn_type;
> + tree attr, decl = fun->decl;
> + unsigned int fn_type = fun->machine->fn_type;
>
> if (fn_type != ARC_FUNCTION_UNKNOWN)
> return fn_type;
>
> - /* Assume we have a normal function (not an interrupt handler). */
> - fn_type = ARC_FUNCTION_NORMAL;
> + /* Check if it is a naked function. */
> + if (lookup_attribute ("naked", DECL_ATTRIBUTES (decl)) != NULL_TREE)
> + fn_type |= ARC_FUNCTION_NAKED;
> + else
> + fn_type |= ARC_FUNCTION_NORMAL;
>
> /* Now see if this is an interrupt handler. */
> - for (a = DECL_ATTRIBUTES (decl);
> - a;
> - a = TREE_CHAIN (a))
> - {
> - tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
> -
> - if (name == get_identifier ("interrupt")
> - && list_length (args) == 1
> - && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
> - {
> - tree value = TREE_VALUE (args);
> -
> - if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
> - || !strcmp (TREE_STRING_POINTER (value), "ilink"))
> - fn_type = ARC_FUNCTION_ILINK1;
> - else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
> - fn_type = ARC_FUNCTION_ILINK2;
> - else if (!strcmp (TREE_STRING_POINTER (value), "firq"))
> - fn_type = ARC_FUNCTION_FIRQ;
> - else
> - gcc_unreachable ();
> - break;
> - }
> + attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
> + if (attr != NULL_TREE)
> + {
> + tree value, args = TREE_VALUE (attr);
> +
> + gcc_assert (list_length (args) == 1);
> + value = TREE_VALUE (args);
> + gcc_assert (TREE_CODE (value) == STRING_CST);
> +
> + if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
> + || !strcmp (TREE_STRING_POINTER (value), "ilink"))
> + fn_type |= ARC_FUNCTION_ILINK1;
> + else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
> + fn_type |= ARC_FUNCTION_ILINK2;
> + else if (!strcmp (TREE_STRING_POINTER (value), "firq"))
> + fn_type |= ARC_FUNCTION_FIRQ;
> + else
> + gcc_unreachable ();
> }
>
> return fun->machine->fn_type = fn_type;
> @@ -2434,7 +2477,7 @@ arc_compute_function_type (struct function *fun)
> static bool
> arc_must_save_register (int regno, struct function *func)
> {
> - enum arc_function_type fn_type = arc_compute_function_type (func);
> + unsigned int fn_type = arc_compute_function_type (func);
> bool irq_auto_save_p = ((irq_ctrl_saved.irq_save_last_reg >= regno)
> && ARC_AUTO_IRQ_P (fn_type));
> bool firq_auto_save_p = ARC_FAST_INTERRUPT_P (fn_type);
> @@ -2879,7 +2922,11 @@ arc_expand_prologue (void)
> Change the stack layout so that we rather store a high register with the
> PRE_MODIFY, thus enabling more short insn generation.) */
> int first_offset = 0;
> - enum arc_function_type fn_type = arc_compute_function_type (cfun);
> + unsigned int fn_type = arc_compute_function_type (cfun);
> +
> + /* Naked functions don't have prologue. */
> + if (ARC_NAKED_P (fn_type))
> + return;
>
> size = ARC_STACK_ALIGN (size);
>
> @@ -2990,7 +3037,7 @@ void
> arc_expand_epilogue (int sibcall_p)
> {
> int size = get_frame_size ();
> - enum arc_function_type fn_type = arc_compute_function_type (cfun);
> + unsigned int fn_type = arc_compute_function_type (cfun);
>
> size = ARC_STACK_ALIGN (size);
> size = (!cfun->machine->frame_info.initialized
> @@ -3006,6 +3053,10 @@ arc_expand_epilogue (int sibcall_p)
> int millicode_p = cfun->machine->frame_info.millicode_end_reg > 0;
> rtx insn;
>
> + /* Naked functions don't have epilogue. */
> + if (ARC_NAKED_P (fn_type))
> + return;
> +
> size_to_deallocate = size;
>
> frame_size = size - (pretend_size +
> @@ -9789,37 +9840,60 @@ arc_can_follow_jump (const rtx_insn *follower, const rtx_insn *followee)
> return true;
> }
>
> -int arc_return_address_regs[5] =
> - {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM, ILINK1_REGNUM};
> +/* Return the register number of the register holding the return address
> + for a function of type TYPE. */
> +
> +int
> +arc_return_address_register (unsigned int fn_type)
> +{
> + int regno = 0;
> +
> + if (ARC_INTERRUPT_P (fn_type))
> + {
> + if (((fn_type & ARC_FUNCTION_ILINK1) | ARC_FUNCTION_FIRQ) != 0)
> + regno = ILINK1_REGNUM;
> + else if ((fn_type & ARC_FUNCTION_ILINK2) != 0)
> + regno = ILINK2_REGNUM;
> + else
> + gcc_unreachable ();
> + }
> + else if (ARC_NORMAL_P (fn_type) || ARC_NAKED_P (fn_type))
> + regno = RETURN_ADDR_REGNUM;
> +
> + gcc_assert (regno != 0);
> + return regno;
> +}
>
> -/* Implement EPILOGUE__USES.
> +/* Implement EPILOGUE_USES.
> Return true if REGNO should be added to the deemed uses of the epilogue.
>
> - We use the return address
> - arc_return_address_regs[arc_compute_function_type (cfun)]. But
> - also, we have to make sure all the register restore instructions
> - are known to be live in interrupt functions, plus the blink
> - register if it is clobbered by the isr. */
> + We have to make sure all the register restore instructions are
> + known to be live in interrupt functions, plus the blink register if
> + it is clobbered by the isr. */
>
> bool
> arc_epilogue_uses (int regno)
> {
> + unsigned int fn_type;
> +
> if (regno == arc_tp_regno)
> return true;
> +
> + fn_type = arc_compute_function_type (cfun);
> if (reload_completed)
> {
> if (ARC_INTERRUPT_P (cfun->machine->fn_type))
> {
> if (!fixed_regs[regno])
> return true;
> - return ((regno == arc_return_address_regs[cfun->machine->fn_type])
> + return ((regno == arc_return_address_register (fn_type))
> || (regno == RETURN_ADDR_REGNUM));
> }
> else
> return regno == RETURN_ADDR_REGNUM;
> }
> else
> - return regno == arc_return_address_regs[arc_compute_function_type (cfun)];
> + return regno == arc_return_address_register (fn_type);
> }
>
> /* Helper for EH_USES macro. */
> diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
> index 5627eb4..149e876 100644
> --- a/gcc/config/arc/arc.h
> +++ b/gcc/config/arc/arc.h
> @@ -1363,10 +1363,6 @@ do { \
> #define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
> arc_asm_output_aligned_decl_local (STREAM, DECL, NAME, SIZE, ALIGNMENT, 0)
>
> -/* To translate the return value of arc_function_type into a register number
> - to jump through for function return. */
> -extern int arc_return_address_regs[5];
> -
> /* Debugging information. */
>
> /* Generate DBX and DWARF debugging information. */
> @@ -1499,22 +1495,38 @@ extern struct rtx_def *arc_compare_op0, *arc_compare_op1;
>
> /* ARC function types. */
> enum arc_function_type {
> - ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL,
> + /* No function should have the unknown type. This value is used to
> + indicate the that function type has not yet been computed. */
> + ARC_FUNCTION_UNKNOWN = 0,
> +
> + /* The normal function type indicates that the function has the
> + standard prologue and epilogue. */
> + ARC_FUNCTION_NORMAL = 1 << 0,
> /* These are interrupt handlers. The name corresponds to the register
> name that contains the return address. */
> - ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2,
> + ARC_FUNCTION_ILINK1 = 1 << 1,
> + ARC_FUNCTION_ILINK2 = 1 << 2,
> /* Fast interrupt is only available on ARCv2 processors. */
> - ARC_FUNCTION_FIRQ
> + ARC_FUNCTION_FIRQ = 1 << 3,
> + /* The naked function type indicates that the function does not have
> + prologue or epilogue, and that no stack frame is available. */
> + ARC_FUNCTION_NAKED = 1 << 4
> };
> -#define ARC_INTERRUPT_P(TYPE) \
> - (((TYPE) == ARC_FUNCTION_ILINK1) || ((TYPE) == ARC_FUNCTION_ILINK2) \
> - || ((TYPE) == ARC_FUNCTION_FIRQ))
>
> -#define ARC_FAST_INTERRUPT_P(TYPE) ((TYPE) == ARC_FUNCTION_FIRQ)
> +/* Check if a function is an interrupt function. */
> +#define ARC_INTERRUPT_P(TYPE) \
> + (((TYPE) & (ARC_FUNCTION_ILINK1 | ARC_FUNCTION_ILINK2 \
> + | ARC_FUNCTION_FIRQ)) != 0)
> +
> +/* Check if a function is a fast interrupt function. */
> +#define ARC_FAST_INTERRUPT_P(TYPE) (((TYPE) & ARC_FUNCTION_FIRQ) != 0)
> +
> +/* Check if a function is normal, that is, has standard prologue and
> + epilogue. */
> +#define ARC_NORMAL_P(TYPE) (((TYPE) & ARC_FUNCTION_NORMAL) != 0)
>
> -/* Compute the type of a function from its DECL. Needed for EPILOGUE_USES. */
> -struct function;
> -extern enum arc_function_type arc_compute_function_type (struct function *);
> +/* Check if a function is naked. */
> +#define ARC_NAKED_P(TYPE) (((TYPE) & ARC_FUNCTION_NAKED) != 0)
>
> /* Called by crtstuff.c to make calls to function FUNCTION that are defined in
> SECTION_OP, and then to switch back to text section. */
> diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
> index 9aa9cd7..0d14085 100644
> --- a/gcc/config/arc/arc.md
> +++ b/gcc/config/arc/arc.md
> @@ -505,8 +505,8 @@
> (cond [(eq_attr "in_delay_slot" "false")
> (const_string "no")
> (match_test "regno_clobbered_p
> - (arc_return_address_regs
> - [arc_compute_function_type (cfun)],
> + (arc_return_address_register
> + (arc_compute_function_type (cfun)),
> insn, SImode, 1)")
> (const_string "no")]
> (const_string "yes")))
> @@ -4859,7 +4859,8 @@
> {
> rtx reg
> = gen_rtx_REG (Pmode,
> - arc_return_address_regs[arc_compute_function_type (cfun)]);
> + arc_return_address_register (arc_compute_function_type
> + (cfun)));
>
> if (TARGET_V2
> && ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
> @@ -4908,7 +4909,8 @@
> xop[0] = operands[0];
> xop[1]
> = gen_rtx_REG (Pmode,
> - arc_return_address_regs[arc_compute_function_type (cfun)]);
> + arc_return_address_register (arc_compute_function_type
> + (cfun)));
>
> if (TARGET_PAD_RETURN)
> arc_pad_return ();
> diff --git a/gcc/testsuite/gcc.target/arc/naked-1.c b/gcc/testsuite/gcc.target/arc/naked-1.c
> new file mode 100644
> index 0000000..e45f433f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/naked-1.c
> @@ -0,0 +1,18 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0" } */
> +/* Check that naked functions don't place arguments on the stack at
> + optimisation level '-O0'. */
> +extern void bar (int);
> +
> +void __attribute__((naked))
> +foo (int n, int m)
> +{
> + bar (n + m);
> +}
> +/* { dg-final { scan-assembler "\tbl @bar" } } */
> +
> +/* Look for things that would appear in a non-naked function, but which
> + should not appear in a naked function. */
> +/* { dg-final { scan-assembler-not "\tj.* \\\[blink\\\]" } } */
> +/* { dg-final { scan-assembler-not "\tst.* " } } */
> +/* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
> diff --git a/gcc/testsuite/gcc.target/arc/naked-2.c b/gcc/testsuite/gcc.target/arc/naked-2.c
> new file mode 100644
> index 0000000..7b7262f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/naked-2.c
> @@ -0,0 +1,26 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0" } */
> +/* Check that naked functions don't place arguments on the stack at
> + optimisation level '-O0'. */
> +
> +#if defined(__HS__) || defined(__EM__)
> +# define ILINK "ilink"
> +#else
> +# define ILINK "ilink1"
> +#endif
> +
> +extern void bar (int);
> +
> +void __attribute__((naked, interrupt(ILINK)))
> +foo (int n, int m)
> +{
> + bar (n + m);
> +}
> +/* { dg-final { scan-assembler "\tbl @bar" } } */
> +
> +/* Look for things that would appear in a non-naked function, but which
> + should not appear in a naked function. */
> +/* { dg-final { scan-assembler-not "\trtie" } } */
> +/* { dg-final { scan-assembler-not "j.*\[ilink1\]" } } */
> +/* { dg-final { scan-assembler-not "\tst.* " } } */
> +/* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
> --
> 1.9.1
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 5/7] [ARC] Enable indexed loads for elf targers.
2017-06-01 13:37 [PATCH 0/7] [ARC] Bug fixing, add support for naked functions Claudiu Zissulescu
` (5 preceding siblings ...)
2017-06-01 13:38 ` [PATCH 1/7] [ARC] Add support for naked functions Claudiu Zissulescu
@ 2017-06-01 13:38 ` Claudiu Zissulescu
2017-07-13 11:55 ` Andrew Burgess
6 siblings, 1 reply; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-06-01 13:38 UTC (permalink / raw)
To: gcc-patches; +Cc: Claudiu.Zissulescu, Francois.Bedard, andrew.burgess
gcc/
2017-02-28 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/arc.opt (mindexed-loads): Use initial value
TARGET_INDEXED_LOADS_DEFAULT.
(mauto-modify-reg): Use initial value
TARGET_AUTO_MODIFY_REG_DEFAULT.
* config/arc/elf.h (TARGET_INDEXED_LOADS_DEFAULT): Define.
(TARGET_AUTO_MODIFY_REG_DEFAULT): Likewise.
* config/arc/linux.h (TARGET_INDEXED_LOADS_DEFAULT): Define.
(TARGET_AUTO_MODIFY_REG_DEFAULT): Likewise.
---
gcc/config/arc/arc.opt | 4 ++--
gcc/config/arc/elf.h | 8 ++++++++
gcc/config/arc/linux.h | 8 ++++++++
3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
index f01a2ff..ed2b827 100644
--- a/gcc/config/arc/arc.opt
+++ b/gcc/config/arc/arc.opt
@@ -270,11 +270,11 @@ Target RejectNegative Var(arc_tune, TUNE_ARC700_4_2_XMAC)
Tune for ARC700 R4.2 Cpu with XMAC block.
mindexed-loads
-Target Var(TARGET_INDEXED_LOADS)
+Target Var(TARGET_INDEXED_LOADS) Init(TARGET_INDEXED_LOADS_DEFAULT)
Enable the use of indexed loads.
mauto-modify-reg
-Target Var(TARGET_AUTO_MODIFY_REG)
+Target Var(TARGET_AUTO_MODIFY_REG) Init(TARGET_AUTO_MODIFY_REG_DEFAULT)
Enable the use of pre/post modify with register displacement.
mmul32x16
diff --git a/gcc/config/arc/elf.h b/gcc/config/arc/elf.h
index c5794f8..43f3408 100644
--- a/gcc/config/arc/elf.h
+++ b/gcc/config/arc/elf.h
@@ -58,3 +58,11 @@ along with GCC; see the file COPYING3. If not see
/* Bare-metal toolchains do not need a thread pointer register. */
#undef TARGET_ARC_TP_REGNO_DEFAULT
#define TARGET_ARC_TP_REGNO_DEFAULT -1
+
+/* Indexed loads are default. */
+#undef TARGET_INDEXED_LOADS_DEFAULT
+#define TARGET_INDEXED_LOADS_DEFAULT 1
+
+/* Pre/post modify with register displacement are default. */
+#undef TARGET_AUTO_MODIFY_REG_DEFAULT
+#define TARGET_AUTO_MODIFY_REG_DEFAULT 1
diff --git a/gcc/config/arc/linux.h b/gcc/config/arc/linux.h
index 83e5a1d..d8e0063 100644
--- a/gcc/config/arc/linux.h
+++ b/gcc/config/arc/linux.h
@@ -83,3 +83,11 @@ along with GCC; see the file COPYING3. If not see
#define SUBTARGET_CPP_SPEC "\
%{pthread:-D_REENTRANT} \
"
+
+/* Indexed loads are default off. */
+#undef TARGET_INDEXED_LOADS_DEFAULT
+#define TARGET_INDEXED_LOADS_DEFAULT 0
+
+/* Pre/post modify with register displacement are default off. */
+#undef TARGET_AUTO_MODIFY_REG_DEFAULT
+#define TARGET_AUTO_MODIFY_REG_DEFAULT 0
--
1.9.1
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 5/7] [ARC] Enable indexed loads for elf targers.
2017-06-01 13:38 ` [PATCH 5/7] [ARC] Enable indexed loads for elf targers Claudiu Zissulescu
@ 2017-07-13 11:55 ` Andrew Burgess
2017-07-13 13:08 ` Claudiu Zissulescu
2017-07-17 12:33 ` Claudiu Zissulescu
0 siblings, 2 replies; 27+ messages in thread
From: Andrew Burgess @ 2017-07-13 11:55 UTC (permalink / raw)
To: Claudiu Zissulescu; +Cc: gcc-patches, Francois.Bedard
* Claudiu Zissulescu <Claudiu.Zissulescu@synopsys.com> [2017-06-01 15:34:55 +0200]:
> gcc/
> 2017-02-28 Claudiu Zissulescu <claziss@synopsys.com>
>
> * config/arc/arc.opt (mindexed-loads): Use initial value
> TARGET_INDEXED_LOADS_DEFAULT.
> (mauto-modify-reg): Use initial value
> TARGET_AUTO_MODIFY_REG_DEFAULT.
> * config/arc/elf.h (TARGET_INDEXED_LOADS_DEFAULT): Define.
> (TARGET_AUTO_MODIFY_REG_DEFAULT): Likewise.
> * config/arc/linux.h (TARGET_INDEXED_LOADS_DEFAULT): Define.
> (TARGET_AUTO_MODIFY_REG_DEFAULT): Likewise.
The change looks fine, but it would be nice if the commit message
explained _why_ we are default off for Linux and on for Elf, I think
more text in the commit message on this sort of thing will help future
developers understand why things are the way they are.
Thanks,
Andrew
> ---
> gcc/config/arc/arc.opt | 4 ++--
> gcc/config/arc/elf.h | 8 ++++++++
> gcc/config/arc/linux.h | 8 ++++++++
> 3 files changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
> index f01a2ff..ed2b827 100644
> --- a/gcc/config/arc/arc.opt
> +++ b/gcc/config/arc/arc.opt
> @@ -270,11 +270,11 @@ Target RejectNegative Var(arc_tune, TUNE_ARC700_4_2_XMAC)
> Tune for ARC700 R4.2 Cpu with XMAC block.
>
> mindexed-loads
> -Target Var(TARGET_INDEXED_LOADS)
> +Target Var(TARGET_INDEXED_LOADS) Init(TARGET_INDEXED_LOADS_DEFAULT)
> Enable the use of indexed loads.
>
> mauto-modify-reg
> -Target Var(TARGET_AUTO_MODIFY_REG)
> +Target Var(TARGET_AUTO_MODIFY_REG) Init(TARGET_AUTO_MODIFY_REG_DEFAULT)
> Enable the use of pre/post modify with register displacement.
>
> mmul32x16
> diff --git a/gcc/config/arc/elf.h b/gcc/config/arc/elf.h
> index c5794f8..43f3408 100644
> --- a/gcc/config/arc/elf.h
> +++ b/gcc/config/arc/elf.h
> @@ -58,3 +58,11 @@ along with GCC; see the file COPYING3. If not see
> /* Bare-metal toolchains do not need a thread pointer register. */
> #undef TARGET_ARC_TP_REGNO_DEFAULT
> #define TARGET_ARC_TP_REGNO_DEFAULT -1
> +
> +/* Indexed loads are default. */
> +#undef TARGET_INDEXED_LOADS_DEFAULT
> +#define TARGET_INDEXED_LOADS_DEFAULT 1
> +
> +/* Pre/post modify with register displacement are default. */
> +#undef TARGET_AUTO_MODIFY_REG_DEFAULT
> +#define TARGET_AUTO_MODIFY_REG_DEFAULT 1
> diff --git a/gcc/config/arc/linux.h b/gcc/config/arc/linux.h
> index 83e5a1d..d8e0063 100644
> --- a/gcc/config/arc/linux.h
> +++ b/gcc/config/arc/linux.h
> @@ -83,3 +83,11 @@ along with GCC; see the file COPYING3. If not see
> #define SUBTARGET_CPP_SPEC "\
> %{pthread:-D_REENTRANT} \
> "
> +
> +/* Indexed loads are default off. */
> +#undef TARGET_INDEXED_LOADS_DEFAULT
> +#define TARGET_INDEXED_LOADS_DEFAULT 0
> +
> +/* Pre/post modify with register displacement are default off. */
> +#undef TARGET_AUTO_MODIFY_REG_DEFAULT
> +#define TARGET_AUTO_MODIFY_REG_DEFAULT 0
> --
> 1.9.1
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: [PATCH 5/7] [ARC] Enable indexed loads for elf targers.
2017-07-13 11:55 ` Andrew Burgess
@ 2017-07-13 13:08 ` Claudiu Zissulescu
2017-07-17 12:33 ` Claudiu Zissulescu
1 sibling, 0 replies; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-07-13 13:08 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gcc-patches, Francois.Bedard
> The change looks fine, but it would be nice if the commit message
> explained _why_ we are default off for Linux and on for Elf, I think
> more text in the commit message on this sort of thing will help future
> developers understand why things are the way they are.
>
This explanation is quite simple, we haven't fully validated Linux with those options on. As it may take a while until I am getting a more complete image on this enhancement for Linux, I've enabled this option for elf, where I've got very good feedback from our gnu users.
Normally, it should be no problem to enable them for Linux as well, but I would like to have more testing data on this subject from various gnu users.
Thanks,
Claudiu
^ permalink raw reply [flat|nested] 27+ messages in thread
* RE: [PATCH 5/7] [ARC] Enable indexed loads for elf targers.
2017-07-13 11:55 ` Andrew Burgess
2017-07-13 13:08 ` Claudiu Zissulescu
@ 2017-07-17 12:33 ` Claudiu Zissulescu
1 sibling, 0 replies; 27+ messages in thread
From: Claudiu Zissulescu @ 2017-07-17 12:33 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gcc-patches, Francois.Bedard
> The change looks fine, but it would be nice if the commit message
> explained _why_ we are default off for Linux and on for Elf, I think
> more text in the commit message on this sort of thing will help future
> developers understand why things are the way they are.
>
Committed with suggested annotations. Thank you for your review,
Claudiu
^ permalink raw reply [flat|nested] 27+ messages in thread