From patchwork Fri Nov 11 10:38:31 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Maciej W. Rozycki" X-Patchwork-Id: 693629 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3tFbxp1RFDz9t1L for ; Fri, 11 Nov 2016 21:39:10 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="AZIP8sEv"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:in-reply-to:message-id:references :mime-version:content-type; q=dns; s=default; b=qEcQ/zoqSZE2Llk9 2mjbsIIE9vk8LrDDnCQonOeEf+/ffkamfDpJAgsaD98jCLLLi61te6QUUgh/LuLi QN7cLHNu//KV/Smn56IJeVXtlOYr4DaBKtQeqfzidkR1qHbGtVuJe3JArreuWSiI j1tLYYaayoJQYnyP+69pCGjS8yo= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:in-reply-to:message-id:references :mime-version:content-type; s=default; bh=x1GRiLOLvsD8OAhssgyNE5 xZUWU=; b=AZIP8sEvsG352VmATilzyJIAw3s+u2j0CNwGl4majh2pAqsGr3pPXC MbrRdRAoru+iGuKCktBvoNw4yuPqhN6LiNt9llI63u1co6fJApK3f85byKBG53/M 3/fr5Gs+Bj3Sr5GbxJJXeBPsT/vbfqXCEch73/2PGwaSc5s/rJHXs= Received: (qmail 83882 invoked by alias); 11 Nov 2016 10:38:59 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 83866 invoked by uid 89); 11 Nov 2016 10:38:57 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.8 required=5.0 tests=AWL, BAYES_00, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy=Feb, feb, 1, 98, set_attr X-HELO: mailapp01.imgtec.com Received: from mailapp01.imgtec.com (HELO mailapp01.imgtec.com) (195.59.15.196) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 11 Nov 2016 10:38:47 +0000 Received: from HHMAIL01.hh.imgtec.org (unknown [10.100.10.19]) by Forcepoint Email with ESMTPS id 667C6E5CED2E9; Fri, 11 Nov 2016 10:38:40 +0000 (GMT) Received: from [10.20.78.79] (10.20.78.79) by HHMAIL01.hh.imgtec.org (10.100.10.21) with Microsoft SMTP Server id 14.3.294.0; Fri, 11 Nov 2016 10:38:40 +0000 Date: Fri, 11 Nov 2016 10:38:31 +0000 From: "Maciej W. Rozycki" To: CC: Matthew Fortune , Catherine Moore Subject: [PATCH 3/3] MIPS/GCC: Mark trailing labels with `.insn' In-Reply-To: Message-ID: References: User-Agent: Alpine 2.20.17 (DEB 179 2016-10-28) MIME-Version: 1.0 Mark trailing labels, either at the end of a function or preceding a MIPS16 constant pool, with the `.insn' assembly pseudo-op so that they are considered code rather than data labels and consequently have ISA annotation added in the symbol table by the assembler. Such labels are created for some cases of unreachable code like with the following example: $ cat switch.c int foo (int i) { static int j; j += i; switch (i) { case -5: return -2; case -3: return -1; case 0: return 0; case 3: return 1; case 5: break; default: __builtin_unreachable (); } return j; } $ gcc -S -mips16 -O2 -o switch-mips16.s switch.c $ cat switch-mips16.s .file 1 "switch.c" .section .mdebug.abi32 .previous .nan legacy .module fp=xx .module nooddspreg .abicalls .option pic0 .text .align 2 .globl foo .set mips16 .set nomicromips .ent foo .type foo, @function foo: .frame $sp,0,$31 # vars= 0, regs= 0/0, args= 0, gp= 0 .mask 0x00000000,0 .fmask 0x00000000,0 lw $3,$L11 lw $2,0($3) addu $2,$4,$2 sw $2,0($3) addiu $3,$4,5 sltu $3, 11 bteqz $L2 sll $5, $3, 1 la $3, $L4 addu $5, $3, $5 lh $5, 0($5) addu $3, $3, $5 j $3 .align 1 .align 2 $L4: .half $L9-$L4 .half $L2-$L4 .half $L5-$L4 .half $L2-$L4 .half $L2-$L4 .half $L6-$L4 .half $L2-$L4 .half $L2-$L4 .half $L7-$L4 .half $L2-$L4 .half $L1-$L4 $L9: li $2,2 neg $2,$2 $L1: jr $31 $L7: .set noreorder .set nomacro jr $31 li $2,1 .set macro .set reorder $L6: .set noreorder .set nomacro jr $31 move $2,$4 .set macro .set reorder $L5: li $2,1 .set noreorder .set nomacro jr $31 neg $2,$2 .set macro .set reorder $L2: .align 2 $L11: .word j.1474 .end foo .size foo, .-foo .local j.1474 .comm j.1474,4,4 .ident "GCC: (GNU) 7.0.0 20160810 (experimental)" $ where `$L2' is placed before MIPS16 constant pool data, or: $ gcc -S -mmicromips -O2 -o switch-micromips.s switch.c $ cat switch-micromips.s .file 1 "switch.c" .section .mdebug.abi32 .previous .nan legacy .module fp=xx .module nooddspreg .abicalls .option pic0 .text .align 2 .globl foo .set nomips16 .set micromips .ent foo .type foo, @function foo: .frame $sp,0,$31 # vars= 0, regs= 0/0, args= 0, gp= 0 .mask 0x00000000,0 .fmask 0x00000000,0 .set noreorder .set nomacro lui $5,%hi(j.1401) addiu $3,$4,5 lw $2,%lo(j.1401)($5) sltu $6,$3,11 addu $2,$4,$2 beqz $6,$L2 sw $2,%lo(j.1401)($5) lui $5,%hi($L4) addiu $5,$5,%lo($L4) lwxs $3,$3($5) jrc $3 .rdata .align 2 .align 2 $L4: .word $L9 .word $L2 .word $L5 .word $L2 .word $L2 .word $L6 .word $L2 .word $L2 .word $L7 .word $L2 .word $L1 .text $L9: li $2,-2 # 0xfffffffffffffffe $L1: jrc $31 $L7: jr $31 li $2,1 # 0x1 $L6: jr $31 move $2,$4 $L5: jr $31 li $2,-1 # 0xffffffffffffffff $L2: .set macro .set reorder .end foo .size foo, .-foo .local j.1401 .comm j.1401,4,4 .ident "GCC: (GNU) 7.0.0 20160810 (experimental)" where the same label is placed at the end of a function. This in turn makes recent trunk versions of gas complain: $ as -o switch-mips16.o switch-mips16.s switch-mips16.s: Assembler messages: switch-mips16.s:26: Error: branch to a symbol in another ISA mode $ as commit 9d862524f6ae ("MIPS: Verify the ISA mode and alignment of branch and jump targets") closed a hole in branch processing, making relocation calculation respect the ISA mode of the symbol referred. This allowed diagnosing the situation where an attempt is made to pass control from code assembled for one ISA mode to code assembled for a different ISA mode and either relaxing the branch to a cross-mode jump or if that is not possible, then reporting this as an error rather than letting such code build and then fail unpredictably at the run time. This however requires the correct annotation of branch targets as code, because the ISA mode is not relevant for data symbols and is therefore not recorded for them. The `.insn' pseudo-op is used for this purpose and has been supported by GAS since: Wed Feb 12 14:36:29 1997 Ian Lance Taylor * config/tc-mips.c (mips_pseudo_table): Add "insn". (s_insn): New static function. * doc/c-mips.texi: Document .insn. so there has been no reason to avoid it where required. More recently this pseudo-op has been documented, by the microMIPS architecture specification[1][2], as required for the correct interpretation of any code label which is not followed by an actual instruction in an assembly source. Let it be produced then, making it appear in output generated right after `$L2' definitions above and thus fixing the assembly. Use the `mach2' pass, after all the MIPS16 constant pools have been fixed, to scan the insn stream backwards, identifying any labels still present at the end of a function or immediately preceding a MIPS16 constant pool, using dummy `consttable' insns previously inserted to identify the beginning of each such constant pool. Insert the `insn_pseudo' insn immediately after these labels, which emits the `.insn' pseudo-op. References: [1] "MIPS Architecture for Programmers, Volume II-B: The microMIPS32 Instruction Set", MIPS Technologies, Inc., Document Number: MD00582, Revision 5.04, January 15, 2014, Section 7.1 "Assembly-Level Compatibility", p. 533 [2] "MIPS Architecture for Programmers, Volume II-B: The microMIPS64 Instruction Set", MIPS Technologies, Inc., Document Number: MD00594, Revision 5.04, January 15, 2014, Section 8.1 "Assembly-Level Compatibility", p. 623 gcc/ * config/mips/mips.c (mips16_emit_constants): Emit `consttable' insn at the beginning of the constant pool. (mips_insert_insn_pseudos): New function. (mips_machine_reorg2): Call it. * config/mips/mips.md (unspec): Add UNSPEC_CONSTTABLE and UNSPEC_INSN_PSEUDO enum values. (insn_pseudo, consttable): New insns. gcc/testsuite/ * gcc.target/mips/insn-casesi.c: New test case. * gcc.target/mips/insn-pseudo-1.c: New test case. * gcc.target/mips/insn-pseudo-2.c: New test case. * gcc.target/mips/insn-pseudo-3.c: New test case. * gcc.target/mips/insn-pseudo-4.c: New test case. * gcc.target/mips/insn-tablejump.c: New test case. --- I have successfully regression-tested it with the `mips-mti-linux-gnu' target, with a big-endian o32 regular MIPS multilib and a little-endian o32 MIPS16 multilib, with no regressions, except as noted below. I did some big-endian n64 regular MIPS and little-endian o32 microMIPS testing, including with the new cases, and things looked good, except as noted below. I also generated assembly manually (for the assembly-match cases) and examined output visually, including all the four above multilibs, and also -fPIC and -mno-abicalls variants, which I have no immediate way of testing automatically. With n64 (`-mabi=n64') testing none of the test cases under gcc.target/mips/ were run and the test harness broke as follows: ERROR: (DejaGnu) proc "cc1: error: '-mfpxx' can only be used with the o32 ABI" does not exist. The error code is NONE The info on the error is: invalid command name "cc1:" while executing "::tcl_unknown cc1: error: '-mfpxx' can only be used with the o32 ABI" ("uplevel" body line 1) invoked from within "uplevel 1 ::tcl_unknown $args" I take it as a bug in the harness, which ought to be looked into separately, and not a problem with this change. With MIPS16 (`-mips16') and microMIPS (`-mmicromips') testing the test cases failed to compile as follows, respectively: spawn -ignore SIGHUP .../gcc/gcc/xgcc -B.../gcc/gcc/ .../gcc/testsuite/gcc.target/mips/insn-tablejump.c -fno-diagnostics-show-caret -fdiagnostics-color=never --sysroot=.../sysroot -O0 -DNOMIPS16=__attribute__((nomips16)) -DNOMICROMIPS=__attribute__((nomicromips)) -DNOCOMPRESSION=__attribute__((nocompression)) -mmicromips -mno-mips16 -DMICROMIPS=__attribute__((micromips)) -EL -mips16 -Wl,-dynamic-linker,.../sysroot/mipsel-r2-mips16-hard/lib/ld.so.1 -Wl,-rpath,.../sysroot/mipsel-r2-mips16-hard/lib -Wl,-rpath,.../sysroot/mipsel-r2-mips16-hard/usr/lib -lm -o insn-tablejump.exe cc1: error: unsupported combination: -mips16 -mmicromips compiler exited with status 1 output is: cc1: error: unsupported combination: -mips16 -mmicromips FAIL: gcc.target/mips/insn-tablejump.c -O0 (test for excess errors) Excess errors: cc1: error: unsupported combination: -mips16 -mmicromips and: spawn -ignore SIGHUP .../gcc/gcc/xgcc -B.../gcc/gcc/ .../gcc/testsuite/gcc.target/mips/insn-casesi.c -fno-diagnostics-show-caret -fdiagnostics-color=never --sysroot=.../sysroot -O0 -DNOMIPS16=__attribute__((nomips16)) -DNOMICROMIPS=__attribute__((nomicromips)) -DNOCOMPRESSION=__attribute__((nocompression)) -mno-micromips -mips16 -mcode-readable=yes -DMIPS16=__attribute__((mips16)) -EL -mmicromips-Wl,-dynamic-linker,.../sysroot/micromipsel-r2-hard/lib/ld.so.1 -Wl,-rpath,.../sysroot/micromipsel-r2-hard/lib -Wl,-rpath,.../sysroot/micromipsel-r2-hard/usr/lib -lm -o insn-casesi.exe cc1: error: unsupported combination: -mips16 -mmicromips compiler exited with status 1 output is: cc1: error: unsupported combination: -mips16 -mmicromips FAIL: gcc.target/mips/insn-casesi.c -O0 (test for excess errors) Excess errors: cc1: error: unsupported combination: -mips16 -mmicromips Again, I take it as a bug in the harness, which places the required overrides specified and implied by `dg-options' before board compilation flags rather than afterwards. As such it's a separate problem which has nothing to do with this change and needs to be fixed independently. OK to apply? Maciej gcc-mips-label-insn.diff Index: gcc/gcc/config/mips/mips.c =================================================================== --- gcc.orig/gcc/config/mips/mips.c 2016-11-09 15:04:00.793911910 +0000 +++ gcc/gcc/config/mips/mips.c 2016-11-09 15:04:20.254759246 +0000 @@ -17133,6 +17133,8 @@ mips16_emit_constants (struct mips16_con int align; align = 0; + if (constants) + insn = emit_insn_after (gen_consttable (), insn); for (c = constants; c != NULL; c = next) { /* If necessary, increase the alignment of PC. */ @@ -19008,6 +19010,46 @@ mips16_split_long_branches (void) while (something_changed); } +/* Insert a `.insn' assembly pseudo-op after any labels followed by + a MIPS16 constant pool or no insn at all. This is needed so that + targets that have been optimised away are still marked as code + and therefore branches that remained and point to them are known + to retain the ISA mode and as such can be successfully assembled. */ + +static void +mips_insert_insn_pseudos (void) +{ + bool insn_pseudo_needed = TRUE; + rtx_insn *insn; + + for (insn = get_last_insn (); insn != NULL_RTX; insn = PREV_INSN (insn)) + switch (GET_CODE (insn)) + { + case INSN: + if (GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE + && XINT (PATTERN (insn), 1) == UNSPEC_CONSTTABLE) + { + insn_pseudo_needed = TRUE; + break; + } + /* Fall through. */ + case JUMP_INSN: + case CALL_INSN: + case JUMP_TABLE_DATA: + insn_pseudo_needed = FALSE; + break; + case CODE_LABEL: + if (insn_pseudo_needed) + { + emit_insn_after (gen_insn_pseudo (), insn); + insn_pseudo_needed = FALSE; + } + break; + default: + break; + } +} + /* Implement TARGET_MACHINE_DEPENDENT_REORG. */ static void @@ -19043,6 +19085,7 @@ mips_machine_reorg2 (void) optimizations, but this should be an extremely rare case anyhow. */ mips_reorg_process_insns (); mips16_split_long_branches (); + mips_insert_insn_pseudos (); return 0; } Index: gcc/gcc/config/mips/mips.md =================================================================== --- gcc.orig/gcc/config/mips/mips.md 2016-11-09 15:04:00.802108728 +0000 +++ gcc/gcc/config/mips/mips.md 2016-11-09 15:04:20.271031267 +0000 @@ -120,6 +120,7 @@ ;; MIPS16 constant pools. UNSPEC_ALIGN + UNSPEC_CONSTTABLE UNSPEC_CONSTTABLE_INT UNSPEC_CONSTTABLE_FLOAT @@ -151,6 +152,9 @@ ;; Stack checking. UNSPEC_PROBE_STACK_RANGE + + ;; The `.insn' pseudo-op. + UNSPEC_INSN_PSEUDO ]) (define_constants @@ -7174,6 +7178,14 @@ return "#nop"; } [(set_attr "type" "nop")]) + +;; The `.insn' pseudo-op. +(define_insn "insn_pseudo" + [(unspec_volatile [(const_int 0)] UNSPEC_INSN_PSEUDO)] + "" + ".insn" + [(set_attr "mode" "none") + (set_attr "insn_count" "0")]) ;; MIPS4 Conditional move instructions. @@ -7308,6 +7320,13 @@ ;; .................... ;; +(define_insn "consttable" + [(unspec_volatile [(const_int 0)] UNSPEC_CONSTTABLE)] + "" + "" + [(set_attr "mode" "none") + (set_attr "insn_count" "0")]) + (define_insn "consttable_tls_reloc" [(unspec_volatile [(match_operand 0 "tls_reloc_operand" "") (match_operand 1 "const_int_operand" "")] Index: gcc/gcc/testsuite/gcc.target/mips/insn-casesi.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc/gcc/testsuite/gcc.target/mips/insn-casesi.c 2016-11-09 18:55:39.856029933 +0000 @@ -0,0 +1,112 @@ +/* { dg-do run } */ +/* { dg-options "-mips16 -mcode-readable=yes" } */ + +int __attribute__ ((noinline)) +frob (int i) +{ + switch (i) + { + case -5: + return -2; + case -3: + return -1; + case 0: + return 0; + case 3: + return 1; + case 5: + break; + default: + __builtin_unreachable (); + } + return i; +} + +int +main (int argc, char **argv) +{ + asm ("" : "+r" (argc)); + argc = frob ((argc & 10) - 5); + asm ("" : "+r" (argc)); + return !argc; +} + +/* This will result in assembly like: + + .text + .align 2 + .globl frob + .set mips16 + .set nomicromips + .ent frob + .type frob, @function +frob: + .frame $sp,0,$31 # vars= 0, regs= 0/0, args= 0, gp= 0 + .mask 0x00000000,0 + .fmask 0x00000000,0 + addiu $2,$4,5 + sltu $2,11 + bteqz $L2 + sll $3,$2,1 + la $2,$L4 + addu $3,$2,$3 + lh $3,0($3) + addu $2,$2,$3 + j $2 + .align 1 + .align 2 +$L4: + .half $L3-$L4 + .half $L2-$L4 + .half $L9-$L4 + .half $L2-$L4 + .half $L2-$L4 + .half $L8-$L4 + .half $L2-$L4 + .half $L2-$L4 + .half $L7-$L4 + .half $L2-$L4 + .half $L8-$L4 +$L8: + .set noreorder + .set nomacro + jr $31 + move $2,$4 + .set macro + .set reorder + +$L9: + li $2,1 + .set noreorder + .set nomacro + jr $31 + neg $2,$2 + .set macro + .set reorder + +$L3: + li $2,2 + .set noreorder + .set nomacro + jr $31 + neg $2,$2 + .set macro + .set reorder + +$L7: + .set noreorder + .set nomacro + jr $31 + li $2,1 + .set macro + .set reorder + +$L2: + .insn + .end frob + .size frob, .-frob + + for `frob' and we want to make sure it links correctly owing to the + `.insn' pseudo-op which needs to be there at `$L2' as there's no + code following and the label is a MIPS16 branch target (even though + the branch is never taken. See also insn-tablejump.c. */ Index: gcc/gcc/testsuite/gcc.target/mips/insn-pseudo-1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc/gcc/testsuite/gcc.target/mips/insn-pseudo-1.c 2016-11-09 18:55:39.866624599 +0000 @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-mno-micromips -mno-mips16" } */ + +void +unreachable (int i) +{ + asm volatile goto ("b\t.\n\tbeqz\t%0,%l1" : : "r" (i) : : punt); +punt: + __builtin_unreachable (); +} + +/* Expect assembly like: + + beqz $4,$L2 + # Anything goes here. +$L2: # The label must match. + .insn +$L3 = . # It's there, but we don't care. + .end unreachable + + that is .insn to be inserted if a code label is at function's end. */ + +/* { dg-final { scan-assembler "\tbeqz\t\\\$\[0-9\]+,(.L\[0-9\]+)\n.*\n\\1:\n\t\\.insn\n(?:.L\[0-9\]+ = \\.\n)?\t\\.end\tunreachable\n" } } */ Index: gcc/gcc/testsuite/gcc.target/mips/insn-pseudo-2.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc/gcc/testsuite/gcc.target/mips/insn-pseudo-2.c 2016-11-09 18:55:39.876167216 +0000 @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-mmicromips" } */ + +void +unreachable (int i) +{ + asm volatile goto ("b\t.\n\tbeqz\t%0,%l1" : : "r" (i) : : punt); +punt: + __builtin_unreachable (); +} + +/* Expect assembly like: + + beqz $4,$L2 + # Anything goes here. +$L2: # The label must match. + .insn +$L3 = . # It's there, but we don't care. + .end unreachable + + that is .insn to be inserted if a code label is at function's end. */ + +/* { dg-final { scan-assembler "\tbeqz\t\\\$\[0-9\]+,(.L\[0-9\]+)\n.*\n\\1:\n\t\\.insn\n(?:.L\[0-9\]+ = \\.\n)?\t\\.end\tunreachable\n" } } */ Index: gcc/gcc/testsuite/gcc.target/mips/insn-pseudo-3.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc/gcc/testsuite/gcc.target/mips/insn-pseudo-3.c 2016-11-09 18:55:39.892706789 +0000 @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-mips16" } */ + +void +unreachable (int i) +{ + asm volatile goto ("b\t.\n\tbeqz\t%0,%l1" : : "r" (i) : : punt); +punt: + __builtin_unreachable (); +} + +/* Expect assembly like: + + beqz $4,$L2 + # Anything goes here. +$L2: # The label must match. + .insn +$L3 = . # It's there, but we don't care. + .end unreachable + + that is .insn to be inserted if a code label is at function's end. */ + +/* { dg-final { scan-assembler "\tbeqz\t\\\$\[0-9\]+,(.L\[0-9\]+)\n.*\n\\1:\n\t\\.insn\n(?:.L\[0-9\]+ = \\.\n)?\t\\.end\tunreachable\n" } } */ Index: gcc/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c 2016-11-09 18:55:39.933208494 +0000 @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-mips16 -mcode-readable=yes" } */ + +void +unreachable (void) +{ + asm volatile goto ("b\t.\n\tbeqz\t%0,%l1" : : "r" (0x12345678) : : punt); +punt: + __builtin_unreachable (); +} + +/* Expect assembly like: + + lw $2,$L5 + # Anything goes here. + beqz $2,$L2 # The register must match. + # Anything goes here. +$L2: # The label must match. + .insn +$L3 = . # It's there, but we don't care. + .align 2 +$L5: # The label must match. + .word 305419896 + + that is .insn to be inserted if a code label is at a constant pool. */ + +/* { dg-final { scan-assembler "\tlw\t(\\\$\[0-9\]+),(.L\[0-9\]+)\n.*\tbeqz\t\\1,(.L\[0-9\]+)\n.*\n\\3:\n\t\\.insn\n(?:.L\[0-9\]+ = \\.\n)?\t\\.align\t2\n\\2:\n\t\\.word\t305419896\n" } } */ Index: gcc/gcc/testsuite/gcc.target/mips/insn-tablejump.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc/gcc/testsuite/gcc.target/mips/insn-tablejump.c 2016-11-09 18:55:39.954800846 +0000 @@ -0,0 +1,98 @@ +/* { dg-do run } */ +/* { dg-options "-mmicromips" } */ + +int __attribute__ ((noinline)) +frob (int i) +{ + switch (i) + { + case -5: + return -2; + case -3: + return -1; + case 0: + return 0; + case 3: + return 1; + case 5: + break; + default: + __builtin_unreachable (); + } + return i; +} + +int +main (int argc, char **argv) +{ + asm ("" : "+r" (argc)); + argc = frob ((argc & 10) - 5); + asm ("" : "+r" (argc)); + return !argc; +} + +/* This will result in assembly like: + + .text + .align 2 + .globl frob + .set nomips16 + .set micromips + .ent frob + .type frob, @function +frob: + .frame $sp,0,$31 # vars= 0, regs= 0/0, args= 0, gp= 0 + .mask 0x00000000,0 + .fmask 0x00000000,0 + .set noreorder + .set nomacro + addiu $3,$4,5 + sltu $2,$3,11 + beqzc $2,$L2 + lui $2,%hi($L4) + addiu $2,$2,%lo($L4) + lwxs $3,$3($2) + jrc $3 + .rdata + .align 2 + .align 2 +$L4: + .word $L3 + .word $L2 + .word $L9 + .word $L2 + .word $L2 + .word $L8 + .word $L2 + .word $L2 + .word $L7 + .word $L2 + .word $L8 + .text +$L8: + jr $31 + move $2,$4 + +$L9: + jr $31 + li $2,-1 # 0xffffffffffffffff + +$L3: + jr $31 + li $2,-2 # 0xfffffffffffffffe + +$L7: + jr $31 + li $2,1 # 0x1 + +$L2: + .insn + .set macro + .set reorder + .end frob + .size frob, .-frob + + for `frob' and we want to make sure it links correctly owing to the + `.insn' pseudo-op which needs to be there at `$L2' as there's no + code following and the label is a microMIPS branch target (even though + the branch is never taken. See also insn-casesi.c. */