Commit 5acc47a4 by Kyrylo Tkachov Committed by Kyrylo Tkachov

[ARM] PR target/70830: Avoid POP-{reglist}^ when returning from interrupt handlers

	PR target/70830
	* config/arm/arm.c (arm_output_multireg_pop): Avoid POP instruction
	when popping the PC and within an interrupt handler routine.
	Add missing tab to output of "ldmfd".
	(output_return_instruction): Output LDMFD with SP update rather
	than POP when returning from interrupt handler.

	* gcc.target/arm/interrupt-1.c: Change dg-compile to dg-assemble.
	Add -save-temps to dg-options.
	Scan for ldmfd rather than pop instruction.
	* gcc.target/arm/interrupt-2.c: Likewise.
	* gcc.target/arm/pr70830.c: New test.

From-SVN: r236169
parent 3cd63842
2016-05-12 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR target/70830
* config/arm/arm.c (arm_output_multireg_pop): Avoid POP instruction
when popping the PC and within an interrupt handler routine.
Add missing tab to output of "ldmfd".
(output_return_instruction): Output LDMFD with SP update rather
than POP when returning from interrupt handler.
2016-05-12 Jakub Jelinek <jakub@redhat.com>
* config/i386/i386.md (isa): Add x64_avx512dq, enable if
......
......@@ -17755,6 +17755,7 @@ arm_output_multireg_pop (rtx *operands, bool return_pc, rtx cond, bool reverse,
int num_saves = XVECLEN (operands[0], 0);
unsigned int regno;
unsigned int regno_base = REGNO (operands[1]);
bool interrupt_p = IS_INTERRUPT (arm_current_func_type ());
offset = 0;
offset += update ? 1 : 0;
......@@ -17772,7 +17773,8 @@ arm_output_multireg_pop (rtx *operands, bool return_pc, rtx cond, bool reverse,
}
conditional = reverse ? "%?%D0" : "%?%d0";
if ((regno_base == SP_REGNUM) && update)
/* Can't use POP if returning from an interrupt. */
if ((regno_base == SP_REGNUM) && !(interrupt_p && return_pc))
{
sprintf (pattern, "pop%s\t{", conditional);
}
......@@ -17781,11 +17783,8 @@ arm_output_multireg_pop (rtx *operands, bool return_pc, rtx cond, bool reverse,
/* Output ldmfd when the base register is SP, otherwise output ldmia.
It's just a convention, their semantics are identical. */
if (regno_base == SP_REGNUM)
/* update is never true here, hence there is no need to handle
pop here. */
sprintf (pattern, "ldmfd%s", conditional);
if (update)
sprintf (pattern, "ldmfd%s\t", conditional);
else if (update)
sprintf (pattern, "ldmia%s\t", conditional);
else
sprintf (pattern, "ldm%s\t", conditional);
......@@ -17811,7 +17810,7 @@ arm_output_multireg_pop (rtx *operands, bool return_pc, rtx cond, bool reverse,
strcat (pattern, "}");
if (IS_INTERRUPT (arm_current_func_type ()) && return_pc)
if (interrupt_p && return_pc)
strcat (pattern, "^");
output_asm_insn (pattern, &cond);
......@@ -19622,8 +19621,12 @@ output_return_instruction (rtx operand, bool really_return, bool reverse,
sprintf (instr, "ldmfd%s\t%%|sp, {", conditional);
}
}
/* For interrupt returns we have to use an LDM rather than
a POP so that we can use the exception return variant. */
else if (IS_INTERRUPT (func_type))
sprintf (instr, "ldmfd%s\t%%|sp!, {", conditional);
else
sprintf (instr, "pop%s\t{", conditional);
sprintf (instr, "pop%s\t{", conditional);
p = instr + strlen (instr);
......
2016-05-12 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR target/70830
* gcc.target/arm/interrupt-1.c: Change dg-compile to dg-assemble.
Add -save-temps to dg-options.
Scan for ldmfd rather than pop instruction.
* gcc.target/arm/interrupt-2.c: Likewise.
* gcc.target/arm/pr70830.c: New test.
2016-05-12 Jakub Jelinek <jakub@redhat.com>
* gcc.target/i386/avx512bw-vpextr-1.c: New test.
......
/* Verify that prologue and epilogue are correct for functions with
__attribute__ ((interrupt)). */
/* { dg-do compile } */
/* { dg-do assemble } */
/* { dg-require-effective-target arm_nothumb } */
/* { dg-options "-O0 -marm" } */
/* { dg-options "-O0 -marm -save-temps" } */
/* This test is not valid when -mthumb. */
extern void bar (int);
......@@ -14,4 +14,4 @@ void foo ()
}
/* { dg-final { scan-assembler "push\t{r0, r1, r2, r3, r4, fp, ip, lr}" } } */
/* { dg-final { scan-assembler "pop\t{r0, r1, r2, r3, r4, fp, ip, pc}\\^" } } */
/* { dg-final { scan-assembler "ldmfd\tsp!, {r0, r1, r2, r3, r4, fp, ip, pc}\\^" } } */
/* Verify that prologue and epilogue are correct for functions with
__attribute__ ((interrupt)). */
/* { dg-do compile } */
/* { dg-do assemble } */
/* { dg-require-effective-target arm_nothumb } */
/* { dg-options "-O1 -marm" } */
/* { dg-options "-O1 -marm -save-temps" } */
/* This test is not valid when -mthumb. */
extern void bar (int);
......@@ -16,4 +16,4 @@ void test()
}
/* { dg-final { scan-assembler "push\t{r0, r1, r2, r3, r4, r5, ip, lr}" } } */
/* { dg-final { scan-assembler "pop\t{r0, r1, r2, r3, r4, r5, ip, pc}\\^" } } */
/* { dg-final { scan-assembler "ldmfd\tsp!, {r0, r1, r2, r3, r4, r5, ip, pc}\\^" } } */
/* PR target/70830. */
/* { dg-do assemble } */
/* { dg-require-effective-target arm_arm_ok } */
/* { dg-options "-Os -marm -save-temps" } */
/* This test is not valid when -mthumb. */
extern void prints (char *);
void __attribute__ ((interrupt ("IRQ"))) dm3730_IRQHandler(void)
{
prints("IRQ" );
}
/* { dg-final { scan-assembler "ldmfd\tsp!, {r0, r1, r2, r3, ip, pc}\\^" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment