From patchwork Mon Jan 15 23:09:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bill Schmidt X-Patchwork-Id: 861108 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-471313-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="GC+hNoXZ"; dkim-atps=neutral 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 3zL8F24ZMtz9sCZ for ; Tue, 16 Jan 2018 10:09:25 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:date:mime-version:content-type :content-transfer-encoding:message-id; q=dns; s=default; b=VvqJ+ NMgkVviqKx/FQIQhCegMmzeyu1+q5t0c0n7f/wInZefg7rKCYUBD3TIhhDAGZmj1 FkDQXZcDzYY5STLwXGyaNFK8rawUAQAEXKWrZsgpX1h2ypsIfhLkyDUTcok3jDOP +cHZfdZxKI1F7riGHslAT4NgY5NAviNmUM55P4= 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:to:cc :from:subject:date:mime-version:content-type :content-transfer-encoding:message-id; s=default; bh=4usgrswu1ZS +AThYLbRj8HEz2cY=; b=GC+hNoXZ1GU4xv/xRaoq966QDmKf0cJFT/C1kY4gCfk EyKcjQ9bNOS9w94NL1cyC3RVC6iq6BAhQcl3ua3ahBHDX1cewMfKTs4lUmY/aoPi ughTgEHb0zhl1v7UdkNFDn9K5c4wIUf7q6uYAhEAV2QL0cSAX0FT3oDuMQhlRq54 = Received: (qmail 77148 invoked by alias); 15 Jan 2018 23:09:17 -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 77136 invoked by uid 89); 15 Jan 2018 23:09:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-10.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY, KAM_SHORT, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy= X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0b-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.158.5) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 15 Jan 2018 23:09:14 +0000 Received: from pps.filterd (m0098414.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w0FN97qX029185 for ; Mon, 15 Jan 2018 18:09:12 -0500 Received: from e37.co.us.ibm.com (e37.co.us.ibm.com [32.97.110.158]) by mx0b-001b2d01.pphosted.com with ESMTP id 2fh0cf4ku9-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 15 Jan 2018 18:09:11 -0500 Received: from localhost by e37.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 15 Jan 2018 16:09:10 -0700 Received: from b03cxnp08027.gho.boulder.ibm.com (9.17.130.19) by e37.co.us.ibm.com (192.168.1.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 15 Jan 2018 16:09:07 -0700 Received: from b03ledav006.gho.boulder.ibm.com (b03ledav006.gho.boulder.ibm.com [9.17.130.237]) by b03cxnp08027.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w0FN97N38520114; Mon, 15 Jan 2018 16:09:07 -0700 Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1F564C603E; Mon, 15 Jan 2018 16:09:07 -0700 (MST) Received: from bigmac.rchland.ibm.com (unknown [9.10.86.45]) by b03ledav006.gho.boulder.ibm.com (Postfix) with ESMTP id BF4C8C6037; Mon, 15 Jan 2018 16:09:06 -0700 (MST) To: GCC Patches Cc: Segher Boessenkool , David Edelsohn From: Bill Schmidt Subject: [PATCH v3, rs6000] Add -mspeculate-indirect-jumps option and implement non-speculating bctr / bctrl Date: Mon, 15 Jan 2018 17:09:06 -0600 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:52.0) Gecko/20100101 Thunderbird/52.5.2 MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 18011523-0024-0000-0000-000017CB8912 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008385; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000245; SDB=6.00975568; UDB=6.00494463; IPR=6.00755495; BA=6.00005778; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00019057; XFM=3.00000015; UTC=2018-01-15 23:09:08 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18011523-0025-0000-0000-00004E4F14D8 Message-Id: X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-01-15_09:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1801150324 X-IsSubscribed: yes Hi, This patch supercedes v2: https://gcc.gnu.org/ml/gcc-patches/2018-01/msg01204.html, and fixes the problems noted in its review. It also adds the test cases from https://gcc.gnu.org/ml/gcc-patches/2018-01/msg01261.html and adjusts them according to the results of the review. There is more function to be provided in a future patch: Sibling calls for all ABIs, and indirect calls for non-ELFv2 ABIs. I'm getting close on that, but I think it's better to keep that separate at this point. Bootstrapped and tested on powerpc64-linux-gnu and powerpc64le-linux-gnu with no regressions. Is this okay for trunk? Thanks, Bill [gcc] 2018-01-15 Bill Schmidt * config/rs6000/rs6000.c (rs6000_opt_vars): Add entry for -mspeculate-indirect-jumps. * config/rs6000/rs6000.md (*call_indirect_elfv2): Disable for -mno-speculate-indirect-jumps. (*call_indirect_elfv2_nospec): New define_insn. (*call_value_indirect_elfv2): Disable for -mno-speculate-indirect-jumps. (*call_value_indirect_elfv2_nospec): New define_insn. (indirect_jump): Emit different RTL for -mno-speculate-indirect-jumps. (*indirect_jump): Disable for -mno-speculate-indirect-jumps. (*indirect_jump_nospec): New define_insn. (tablejump): Emit different RTL for -mno-speculate-indirect-jumps. (tablejumpsi): Disable for -mno-speculate-indirect-jumps. (tablejumpsi_nospec): New define_expand. (tablejumpdi): Disable for -mno-speculate-indirect-jumps. (tablejumpdi_nospec): New define_expand. (*tablejump_internal1): Disable for -mno-speculate-indirect-jumps. (*tablejump_internal1_nospec): New define_insn. * config/rs6000/rs6000.opt (mspeculate-indirect-jumps): New option. [gcc/testsuite] 2018-01-15 Bill Schmidt * gcc.target/powerpc/safe-indirect-jump-1.c: New file. * gcc.target/powerpc/safe-indirect-jump-2.c: New file. * gcc.target/powerpc/safe-indirect-jump-3.c: New file. * gcc.target/powerpc/safe-indirect-jump-4.c: New file. * gcc.target/powerpc/safe-indirect-jump-5.c: New file. * gcc.target/powerpc/safe-indirect-jump-6.c: New file. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 256364) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -36726,6 +36726,9 @@ static struct rs6000_opt_var const rs6000_opt_vars { "sched-epilog", offsetof (struct gcc_options, x_TARGET_SCHED_PROLOG), offsetof (struct cl_target_option, x_TARGET_SCHED_PROLOG), }, + { "speculate-indirect-jumps", + offsetof (struct gcc_options, x_rs6000_speculate_indirect_jumps), + offsetof (struct cl_target_option, x_rs6000_speculate_indirect_jumps), }, }; /* Inner function to handle attribute((target("..."))) and #pragma GCC target Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 256364) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -11222,11 +11222,22 @@ (match_operand 1 "" "g,g")) (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_ELFv2" + "DEFAULT_ABI == ABI_ELFv2 && rs6000_speculate_indirect_jumps" "b%T0l\; 2,%2(1)" [(set_attr "type" "jmpreg") (set_attr "length" "8")]) +;; Variant with deliberate misprediction. +(define_insn "*call_indirect_elfv2_nospec" + [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l")) + (match_operand 1 "" "g,g")) + (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_ELFv2 && !rs6000_speculate_indirect_jumps" + "crset eq\;beq%T0l-\; 2,%2(1)" + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) + (define_insn "*call_value_indirect_elfv2" [(set (match_operand 0 "" "") (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) @@ -11233,11 +11244,22 @@ (match_operand 2 "" "g,g"))) (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_ELFv2" + "DEFAULT_ABI == ABI_ELFv2 && rs6000_speculate_indirect_jumps" "b%T1l\; 2,%3(1)" [(set_attr "type" "jmpreg") (set_attr "length" "8")]) +; Variant with deliberate misprediction. +(define_insn "*call_value_indirect_elfv2_nospec" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) + (match_operand 2 "" "g,g"))) + (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_ELFv2 && !rs6000_speculate_indirect_jumps" + "crset eq\;beq%T1l-\; 2,%3(1)" + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) ;; Call subroutine returning any type. (define_expand "untyped_call" @@ -12917,15 +12939,34 @@ [(set_attr "type" "jmpreg")]) (define_expand "indirect_jump" - [(set (pc) (match_operand 0 "register_operand"))]) + [(set (pc) (match_operand 0 "register_operand"))] + "" +{ + if (!rs6000_speculate_indirect_jumps) { + rtx ccreg = gen_reg_rtx (CCmode); + if (Pmode == DImode) + emit_jump_insn (gen_indirect_jumpdi_nospec (operands[0], ccreg)); + else + emit_jump_insn (gen_indirect_jumpsi_nospec (operands[0], ccreg)); + DONE; + } +}) (define_insn "*indirect_jump" [(set (pc) (match_operand:P 0 "register_operand" "c,*l"))] - "" + "rs6000_speculate_indirect_jumps" "b%T0" [(set_attr "type" "jmpreg")]) +(define_insn "indirect_jump_nospec" + [(set (pc) (match_operand:P 0 "register_operand" "c,*l")) + (clobber (match_operand:CC 1 "cc_reg_operand" "=y,y"))] + "!rs6000_speculate_indirect_jumps" + "crset %E1\;beq%T0- %1\;b ." + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) + ;; Table jump for switch statements: (define_expand "tablejump" [(use (match_operand 0)) @@ -12933,9 +12974,27 @@ "" { if (TARGET_32BIT) - emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); + { + if (rs6000_speculate_indirect_jumps) + emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); + else + { + rtx ccreg = gen_reg_rtx (CCmode); + rtx jump = gen_tablejumpsi_nospec (operands[0], operands[1], ccreg); + emit_jump_insn (jump); + } + } else - emit_jump_insn (gen_tablejumpdi (operands[0], operands[1])); + { + if (rs6000_speculate_indirect_jumps) + emit_jump_insn (gen_tablejumpdi (operands[0], operands[1])); + else + { + rtx ccreg = gen_reg_rtx (CCmode); + rtx jump = gen_tablejumpdi_nospec (operands[0], operands[1], ccreg); + emit_jump_insn (jump); + } + } DONE; }) @@ -12946,7 +13005,7 @@ (parallel [(set (pc) (match_dup 3)) (use (label_ref (match_operand 1)))])] - "TARGET_32BIT" + "TARGET_32BIT && rs6000_speculate_indirect_jumps" { operands[0] = force_reg (SImode, operands[0]); operands[2] = force_reg (SImode, gen_rtx_LABEL_REF (SImode, operands[1])); @@ -12953,6 +13012,21 @@ operands[3] = gen_reg_rtx (SImode); }) +(define_expand "tablejumpsi_nospec" + [(set (match_dup 4) + (plus:SI (match_operand:SI 0) + (match_dup 3))) + (parallel [(set (pc) + (match_dup 4)) + (use (label_ref (match_operand 1))) + (clobber (match_operand 2))])] + "TARGET_32BIT && !rs6000_speculate_indirect_jumps" +{ + operands[0] = force_reg (SImode, operands[0]); + operands[3] = force_reg (SImode, gen_rtx_LABEL_REF (SImode, operands[1])); + operands[4] = gen_reg_rtx (SImode); +}) + (define_expand "tablejumpdi" [(set (match_dup 4) (sign_extend:DI (match_operand:SI 0 "lwa_operand"))) @@ -12962,7 +13036,7 @@ (parallel [(set (pc) (match_dup 3)) (use (label_ref (match_operand 1)))])] - "TARGET_64BIT" + "TARGET_64BIT && rs6000_speculate_indirect_jumps" { operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1])); operands[3] = gen_reg_rtx (DImode); @@ -12969,14 +13043,41 @@ operands[4] = gen_reg_rtx (DImode); }) +(define_expand "tablejumpdi_nospec" + [(set (match_dup 5) + (sign_extend:DI (match_operand:SI 0 "lwa_operand"))) + (set (match_dup 4) + (plus:DI (match_dup 5) + (match_dup 3))) + (parallel [(set (pc) + (match_dup 4)) + (use (label_ref (match_operand 1))) + (clobber (match_operand 2))])] + "TARGET_64BIT && !rs6000_speculate_indirect_jumps" +{ + operands[3] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1])); + operands[4] = gen_reg_rtx (DImode); + operands[5] = gen_reg_rtx (DImode); +}) + (define_insn "*tablejump_internal1" [(set (pc) (match_operand:P 0 "register_operand" "c,*l")) (use (label_ref (match_operand 1)))] - "" + "rs6000_speculate_indirect_jumps" "b%T0" [(set_attr "type" "jmpreg")]) +(define_insn "*tablejump_internal1_nospec" + [(set (pc) + (match_operand:P 0 "register_operand" "c,*l")) + (use (label_ref (match_operand 1))) + (clobber (match_operand:CC 2 "cc_reg_operand" "=y,y"))] + "!rs6000_speculate_indirect_jumps" + "crset %E2\;beq%T0- %2\;b ." + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) + (define_insn "nop" [(unspec [(const_int 0)] UNSPEC_NOP)] "" Index: gcc/config/rs6000/rs6000.opt =================================================================== --- gcc/config/rs6000/rs6000.opt (revision 256364) +++ gcc/config/rs6000/rs6000.opt (working copy) @@ -617,3 +617,8 @@ Use the given offset for addressing the stack-prot TargetVariable long rs6000_stack_protector_guard_offset = 0 + +;; -mno-speculate-indirect-jumps adds deliberate misprediction to indirect +;; branches via the CTR. +mspeculate-indirect-jumps +Target Undocumented Var(rs6000_speculate_indirect_jumps) Init(1) Save Index: gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c (working copy) @@ -0,0 +1,14 @@ +/* { dg-do compile { target { powerpc64le-*-* } } } */ +/* { dg-additional-options "-mno-speculate-indirect-jumps" } */ + +/* Test for deliberate misprediction of indirect calls for ELFv2. */ + +extern int (*f)(); + +int bar () +{ + return (*f) (); +} + +/* { dg-final { scan-assembler "crset eq" } } */ +/* { dg-final { scan-assembler "beqctrl-" } } */ Index: gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c (working copy) @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-mno-speculate-indirect-jumps" } */ + +/* Test for deliberate misprediction of computed goto. */ + +int bar (int); +int baz (int); +int spaz (int); + +int foo (int x) +{ + static void *labptr[] = { &&lab0, &&lab1, &&lab2 }; + + if (x < 0 || x > 2) + return -1; + + goto *labptr[x]; + + lab0: + return bar (x); + + lab1: + return baz (x) + 1; + + lab2: + return spaz (x) / 2; +} + +/* The following assumes CR7 as the first chosen volatile. */ + +/* { dg-final { scan-assembler "crset 30" } } */ +/* { dg-final { scan-assembler "beqctr- 7" } } */ +/* { dg-final { scan-assembler "b ." } } */ Index: gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c (working copy) @@ -0,0 +1,52 @@ +/* { dg-do compile } */ +/* { dg-options "-mno-speculate-indirect-jumps" } */ + +/* Test for deliberate misprediction of jump tables. */ + +void bar (void); + +int foo (int x) +{ + int a; + + switch (x) + { + default: + a = -1; + break; + case 0: + a = x * x; + break; + case 1: + a = x + 1; + break; + case 2: + a = x + x; + break; + case 3: + a = x << 3; + break; + case 4: + a = x >> 1; + break; + case 5: + a = x; + break; + case 6: + a = 0; + break; + case 7: + a = x * x + x; + break; + } + + bar(); + + return a; +} + +/* The following assumes CR7 as the first chosen volatile. */ + +/* { dg-final { scan-assembler "crset 30" } } */ +/* { dg-final { scan-assembler "beqctr- 7" } } */ +/* { dg-final { scan-assembler "b ." } } */ Index: gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-4.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-4.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-4.c (working copy) @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options "-mno-speculate-indirect-jumps" } */ + +/* Test for deliberate misprediction of indirect calls for ELFv2. */ + +int (*f)(); + +int __attribute__((noinline)) bar () +{ + return (*f) (); +} + +int g () +{ + return 26; +} + +int main () +{ + f = &g; + if (bar () != 26) + __builtin_abort (); + + return 0; +} Index: gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-5.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-5.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-5.c (working copy) @@ -0,0 +1,55 @@ +/* { dg-do run } */ +/* { dg-additional-options "-mno-speculate-indirect-jumps -Wno-pedantic" } */ + +/* Test for deliberate misprediction of computed goto. */ + +int __attribute__((noinline)) bar (int i) +{ + return 1960 + i; +} + +int __attribute__((noinline)) baz (int i) +{ + return i * i; +} + +int __attribute__((noinline)) spaz (int i) +{ + return i + 1; +} + +int foo (int x) +{ + static void *labptr[] = { &&lab0, &&lab1, &&lab2 }; + + if (x < 0 || x > 2) + return -1; + + goto *labptr[x]; + + lab0: + return bar (x); + + lab1: + return baz (x) + 1; + + lab2: + return spaz (x) / 2; +} + +int main () +{ + if (foo (0) != 1960) + __builtin_abort (); + + if (foo (1) != 2) + __builtin_abort (); + + if (foo (2) != 1) + __builtin_abort (); + + if (foo (3) != -1) + __builtin_abort (); + + return 0; +} Index: gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-6.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-6.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-6.c (working copy) @@ -0,0 +1,80 @@ +/* { dg-do run } */ +/* { dg-additional-options "-mno-speculate-indirect-jumps" } */ + +/* Test for deliberate misprediction of jump tables. */ + +void __attribute__((noinline)) bar () +{ +} + +int foo (int x) +{ + int a; + + switch (x) + { + default: + a = -1; + break; + case 0: + a = x * x + 3; + break; + case 1: + a = x + 1; + break; + case 2: + a = x + x; + break; + case 3: + a = x << 3; + break; + case 4: + a = x >> 1; + break; + case 5: + a = x; + break; + case 6: + a = 0; + break; + case 7: + a = x * x + x; + break; + } + + bar(); + + return a; +} + +int main () +{ + if (foo (0) != 3) + __builtin_abort (); + + if (foo (1) != 2) + __builtin_abort (); + + if (foo (2) != 4) + __builtin_abort (); + + if (foo (3) != 24) + __builtin_abort (); + + if (foo (4) != 2) + __builtin_abort (); + + if (foo (5) != 5) + __builtin_abort (); + + if (foo (6) != 0) + __builtin_abort (); + + if (foo (7) != 56) + __builtin_abort (); + + if (foo (8) != -1) + __builtin_abort (); + + return 0; +}