Browse Source

xtensa: fix bootup, add buildroot patches

Waldemar Brodkorb 2 years ago
parent
commit
4dac543bb6

+ 1 - 0
target/xtensa/kernel/qemu-xtensa

@@ -1,3 +1,4 @@
 CONFIG_XTENSA=y
 CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,38400 memmap=0x04000000@0"

+ 41 - 0
toolchain/binutils/patches/2.32/0003-bfd-xtensa-fix-shrink_dynamic_reloc_sections-for-exp.patch

@@ -0,0 +1,41 @@
+From 278989f23735aa501be1052e085540c75c126dbb Mon Sep 17 00:00:00 2001
+From: Max Filippov <jcmvbkbc@gmail.com>
+Date: Thu, 28 Mar 2019 17:03:57 -0700
+Subject: [PATCH] bfd: xtensa: fix shrink_dynamic_reloc_sections for
+ export-dynamic
+
+shrink_dynamic_reloc_sections must remove PLT entry that was created for
+an undefined weak symbol in the presence of --export-dynamic option when
+relaxation coalesces literals pointing to that symbol. This fixes the
+following assertion:
+
+  ld: BFD (GNU Binutils) 2.31.1 internal error, aborting at
+  elf32-xtensa.c:3292 in elf_xtensa_finish_dynamic_sections
+
+2019-03-28  Max Filippov  <jcmvbkbc@gmail.com>
+bfd/
+	* elf32-xtensa.c (shrink_dynamic_reloc_sections): Add
+	info->export_dynamic to the conditional.
+
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
+---
+ bfd/elf32-xtensa.c                                         |  3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
+index c3df3d6db756..37ea200eea74 100644
+--- a/bfd/elf32-xtensa.c
++++ b/bfd/elf32-xtensa.c
+@@ -10083,7 +10083,8 @@ shrink_dynamic_reloc_sections (struct bfd_link_info *info,
+       && (input_section->flags & SEC_ALLOC) != 0
+       && (dynamic_symbol || bfd_link_pic (info))
+       && (!h || h->root.type != bfd_link_hash_undefweak
+-	  || (dynamic_symbol && bfd_link_dll (info))))
++	  || (dynamic_symbol
++	      && (bfd_link_dll (info) || info->export_dynamic))))
+     {
+       asection *srel;
+       bfd_boolean is_plt = FALSE;
+-- 
+2.11.0
+

+ 294 - 0
toolchain/binutils/patches/2.32/0004-gas-use-literals-const16-for-xtensa-loop-relaxation.patch

@@ -0,0 +1,294 @@
+From 0dbdfb7918d0b0cfcb8883b24c1291574bf5bb7c Mon Sep 17 00:00:00 2001
+From: Max Filippov <jcmvbkbc@gmail.com>
+Date: Tue, 2 Apr 2019 14:32:42 -0700
+Subject: [PATCH] gas: use literals/const16 for xtensa loop relaxation
+
+Loop opcode relaxation that uses addi/addmi doesn't work well with other
+relaxations that may cause code movement. Instead of encoding fixed loop
+end offset in the relaxed sequence use l32r or a pair of const16 to load
+loop end address. This way the address of the loop end gets a relocation
+record and it gets updated appropriately.
+
+gas/
+2019-04-02  Max Filippov  <jcmvbkbc@gmail.com>
+
+	* config/tc-xtensa.c (convert_frag_immed): Drop
+	convert_frag_immed_finish_loop invocation.
+	(convert_frag_immed_finish_loop): Drop declaration and
+	definition.
+	* config/xtensa-relax.c (widen_spec_list): Replace loop
+	widening that uses addi/addmi with widening that uses l32r
+	and const16.
+
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
+---
+ gas/config/tc-xtensa.c    | 120 ----------------------------------------------
+ gas/config/xtensa-relax.c |  77 ++++++++++++++++++++---------
+ 2 files changed, 55 insertions(+), 142 deletions(-)
+
+diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
+index 3bdbbc931cfc..0cc06361cf6f 100644
+--- a/gas/config/tc-xtensa.c
++++ b/gas/config/tc-xtensa.c
+@@ -10668,7 +10668,6 @@ convert_frag_fill_nop (fragS *fragP)
+ static fixS *fix_new_exp_in_seg
+   (segT, subsegT, fragS *, int, int, expressionS *, int,
+    bfd_reloc_code_real_type);
+-static void convert_frag_immed_finish_loop (segT, fragS *, TInsn *);
+ 
+ static void
+ convert_frag_immed (segT segP,
+@@ -10910,9 +10909,6 @@ convert_frag_immed (segT segP,
+ 	}
+     }
+ 
+-  if (expanded && xtensa_opcode_is_loop (isa, orig_tinsn.opcode) == 1)
+-    convert_frag_immed_finish_loop (segP, fragP, &orig_tinsn);
+-
+   if (expanded && is_direct_call_opcode (orig_tinsn.opcode))
+     {
+       /* Add an expansion note on the expanded instruction.  */
+@@ -10949,122 +10945,6 @@ fix_new_exp_in_seg (segT new_seg,
+ }
+ 
+ 
+-/* Relax a loop instruction so that it can span loop >256 bytes.
+-
+-                  loop    as, .L1
+-          .L0:
+-                  rsr     as, LEND
+-                  wsr     as, LBEG
+-                  addi    as, as, lo8 (label-.L1)
+-                  addmi   as, as, mid8 (label-.L1)
+-                  wsr     as, LEND
+-                  isync
+-                  rsr     as, LCOUNT
+-                  addi    as, as, 1
+-          .L1:
+-                  <<body>>
+-          label:
+-*/
+-
+-static void
+-convert_frag_immed_finish_loop (segT segP, fragS *fragP, TInsn *tinsn)
+-{
+-  TInsn loop_insn;
+-  TInsn addi_insn;
+-  TInsn addmi_insn;
+-  unsigned long target;
+-  static xtensa_insnbuf insnbuf = NULL;
+-  unsigned int loop_length, loop_length_hi, loop_length_lo;
+-  xtensa_isa isa = xtensa_default_isa;
+-  addressT loop_offset;
+-  addressT addi_offset = 9;
+-  addressT addmi_offset = 12;
+-  fragS *next_fragP;
+-  int target_count;
+-
+-  if (!insnbuf)
+-    insnbuf = xtensa_insnbuf_alloc (isa);
+-
+-  /* Get the loop offset.  */
+-  loop_offset = get_expanded_loop_offset (tinsn->opcode);
+-
+-  /* Validate that there really is a LOOP at the loop_offset.  Because
+-     loops are not bundleable, we can assume that the instruction will be
+-     in slot 0.  */
+-  tinsn_from_chars (&loop_insn, fragP->fr_opcode + loop_offset, 0);
+-  tinsn_immed_from_frag (&loop_insn, fragP, 0);
+-
+-  gas_assert (xtensa_opcode_is_loop (isa, loop_insn.opcode) == 1);
+-  addi_offset += loop_offset;
+-  addmi_offset += loop_offset;
+-
+-  gas_assert (tinsn->ntok == 2);
+-  if (tinsn->tok[1].X_op == O_constant)
+-    target = tinsn->tok[1].X_add_number;
+-  else if (tinsn->tok[1].X_op == O_symbol)
+-    {
+-      /* Find the fragment.  */
+-      symbolS *sym = tinsn->tok[1].X_add_symbol;
+-      gas_assert (S_GET_SEGMENT (sym) == segP
+-	      || S_GET_SEGMENT (sym) == absolute_section);
+-      target = (S_GET_VALUE (sym) + tinsn->tok[1].X_add_number);
+-    }
+-  else
+-    {
+-      as_bad (_("invalid expression evaluation type %d"), tinsn->tok[1].X_op);
+-      target = 0;
+-    }
+-
+-  loop_length = target - (fragP->fr_address + fragP->fr_fix);
+-  loop_length_hi = loop_length & ~0x0ff;
+-  loop_length_lo = loop_length & 0x0ff;
+-  if (loop_length_lo >= 128)
+-    {
+-      loop_length_lo -= 256;
+-      loop_length_hi += 256;
+-    }
+-
+-  /* Because addmi sign-extends the immediate, 'loop_length_hi' can be at most
+-     32512.  If the loop is larger than that, then we just fail.  */
+-  if (loop_length_hi > 32512)
+-    as_bad_where (fragP->fr_file, fragP->fr_line,
+-		  _("loop too long for LOOP instruction"));
+-
+-  tinsn_from_chars (&addi_insn, fragP->fr_opcode + addi_offset, 0);
+-  gas_assert (addi_insn.opcode == xtensa_addi_opcode);
+-
+-  tinsn_from_chars (&addmi_insn, fragP->fr_opcode + addmi_offset, 0);
+-  gas_assert (addmi_insn.opcode == xtensa_addmi_opcode);
+-
+-  set_expr_const (&addi_insn.tok[2], loop_length_lo);
+-  tinsn_to_insnbuf (&addi_insn, insnbuf);
+-
+-  fragP->tc_frag_data.is_insn = TRUE;
+-  xtensa_insnbuf_to_chars
+-    (isa, insnbuf, (unsigned char *) fragP->fr_opcode + addi_offset, 0);
+-
+-  set_expr_const (&addmi_insn.tok[2], loop_length_hi);
+-  tinsn_to_insnbuf (&addmi_insn, insnbuf);
+-  xtensa_insnbuf_to_chars
+-    (isa, insnbuf, (unsigned char *) fragP->fr_opcode + addmi_offset, 0);
+-
+-  /* Walk through all of the frags from here to the loop end
+-     and mark them as no_transform to keep them from being modified
+-     by the linker.  If we ever have a relocation for the
+-     addi/addmi of the difference of two symbols we can remove this.  */
+-
+-  target_count = 0;
+-  for (next_fragP = fragP; next_fragP != NULL;
+-       next_fragP = next_fragP->fr_next)
+-    {
+-      next_fragP->tc_frag_data.is_no_transform = TRUE;
+-      if (next_fragP->tc_frag_data.is_loop_target)
+-	target_count++;
+-      if (target_count == 2)
+-	break;
+-    }
+-}
+-
+ 
+ /* A map that keeps information on a per-subsegment basis.  This is
+    maintained during initial assembly, but is invalid once the
+diff --git a/gas/config/xtensa-relax.c b/gas/config/xtensa-relax.c
+index cb296ed85ed2..daf15d52c259 100644
+--- a/gas/config/xtensa-relax.c
++++ b/gas/config/xtensa-relax.c
+@@ -87,13 +87,7 @@
+    when the first and second operands are not the same as specified
+    by the "| %at!=%as" precondition clause.
+    {"l32i %at,%as,%imm | %at!=%as",
+-   "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l32i %at,%at,0"}
+-
+-   There is special case for loop instructions here, but because we do
+-   not currently have the ability to represent the difference of two
+-   symbols, the conversion requires special code in the assembler to
+-   write the operands of the addi/addmi pair representing the
+-   difference of the old and new loop end label.  */
++   "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l32i %at,%at,0"}  */
+ 
+ #include "as.h"
+ #include "xtensa-isa.h"
+@@ -306,44 +300,83 @@ static string_pattern_pair widen_spec_list[] =
+   {"l32i %at,%as,%imm | %at!=%as ? IsaUseConst16",
+    "const16 %at,HI16U(%imm); const16 %at,LOW16U(%imm); add %at,%at,%as; l32i %at,%at,0"},
+ 
+-  /* This is only PART of the loop instruction.  In addition,
+-     hardcoded into its use is a modification of the final operand in
+-     the instruction in bytes 9 and 12.  */
+-  {"loop %as,%label | %as!=1 ? IsaUseLoops",
++  /* Widening loops with literals.  */
++  {"loop %as,%label | %as!=1 ? IsaUseLoops ? IsaUseL32R",
++   "loop %as,%LABEL;"
++   "rsr.lend    %as;"		/* LEND */
++   "wsr.lbeg    %as;"		/* LBEG */
++   "LITERAL     %label;"
++   "l32r        %as, %LITERAL;"
++   "nop;"
++   "wsr.lend    %as;"
++   "isync;"
++   "rsr.lcount    %as;"		/* LCOUNT */
++   "addi    %as, %as, 1;"
++   "LABEL"},
++  {"loopgtz %as,%label | %as!=1 ? IsaUseLoops ? IsaUseL32R",
++   "beqz    %as,%label;"
++   "bltz    %as,%label;"
++   "loopgtz %as,%LABEL;"
++   "rsr.lend    %as;"		/* LEND */
++   "wsr.lbeg    %as;"		/* LBEG */
++   "LITERAL     %label;"
++   "l32r        %as, %LITERAL;"
++   "nop;"
++   "wsr.lend    %as;"
++   "isync;"
++   "rsr.lcount    %as;"		/* LCOUNT */
++   "addi    %as, %as, 1;"
++   "LABEL"},
++  {"loopnez %as,%label | %as!=1 ? IsaUseLoops ? IsaUseL32R",
++   "beqz     %as,%label;"
++   "loopnez %as,%LABEL;"
++   "rsr.lend    %as;"		/* LEND */
++   "wsr.lbeg    %as;"		/* LBEG */
++   "LITERAL     %label;"
++   "l32r        %as, %LITERAL;"
++   "nop;"
++   "wsr.lend    %as;"
++   "isync;"
++   "rsr.lcount    %as;"		/* LCOUNT */
++   "addi    %as, %as, 1;"
++   "LABEL"},
++
++  /* Widening loops with const16.  */
++  {"loop %as,%label | %as!=1 ? IsaUseLoops ? IsaUseConst16",
+    "loop %as,%LABEL;"
+    "rsr.lend    %as;"		/* LEND */
+    "wsr.lbeg    %as;"		/* LBEG */
+-   "addi    %as, %as, 0;"	/* lo8(%label-%LABEL1) */
+-   "addmi   %as, %as, 0;"	/* mid8(%label-%LABEL1) */
++   "const16     %as,HI16U(%label);"
++   "const16     %as,LOW16U(%label);"
+    "wsr.lend    %as;"
+    "isync;"
+    "rsr.lcount    %as;"		/* LCOUNT */
+-   "addi    %as, %as, 1;"	/* density -> addi.n %as, %as, 1 */
++   "addi    %as, %as, 1;"
+    "LABEL"},
+-  {"loopgtz %as,%label | %as!=1 ? IsaUseLoops",
++  {"loopgtz %as,%label | %as!=1 ? IsaUseLoops ? IsaUseConst16",
+    "beqz    %as,%label;"
+    "bltz    %as,%label;"
+    "loopgtz %as,%LABEL;"
+    "rsr.lend    %as;"		/* LEND */
+    "wsr.lbeg    %as;"		/* LBEG */
+-   "addi    %as, %as, 0;"	/* lo8(%label-%LABEL1) */
+-   "addmi   %as, %as, 0;"	/* mid8(%label-%LABEL1) */
++   "const16     %as,HI16U(%label);"
++   "const16     %as,LOW16U(%label);"
+    "wsr.lend    %as;"
+    "isync;"
+    "rsr.lcount    %as;"		/* LCOUNT */
+-   "addi    %as, %as, 1;"	/* density -> addi.n %as, %as, 1 */
++   "addi    %as, %as, 1;"
+    "LABEL"},
+-  {"loopnez %as,%label | %as!=1 ? IsaUseLoops",
++  {"loopnez %as,%label | %as!=1 ? IsaUseLoops ? IsaUseConst16",
+    "beqz     %as,%label;"
+    "loopnez %as,%LABEL;"
+    "rsr.lend    %as;"		/* LEND */
+    "wsr.lbeg    %as;"		/* LBEG */
+-   "addi    %as, %as, 0;"	/* lo8(%label-%LABEL1) */
+-   "addmi   %as, %as, 0;"	/* mid8(%label-%LABEL1) */
++   "const16     %as,HI16U(%label);"
++   "const16     %as,LOW16U(%label);"
+    "wsr.lend    %as;"
+    "isync;"
+    "rsr.lcount    %as;"		/* LCOUNT */
+-   "addi    %as, %as, 1;"	/* density -> addi.n %as, %as, 1 */
++   "addi    %as, %as, 1;"
+    "LABEL"},
+ 
+   /* Relaxing to wide branches.  Order is important here.  With wide
+-- 
+2.11.0
+

+ 96 - 0
toolchain/binutils/patches/2.32/0005-xtensa-gas-put-.literal_position-at-section-start.patch

@@ -0,0 +1,96 @@
+From 471702ac4a57878a06e8167f063274cf413e548d Mon Sep 17 00:00:00 2001
+From: Max Filippov <jcmvbkbc@gmail.com>
+Date: Mon, 8 Apr 2019 13:47:18 -0700
+Subject: [PATCH] xtensa: gas: put .literal_position at section start
+
+Provide literal position at the beginning of each section for literal
+space reserved by relaxations when text-section-literals or
+auto-litpools options are used. Remove code that adds fill frag to the
+literal section for every .literal_position directive to avoid creation
+of empty literal sections.
+
+Fix auto-litpools tests that got literal pool address changes.
+
+gas/
+2019-04-11  Max Filippov  <jcmvbkbc@gmail.com>
+
+	* config/tc-xtensa.c (xtensa_is_init_fini): Add declaration.
+	(xtensa_mark_literal_pool_location): Don't add fill frag to literal
+	section that records literal pool location.
+	(md_begin): Call xtensa_mark_literal_pool_location when text
+	section literals or auto litpools are used.
+	(xtensa_elf_section_change_hook): Call
+	xtensa_mark_literal_pool_location when text section literals or
+	auto litpools are used, there's no literal pool location defined
+	for the current section and it's not .init or .fini.
+
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
+---
+ gas/config/tc-xtensa.c                          | 22 +++++++++-------------
+ 1 file changed, 9 insertions(+), 13 deletions(-)
+
+diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
+index 0cc06361cf6f..6a80e76fed8c 100644
+--- a/gas/config/tc-xtensa.c
++++ b/gas/config/tc-xtensa.c
+@@ -497,6 +497,7 @@ static fixS *xg_append_jump (fragS *fragP, symbolS *sym, offsetT offset);
+ static void xtensa_maybe_create_literal_pool_frag (bfd_boolean, bfd_boolean);
+ static bfd_boolean auto_litpools = FALSE;
+ static int auto_litpool_limit = 0;
++static bfd_boolean xtensa_is_init_fini (segT seg);
+ 
+ /* Alignment Functions.  */
+ 
+@@ -4797,7 +4798,6 @@ xtensa_mark_literal_pool_location (void)
+ {
+   /* Any labels pointing to the current location need
+      to be adjusted to after the literal pool.  */
+-  emit_state s;
+   fragS *pool_location;
+ 
+   if (use_literal_section)
+@@ -4818,19 +4818,7 @@ xtensa_mark_literal_pool_location (void)
+ 		RELAX_LITERAL_POOL_END, NULL, 0, NULL);
+   xtensa_set_frag_assembly_state (frag_now);
+ 
+-  /* Now put a frag into the literal pool that points to this location.  */
+   set_literal_pool_location (now_seg, pool_location);
+-  xtensa_switch_to_non_abs_literal_fragment (&s);
+-  frag_align (2, 0, 0);
+-  record_alignment (now_seg, 2);
+-
+-  /* Close whatever frag is there.  */
+-  frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
+-  xtensa_set_frag_assembly_state (frag_now);
+-  frag_now->tc_frag_data.literal_frag = pool_location;
+-  frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
+-  xtensa_restore_emit_state (&s);
+-  xtensa_set_frag_assembly_state (frag_now);
+ }
+ 
+ 
+@@ -5334,6 +5322,9 @@ md_begin (void)
+   /* Set up the assembly state.  */
+   if (!frag_now->tc_frag_data.is_assembly_state_set)
+     xtensa_set_frag_assembly_state (frag_now);
++
++  if (!use_literal_section)
++    xtensa_mark_literal_pool_location ();
+ }
+ 
+ 
+@@ -5933,6 +5924,11 @@ xtensa_elf_section_change_hook (void)
+   /* Set up the assembly state.  */
+   if (!frag_now->tc_frag_data.is_assembly_state_set)
+     xtensa_set_frag_assembly_state (frag_now);
++
++  if (!use_literal_section
++      && seg_info (now_seg)->tc_segment_info_data.literal_pool_loc == NULL
++      && !xtensa_is_init_fini (now_seg))
++    xtensa_mark_literal_pool_location ();
+ }
+ 
+ 
+-- 
+2.11.0
+

+ 43 - 0
toolchain/gcc/patches/8.3.0/0001-xtensa-backport-fix-for-PR-target-90922.patch

@@ -0,0 +1,43 @@
+From a592242578e573778241cae6d3928c064dcdfda4 Mon Sep 17 00:00:00 2001
+From: jcmvbkbc <jcmvbkbc@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Tue, 18 Jun 2019 22:19:12 +0000
+Subject: [PATCH] xtensa: fix for PR target/90922
+
+Stack pointer adjustment code in prologue missed a case of no
+callee-saved registers and a stack frame size bigger than 128 bytes.
+Handle that case.
+
+This fixes the following gcc tests with call0 ABI:
+  gcc.c-torture/execute/stdarg-2.c
+  gcc.dg/torture/pr55882.c
+  gcc.dg/torture/pr57569.c
+
+gcc/
+2019-06-18  Max Filippov  <jcmvbkbc@gmail.com>
+
+	* config/xtensa/xtensa.c (xtensa_expand_prologue): Add stack
+	pointer adjustment for the case of no callee-saved registers and
+	stack frame bigger than 128 bytes.
+
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
+---
+ gcc/config/xtensa/xtensa.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
+index 19bd616d67f6..ee5612441e25 100644
+--- a/gcc/config/xtensa/xtensa.c
++++ b/gcc/config/xtensa/xtensa.c
+@@ -2862,7 +2862,8 @@ xtensa_expand_prologue (void)
+ 			    gen_rtx_SET (mem, reg));
+ 	    }
+ 	}
+-      if (total_size > 1024)
++      if (total_size > 1024
++	  || (!callee_save_size && total_size > 128))
+ 	{
+ 	  rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
+ 	  emit_move_insn (tmp_reg, GEN_INT (total_size -
+-- 
+2.11.0
+

+ 49 - 0
toolchain/gcc/patches/8.3.0/0002-xtensa-fix-PR-target-91880.patch

@@ -0,0 +1,49 @@
+From 7c11710230921246156aecc20eb4b6ccaeaaa473 Mon Sep 17 00:00:00 2001
+From: Max Filippov <jcmvbkbc@gmail.com>
+Date: Tue, 24 Sep 2019 04:15:17 -0700
+Subject: [PATCH] xtensa: fix PR target/91880
+
+Xtensa hwloop_optimize segfaults when zero overhead loop is about to be
+inserted as the first instruction of the function.
+Insert zero overhead loop instruction into new basic block before the
+loop when basic block that precedes the loop is empty.
+
+2019-09-26  Max Filippov  <jcmvbkbc@gmail.com>
+gcc/
+	* config/xtensa/xtensa.c (hwloop_optimize): Insert zero overhead
+	loop instruction into new basic block before the loop when basic
+	block that precedes the loop is empty.
+
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
+---
+Backported from: r276166
+
+ gcc/config/xtensa/xtensa.c                 |  5 ++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
+index ee5612441e25..2527468d57db 100644
+--- a/gcc/config/xtensa/xtensa.c
++++ b/gcc/config/xtensa/xtensa.c
+@@ -4232,7 +4232,9 @@ hwloop_optimize (hwloop_info loop)
+ 
+   seq = get_insns ();
+ 
+-  if (!single_succ_p (entry_bb) || vec_safe_length (loop->incoming) > 1)
++  entry_after = BB_END (entry_bb);
++  if (!single_succ_p (entry_bb) || vec_safe_length (loop->incoming) > 1
++      || !entry_after)
+     {
+       basic_block new_bb;
+       edge e;
+@@ -4253,7 +4255,6 @@ hwloop_optimize (hwloop_info loop)
+     }
+   else
+     {
+-      entry_after = BB_END (entry_bb);
+       while (DEBUG_INSN_P (entry_after)
+              || (NOTE_P (entry_after)
+ 		 && NOTE_KIND (entry_after) != NOTE_INSN_BASIC_BLOCK))
+-- 
+2.11.0
+