From 1a7ad2f1ed99afd9770ae968b900cd18d343f98f Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 9 Nov 2015 10:21:04 +0000 Subject: svn merge -r229832:230008 svn+ssh://gcc.gnu.org/svn/gcc/trunk git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gomp-4_5-branch@230009 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 845 ++++++++++++++++++- gcc/DATESTAMP | 2 +- gcc/ada/ChangeLog | 29 + gcc/ada/gcc-interface/decl.c | 49 +- gcc/ada/gcc-interface/gigi.h | 3 + gcc/ada/gcc-interface/trans.c | 4 +- gcc/ada/gcc-interface/utils.c | 85 +- gcc/ada/gcc-interface/utils2.c | 11 +- gcc/alloc-pool.h | 2 +- gcc/asan.c | 6 +- gcc/bb-reorder.c | 6 +- gcc/builtins.c | 263 +----- gcc/builtins.def | 9 +- gcc/builtins.h | 1 - gcc/c-family/ChangeLog | 30 + gcc/c-family/c-common.c | 81 +- gcc/c-family/c-common.h | 4 +- gcc/c-family/c-pragma.c | 50 ++ gcc/c-family/c-pragma.h | 1 + gcc/c-family/c.opt | 19 +- gcc/c/ChangeLog | 20 + gcc/c/c-decl.c | 51 +- gcc/c/c-errors.c | 12 +- gcc/c/c-objc-common.c | 2 +- gcc/c/c-typeck.c | 66 +- gcc/calls.c | 10 +- gcc/cfg-flags.def | 7 +- gcc/cfgexpand.c | 12 +- gcc/common/config/i386/i386-common.c | 3 + gcc/config.gcc | 2 +- gcc/config/aarch64/aarch64-builtins.c | 115 +++ gcc/config/aarch64/aarch64-protos.h | 4 + gcc/config/aarch64/aarch64-simd-builtins.def | 22 +- gcc/config/aarch64/aarch64-simd.md | 93 ++- gcc/config/aarch64/aarch64-tuning-flags.def | 1 + gcc/config/aarch64/aarch64.c | 140 +++- gcc/config/aarch64/aarch64.md | 3 + gcc/config/aarch64/aarch64.opt | 5 + gcc/config/aarch64/arm_neon.h | 822 +++++++++---------- gcc/config/arm/aarch-common.c | 6 + gcc/config/arm/arm-ldmstm.ml | 23 +- gcc/config/arm/arm.c | 157 ++-- gcc/config/arm/arm.h | 19 +- gcc/config/arm/arm.md | 200 ++--- gcc/config/arm/arm.opt | 2 +- gcc/config/arm/ldmstm.md | 126 +-- gcc/config/arm/sync.md | 4 +- gcc/config/arm/thumb2.md | 12 +- gcc/config/i386/i386-c.c | 8 + gcc/config/i386/i386-protos.h | 8 +- gcc/config/i386/i386.c | 308 +++++-- gcc/config/i386/i386.h | 3 +- gcc/config/i386/i386.md | 91 ++- gcc/config/i386/predicates.md | 8 +- gcc/config/i386/rdos.h | 2 +- gcc/config/mips/loongson.md | 56 +- gcc/config/mips/mips.c | 4 +- gcc/config/s390/s390.c | 2 +- gcc/config/sparc/sparc.opt | 2 +- gcc/config/tilegx/tilegx.c | 2 +- gcc/config/tilepro/tilepro.c | 2 +- gcc/cp/ChangeLog | 43 + gcc/cp/constraint.cc | 37 +- gcc/cp/error.c | 5 +- gcc/cp/init.c | 14 +- gcc/cp/parser.c | 128 +-- gcc/cp/pt.c | 17 +- gcc/cselib.c | 22 +- gcc/dbxout.c | 6 +- gcc/diagnostic-color.c | 5 +- gcc/diagnostic-core.h | 8 + gcc/diagnostic-show-locus.c | 755 ++++++++++++++--- gcc/diagnostic.c | 202 ++++- gcc/diagnostic.h | 54 +- gcc/doc/extend.texi | 116 ++- gcc/doc/invoke.texi | 41 +- gcc/doc/md.texi | 20 +- gcc/doc/tm.texi | 10 + gcc/doc/tm.texi.in | 4 + gcc/dwarf2out.c | 88 +- gcc/expmed.c | 266 ++++-- gcc/expmed.h | 8 +- gcc/expr.c | 328 +++++--- gcc/expr.h | 5 +- gcc/flag-types.h | 9 +- gcc/fold-const-call.c | 256 +++++- gcc/fold-const.c | 220 +++-- gcc/fold-const.h | 1 + gcc/fortran/ChangeLog | 65 +- gcc/fortran/array.c | 24 +- gcc/fortran/check.c | 40 +- gcc/fortran/class.c | 4 + gcc/fortran/cpp.c | 13 +- gcc/fortran/decl.c | 34 +- gcc/fortran/error.c | 103 +-- gcc/fortran/match.c | 20 +- gcc/fortran/trans-array.c | 2 + gcc/fortran/trans-types.c | 14 +- gcc/function.c | 39 +- gcc/genmatch.c | 37 +- gcc/gensupport.c | 9 +- gcc/gimple-expr.c | 8 +- gcc/gimple-fold.c | 13 +- gcc/gimple-laddress.c | 4 +- gcc/gimple-ssa-strength-reduction.c | 6 +- gcc/gimple.c | 13 +- gcc/gimplify.c | 15 +- gcc/go/gofrontend/MERGE | 2 +- gcc/graphite-optimize-isl.c | 22 +- gcc/graphite-poly.c | 2 + gcc/graphite-poly.h | 3 + gcc/graphite-scop-detection.c | 18 +- gcc/graphite-sese-to-poly.c | 240 ++++-- gcc/ifcvt.c | 4 +- gcc/input.c | 22 + gcc/internal-fn.c | 4 - gcc/internal-fn.def | 2 + gcc/ipa-cp.c | 2 +- gcc/ipa-inline-analysis.c | 1 + gcc/ipa-polymorphic-call.c | 44 +- gcc/ipa-prop.c | 30 +- gcc/ipa-prop.h | 6 +- gcc/jit/ChangeLog | 4 + gcc/jit/jit-builtins.c | 1 - gcc/lra.c | 2 +- gcc/lto-streamer-out.c | 3 +- gcc/lto/ChangeLog | 8 + gcc/lto/lto-lang.c | 1 - gcc/lto/lto.c | 5 +- gcc/objc/ChangeLog | 5 + gcc/objc/objc-encoding.c | 10 +- gcc/omp-low.c | 183 +++-- gcc/output.h | 9 +- gcc/postreload-gcse.c | 2 + gcc/pretty-print.c | 21 + gcc/pretty-print.h | 25 +- gcc/print-tree.c | 7 + gcc/rtl-error.c | 3 +- gcc/rtl.h | 1 + gcc/sched-deps.c | 4 +- gcc/simplify-rtx.c | 7 +- gcc/stor-layout.c | 11 +- gcc/target.def | 17 + gcc/targhooks.c | 17 + gcc/targhooks.h | 2 + gcc/testsuite/ChangeLog | 200 +++++ .../c-c++-common/goacc-gomp/nesting-fail-1.c | 12 +- gcc/testsuite/c-c++-common/goacc/nesting-fail-1.c | 24 +- gcc/testsuite/c-c++-common/gomp/cancel-1.c | 77 +- gcc/testsuite/c-c++-common/gomp/clauses-4.c | 34 +- gcc/testsuite/c-c++-common/gomp/doacross-1.c | 4 +- gcc/testsuite/c-c++-common/gomp/nesting-2.c | 154 ++++ gcc/testsuite/c-c++-common/gomp/nesting-warn-1.c | 12 +- gcc/testsuite/c-c++-common/gomp/ordered-3.c | 12 + gcc/testsuite/c-c++-common/gomp/ordered-4.c | 54 ++ gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc | 33 + gcc/testsuite/g++.dg/concepts/generic-fn-err.C | 4 +- gcc/testsuite/g++.dg/concepts/placeholder6.C | 10 + gcc/testsuite/g++.dg/gomp/ordered-2.C | 2 +- gcc/testsuite/g++.dg/lto/pr68057_0.C | 23 + gcc/testsuite/g++.dg/lto/pr68057_1.C | 17 + gcc/testsuite/g++.dg/torture/pr68220.C | 238 ++++++ gcc/testsuite/g++.dg/vect/pr68145.cc | 41 + gcc/testsuite/gcc.dg/Wno-frame-address.c | 2 +- gcc/testsuite/gcc.dg/gomp/ordered-2.c | 2 +- gcc/testsuite/gcc.dg/graphite/fuse-1.c | 43 + gcc/testsuite/gcc.dg/graphite/fuse-2.c | 43 + gcc/testsuite/gcc.dg/graphite/interchange-13.c | 1 - gcc/testsuite/gcc.dg/lto/20110201-1_0.c | 4 +- .../gcc.dg/plugin/diagnostic-test-show-locus-bw.c | 149 ++++ .../plugin/diagnostic-test-show-locus-color.c | 158 ++++ .../plugin/diagnostic_plugin_test_show_locus.c | 326 ++++++++ gcc/testsuite/gcc.dg/plugin/plugin.exp | 3 + gcc/testsuite/gcc.dg/pr68088_1.c | 15 + gcc/testsuite/gcc.dg/pragma-diag-5.c | 2 +- gcc/testsuite/gcc.dg/sso-1.c | 19 + gcc/testsuite/gcc.dg/sso-2.c | 94 +++ gcc/testsuite/gcc.dg/sso-3.c | 94 +++ gcc/testsuite/gcc.dg/sso-4.c | 20 + gcc/testsuite/gcc.dg/sso-5.c | 24 + gcc/testsuite/gcc.dg/sso-6.c | 72 ++ gcc/testsuite/gcc.dg/sso-7.c | 44 + gcc/testsuite/gcc.dg/sso-8.c | 44 + gcc/testsuite/gcc.dg/sso/dump.h | 23 + gcc/testsuite/gcc.dg/sso/init1.h | 12 + gcc/testsuite/gcc.dg/sso/init13.h | 15 + gcc/testsuite/gcc.dg/sso/init2.h | 24 + gcc/testsuite/gcc.dg/sso/init3.h | 34 + gcc/testsuite/gcc.dg/sso/init4.h | 14 + gcc/testsuite/gcc.dg/sso/init5.h | 14 + gcc/testsuite/gcc.dg/sso/init6.h | 24 + gcc/testsuite/gcc.dg/sso/init7.h | 28 + gcc/testsuite/gcc.dg/sso/init8.h | 28 + gcc/testsuite/gcc.dg/sso/init9.h | 14 + gcc/testsuite/gcc.dg/sso/p1.c | 64 ++ gcc/testsuite/gcc.dg/sso/p13.c | 64 ++ gcc/testsuite/gcc.dg/sso/p2.c | 88 ++ gcc/testsuite/gcc.dg/sso/p3.c | 88 ++ gcc/testsuite/gcc.dg/sso/p4.c | 64 ++ gcc/testsuite/gcc.dg/sso/p5.c | 74 ++ gcc/testsuite/gcc.dg/sso/p6.c | 74 ++ gcc/testsuite/gcc.dg/sso/p7.c | 74 ++ gcc/testsuite/gcc.dg/sso/p8.c | 74 ++ gcc/testsuite/gcc.dg/sso/p9.c | 64 ++ gcc/testsuite/gcc.dg/sso/q1.c | 50 ++ gcc/testsuite/gcc.dg/sso/q13.c | 50 ++ gcc/testsuite/gcc.dg/sso/q2.c | 54 ++ gcc/testsuite/gcc.dg/sso/q3.c | 54 ++ gcc/testsuite/gcc.dg/sso/q4.c | 50 ++ gcc/testsuite/gcc.dg/sso/q5.c | 46 ++ gcc/testsuite/gcc.dg/sso/q6.c | 45 + gcc/testsuite/gcc.dg/sso/q7.c | 46 ++ gcc/testsuite/gcc.dg/sso/q8.c | 46 ++ gcc/testsuite/gcc.dg/sso/q9.c | 50 ++ gcc/testsuite/gcc.dg/sso/r3.c | 65 ++ gcc/testsuite/gcc.dg/sso/r5.c | 65 ++ gcc/testsuite/gcc.dg/sso/r6.c | 65 ++ gcc/testsuite/gcc.dg/sso/r7.c | 65 ++ gcc/testsuite/gcc.dg/sso/r8.c | 65 ++ gcc/testsuite/gcc.dg/sso/s3.c | 79 ++ gcc/testsuite/gcc.dg/sso/s5.c | 91 +++ gcc/testsuite/gcc.dg/sso/s6.c | 81 ++ gcc/testsuite/gcc.dg/sso/s7.c | 79 ++ gcc/testsuite/gcc.dg/sso/s8.c | 79 ++ gcc/testsuite/gcc.dg/sso/sso.exp | 40 + gcc/testsuite/gcc.dg/sso/t1.c | 56 ++ gcc/testsuite/gcc.dg/sso/t13.c | 56 ++ gcc/testsuite/gcc.dg/sso/t2.c | 92 +++ gcc/testsuite/gcc.dg/sso/t3.c | 92 +++ gcc/testsuite/gcc.dg/sso/t4.c | 56 ++ gcc/testsuite/gcc.dg/sso/t5.c | 72 ++ gcc/testsuite/gcc.dg/sso/t6.c | 72 ++ gcc/testsuite/gcc.dg/sso/t7.c | 72 ++ gcc/testsuite/gcc.dg/sso/t8.c | 72 ++ gcc/testsuite/gcc.dg/sso/t9.c | 56 ++ gcc/testsuite/gcc.dg/sso/u5.c | 52 ++ gcc/testsuite/gcc.dg/sso/u6.c | 52 ++ gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c | 4 +- gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c | 6 +- gcc/testsuite/gcc.dg/vect/bb-slp-38.c | 44 + .../gcc.target/aarch64/advsimd-intrinsics/vqtbX.c | 519 ++++++++++++ .../gcc.target/aarch64/advsimd-intrinsics/vtbX.c | 4 +- gcc/testsuite/gcc.target/arm/combine-movs.c | 3 +- gcc/testsuite/gcc.target/arm/interrupt-1.c | 4 +- gcc/testsuite/gcc.target/arm/interrupt-2.c | 4 +- gcc/testsuite/gcc.target/arm/mincmp.c | 20 - gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c | 2 +- gcc/testsuite/gcc.target/i386/addr-space-1.c | 11 + gcc/testsuite/gcc.target/i386/addr-space-2.c | 11 + gcc/testsuite/gcc.target/i386/addr-space-3.c | 10 + gcc/testsuite/gcc.target/i386/movbe-3.c | 19 + .../gfortran.dg/allocate_with_arrayspec_1.f90 | 29 + gcc/testsuite/gfortran.dg/goacc/combined_loop.f90 | 3 + .../gfortran.dg/goacc/parallel-kernels-regions.f95 | 20 +- gcc/testsuite/gfortran.dg/goacc/private-3.f95 | 3 +- gcc/testsuite/gfortran.dg/gomp/target3.f90 | 2 +- gcc/testsuite/gfortran.dg/graphite/PR53852.f90 | 37 + gcc/testsuite/gfortran.dg/graphite/PR67518.f90 | 45 + gcc/testsuite/gfortran.dg/pr66465.f90 | 23 + gcc/testsuite/gfortran.dg/pr68053.f90 | 10 + gcc/testsuite/gfortran.dg/pr68151.f90 | 13 + gcc/testsuite/gfortran.dg/pr68153.f90 | 9 + gcc/testsuite/gfortran.dg/pr68224.f90 | 10 + gcc/testsuite/gfortran.dg/proc_ptr_47.f90 | 37 + .../gfortran.dg/warn_unused_function_2.f90 | 9 + gcc/testsuite/gnat.dg/specs/sso1.ads | 19 + gcc/testsuite/gnat.dg/specs/sso2.ads | 26 + gcc/testsuite/gnat.dg/sso/conv1.adb | 50 ++ gcc/testsuite/gnat.dg/sso/dump.adb | 17 + gcc/testsuite/gnat.dg/sso/dump.ads | 3 + gcc/testsuite/gnat.dg/sso/init1.ads | 26 + gcc/testsuite/gnat.dg/sso/init10.ads | 23 + gcc/testsuite/gnat.dg/sso/init11.ads | 34 + gcc/testsuite/gnat.dg/sso/init12.ads | 25 + gcc/testsuite/gnat.dg/sso/init13.ads | 33 + gcc/testsuite/gnat.dg/sso/init2.ads | 69 ++ gcc/testsuite/gnat.dg/sso/init3.ads | 78 ++ gcc/testsuite/gnat.dg/sso/init4.ads | 27 + gcc/testsuite/gnat.dg/sso/init5.ads | 39 + gcc/testsuite/gnat.dg/sso/init6.ads | 39 + gcc/testsuite/gnat.dg/sso/init7.ads | 59 ++ gcc/testsuite/gnat.dg/sso/init8.ads | 59 ++ gcc/testsuite/gnat.dg/sso/init9.ads | 27 + gcc/testsuite/gnat.dg/sso/p1.adb | 62 ++ gcc/testsuite/gnat.dg/sso/p10.adb | 63 ++ gcc/testsuite/gnat.dg/sso/p11.adb | 68 ++ gcc/testsuite/gnat.dg/sso/p12.adb | 122 +++ gcc/testsuite/gnat.dg/sso/p13.adb | 63 ++ gcc/testsuite/gnat.dg/sso/p2.adb | 80 ++ gcc/testsuite/gnat.dg/sso/p3.adb | 80 ++ gcc/testsuite/gnat.dg/sso/p4.adb | 63 ++ gcc/testsuite/gnat.dg/sso/p5.adb | 68 ++ gcc/testsuite/gnat.dg/sso/p6.adb | 61 ++ gcc/testsuite/gnat.dg/sso/p7.adb | 61 ++ gcc/testsuite/gnat.dg/sso/p8.adb | 61 ++ gcc/testsuite/gnat.dg/sso/p9.adb | 63 ++ gcc/testsuite/gnat.dg/sso/q1.adb | 52 ++ gcc/testsuite/gnat.dg/sso/q10.adb | 53 ++ gcc/testsuite/gnat.dg/sso/q11.adb | 44 + gcc/testsuite/gnat.dg/sso/q12.adb | 43 + gcc/testsuite/gnat.dg/sso/q13.adb | 53 ++ gcc/testsuite/gnat.dg/sso/q2.adb | 60 ++ gcc/testsuite/gnat.dg/sso/q3.adb | 60 ++ gcc/testsuite/gnat.dg/sso/q4.adb | 53 ++ gcc/testsuite/gnat.dg/sso/q5.adb | 44 + gcc/testsuite/gnat.dg/sso/q6.adb | 44 + gcc/testsuite/gnat.dg/sso/q7.adb | 44 + gcc/testsuite/gnat.dg/sso/q8.adb | 44 + gcc/testsuite/gnat.dg/sso/q9.adb | 53 ++ gcc/testsuite/gnat.dg/sso/r11.adb | 68 ++ gcc/testsuite/gnat.dg/sso/r12.adb | 123 +++ gcc/testsuite/gnat.dg/sso/r3.adb | 68 ++ gcc/testsuite/gnat.dg/sso/r5.adb | 68 ++ gcc/testsuite/gnat.dg/sso/r6.adb | 68 ++ gcc/testsuite/gnat.dg/sso/r7.adb | 68 ++ gcc/testsuite/gnat.dg/sso/r8.adb | 68 ++ gcc/testsuite/gnat.dg/sso/s11.adb | 78 ++ gcc/testsuite/gnat.dg/sso/s12.adb | 77 ++ gcc/testsuite/gnat.dg/sso/s3.adb | 79 ++ gcc/testsuite/gnat.dg/sso/s5.adb | 78 ++ gcc/testsuite/gnat.dg/sso/s6.adb | 79 ++ gcc/testsuite/gnat.dg/sso/s7.adb | 79 ++ gcc/testsuite/gnat.dg/sso/s8.adb | 79 ++ gcc/testsuite/gnat.dg/sso/sso.exp | 40 + gcc/testsuite/gnat.dg/sso/t1.adb | 55 ++ gcc/testsuite/gnat.dg/sso/t10.adb | 56 ++ gcc/testsuite/gnat.dg/sso/t11.adb | 67 ++ gcc/testsuite/gnat.dg/sso/t12.adb | 66 ++ gcc/testsuite/gnat.dg/sso/t13.adb | 56 ++ gcc/testsuite/gnat.dg/sso/t2.adb | 84 ++ gcc/testsuite/gnat.dg/sso/t3.adb | 84 ++ gcc/testsuite/gnat.dg/sso/t4.adb | 56 ++ gcc/testsuite/gnat.dg/sso/t5.adb | 67 ++ gcc/testsuite/gnat.dg/sso/t6.adb | 67 ++ gcc/testsuite/gnat.dg/sso/t7.adb | 68 ++ gcc/testsuite/gnat.dg/sso/t8.adb | 68 ++ gcc/testsuite/gnat.dg/sso/t9.adb | 56 ++ gcc/testsuite/gnat.dg/sso/u11.adb | 44 + gcc/testsuite/gnat.dg/sso/u5.adb | 44 + gcc/testsuite/gnat.dg/sso/u6.adb | 44 + gcc/testsuite/gnat.dg/sso1.adb | 77 ++ gcc/testsuite/gnat.dg/sso2.adb | 14 + gcc/testsuite/gnat.dg/sso2.ads | 13 + gcc/testsuite/gnat.dg/sso3.adb | 52 ++ gcc/testsuite/gnat.dg/sso4.adb | 55 ++ gcc/testsuite/gnat.dg/sso5.adb | 52 ++ gcc/testsuite/gnat.dg/sso6.adb | 54 ++ gcc/testsuite/gnat.dg/sso7.adb | 52 ++ gcc/testsuite/lib/gcc-dg.exp | 1 + gcc/trans-mem.c | 3 + gcc/tree-affine.c | 10 +- gcc/tree-call-cdce.c | 37 +- gcc/tree-cfg.c | 2 +- gcc/tree-core.h | 15 +- gcc/tree-data-ref.c | 20 +- gcc/tree-dfa.c | 11 +- gcc/tree-dfa.h | 2 +- gcc/tree-diagnostic.c | 2 +- gcc/tree-hash-traits.h | 10 +- gcc/tree-inline.c | 2 + gcc/tree-into-ssa.c | 2 +- gcc/tree-into-ssa.h | 1 + gcc/tree-outof-ssa.c | 2 +- gcc/tree-parloops.c | 2 + gcc/tree-pretty-print.c | 2 +- gcc/tree-scalar-evolution.c | 7 +- gcc/tree-sra.c | 106 ++- gcc/tree-ssa-address.c | 2 +- gcc/tree-ssa-alias.c | 18 +- gcc/tree-ssa-dce.c | 4 +- gcc/tree-ssa-loop-ivopts.c | 27 +- gcc/tree-ssa-math-opts.c | 10 +- gcc/tree-ssa-pre.c | 5 +- gcc/tree-ssa-sccvn.c | 67 +- gcc/tree-ssa-sccvn.h | 1 + gcc/tree-ssa-structalias.c | 10 +- gcc/tree-ssa-tail-merge.c | 2 +- gcc/tree-ssa-threadedge.c | 114 +-- gcc/tree-ssa-threadupdate.c | 288 +------ gcc/tree-ssanames.c | 192 ++++- gcc/tree-streamer-in.c | 7 +- gcc/tree-streamer-out.c | 7 +- gcc/tree-vect-data-refs.c | 21 +- gcc/tree-vect-patterns.c | 69 +- gcc/tree-vect-slp.c | 184 +++-- gcc/tree-vect-stmts.c | 28 +- gcc/tree-vectorizer.c | 35 + gcc/tree-vectorizer.h | 3 + gcc/tree-vrp.c | 14 +- gcc/tree.c | 10 +- gcc/tree.h | 85 +- gcc/tsan.c | 6 +- gcc/ubsan.c | 8 +- gcc/var-tracking.c | 3 +- gcc/varasm.c | 121 ++- gcc/varasm.h | 2 +- include/ChangeLog | 10 + include/obstack.h | 910 ++++++++++----------- libcilkrts/ChangeLog | 6 + libcilkrts/runtime/config/x86/os-unix-sysdep.c | 2 +- libcpp/ChangeLog | 25 + libcpp/errors.c | 7 +- libcpp/include/cpplib.h | 4 +- libcpp/include/line-map.h | 220 +++++ libcpp/line-map.c | 133 +++ libgcc/ChangeLog | 19 + libgcc/config/rs6000/atexit.c | 44 + libgcc/config/rs6000/cxa_finalize.c | 4 +- libgcc/config/rs6000/libgcc-aix-cxa.ver | 4 + libgcc/config/rs6000/t-aix-cxa | 3 +- libgcc/config/visium/lib2funcs.c | 2 +- libgcc/fixed-bit.h | 10 +- libgcc/fp-bit.h | 4 +- libgcc/libgcc2.c | 24 +- libgcc/libgcc2.h | 8 +- libgcc/libgcov.h | 4 +- libgo/Makefile.am | 14 +- libgo/Makefile.in | 9 +- libgo/go/encoding/json/decode_test.go | 16 +- libgo/go/encoding/json/encode.go | 2 +- libgo/go/encoding/xml/marshal_test.go | 10 + libgo/go/encoding/xml/typeinfo.go | 2 +- libgo/go/net/tcpsockopt_solaris.go | 24 +- libgo/go/reflect/export_test.go | 4 +- libgo/go/reflect/type.go | 2 +- libgo/go/reflect/value.go | 29 +- libgo/go/syscall/exec_bsd.go | 6 +- libgo/go/syscall/exec_linux.go | 11 +- libgo/go/syscall/exec_unix.go | 6 +- libgo/go/syscall/exec_unix_test.go | 2 +- libgo/go/syscall/libcall_bsd.go | 27 + libgo/runtime/go-varargs.c | 1 + libgomp/ChangeLog | 5 + .../libgomp.oacc-c-c++-common/loop-red-v-2.c | 2 + .../libgomp.oacc-c-c++-common/loop-red-w-2.c | 2 + libiberty/ChangeLog | 34 + libiberty/config.in | 3 + libiberty/configure | 64 ++ libiberty/configure.ac | 7 + libiberty/obstack.c | 570 +++++-------- libiberty/obstacks.texi | 257 +++--- libobjc/ChangeLog | 11 + libobjc/encoding.c | 35 +- libsanitizer/ChangeLog | 18 + libsanitizer/Makefile.in | 1 + libsanitizer/asan/Makefile.am | 2 +- libsanitizer/asan/Makefile.in | 3 +- libsanitizer/configure | 38 +- libsanitizer/configure.ac | 24 + libsanitizer/interception/Makefile.in | 1 + libsanitizer/libbacktrace/Makefile.in | 1 + libsanitizer/lsan/Makefile.in | 1 + libsanitizer/sanitizer_common/Makefile.in | 1 + .../sanitizer_common_interceptors.inc | 14 +- libsanitizer/tsan/Makefile.am | 2 +- libsanitizer/tsan/Makefile.in | 3 +- libsanitizer/ubsan/Makefile.in | 1 + libstdc++-v3/ChangeLog | 12 + .../complex/requirements/constexpr_functions.cc | 2 +- .../complex/value_operations/constexpr.cc | 2 +- libstdc++-v3/testsuite/lib/libstdc++.exp | 2 + libvtv/ChangeLog | 5 + libvtv/vtv_malloc.cc | 7 +- 463 files changed, 18860 insertions(+), 4004 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/gomp/nesting-2.c create mode 100644 gcc/testsuite/c-c++-common/gomp/ordered-4.c create mode 100644 gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc create mode 100644 gcc/testsuite/g++.dg/concepts/placeholder6.C create mode 100644 gcc/testsuite/g++.dg/lto/pr68057_0.C create mode 100644 gcc/testsuite/g++.dg/lto/pr68057_1.C create mode 100644 gcc/testsuite/g++.dg/torture/pr68220.C create mode 100644 gcc/testsuite/g++.dg/vect/pr68145.cc create mode 100644 gcc/testsuite/gcc.dg/graphite/fuse-1.c create mode 100644 gcc/testsuite/gcc.dg/graphite/fuse-2.c create mode 100644 gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c create mode 100644 gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c create mode 100644 gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c create mode 100644 gcc/testsuite/gcc.dg/pr68088_1.c create mode 100644 gcc/testsuite/gcc.dg/sso-1.c create mode 100644 gcc/testsuite/gcc.dg/sso-2.c create mode 100644 gcc/testsuite/gcc.dg/sso-3.c create mode 100644 gcc/testsuite/gcc.dg/sso-4.c create mode 100644 gcc/testsuite/gcc.dg/sso-5.c create mode 100644 gcc/testsuite/gcc.dg/sso-6.c create mode 100644 gcc/testsuite/gcc.dg/sso-7.c create mode 100644 gcc/testsuite/gcc.dg/sso-8.c create mode 100644 gcc/testsuite/gcc.dg/sso/dump.h create mode 100644 gcc/testsuite/gcc.dg/sso/init1.h create mode 100644 gcc/testsuite/gcc.dg/sso/init13.h create mode 100644 gcc/testsuite/gcc.dg/sso/init2.h create mode 100644 gcc/testsuite/gcc.dg/sso/init3.h create mode 100644 gcc/testsuite/gcc.dg/sso/init4.h create mode 100644 gcc/testsuite/gcc.dg/sso/init5.h create mode 100644 gcc/testsuite/gcc.dg/sso/init6.h create mode 100644 gcc/testsuite/gcc.dg/sso/init7.h create mode 100644 gcc/testsuite/gcc.dg/sso/init8.h create mode 100644 gcc/testsuite/gcc.dg/sso/init9.h create mode 100644 gcc/testsuite/gcc.dg/sso/p1.c create mode 100644 gcc/testsuite/gcc.dg/sso/p13.c create mode 100644 gcc/testsuite/gcc.dg/sso/p2.c create mode 100644 gcc/testsuite/gcc.dg/sso/p3.c create mode 100644 gcc/testsuite/gcc.dg/sso/p4.c create mode 100644 gcc/testsuite/gcc.dg/sso/p5.c create mode 100644 gcc/testsuite/gcc.dg/sso/p6.c create mode 100644 gcc/testsuite/gcc.dg/sso/p7.c create mode 100644 gcc/testsuite/gcc.dg/sso/p8.c create mode 100644 gcc/testsuite/gcc.dg/sso/p9.c create mode 100644 gcc/testsuite/gcc.dg/sso/q1.c create mode 100644 gcc/testsuite/gcc.dg/sso/q13.c create mode 100644 gcc/testsuite/gcc.dg/sso/q2.c create mode 100644 gcc/testsuite/gcc.dg/sso/q3.c create mode 100644 gcc/testsuite/gcc.dg/sso/q4.c create mode 100644 gcc/testsuite/gcc.dg/sso/q5.c create mode 100644 gcc/testsuite/gcc.dg/sso/q6.c create mode 100644 gcc/testsuite/gcc.dg/sso/q7.c create mode 100644 gcc/testsuite/gcc.dg/sso/q8.c create mode 100644 gcc/testsuite/gcc.dg/sso/q9.c create mode 100644 gcc/testsuite/gcc.dg/sso/r3.c create mode 100644 gcc/testsuite/gcc.dg/sso/r5.c create mode 100644 gcc/testsuite/gcc.dg/sso/r6.c create mode 100644 gcc/testsuite/gcc.dg/sso/r7.c create mode 100644 gcc/testsuite/gcc.dg/sso/r8.c create mode 100644 gcc/testsuite/gcc.dg/sso/s3.c create mode 100644 gcc/testsuite/gcc.dg/sso/s5.c create mode 100644 gcc/testsuite/gcc.dg/sso/s6.c create mode 100644 gcc/testsuite/gcc.dg/sso/s7.c create mode 100644 gcc/testsuite/gcc.dg/sso/s8.c create mode 100644 gcc/testsuite/gcc.dg/sso/sso.exp create mode 100644 gcc/testsuite/gcc.dg/sso/t1.c create mode 100644 gcc/testsuite/gcc.dg/sso/t13.c create mode 100644 gcc/testsuite/gcc.dg/sso/t2.c create mode 100644 gcc/testsuite/gcc.dg/sso/t3.c create mode 100644 gcc/testsuite/gcc.dg/sso/t4.c create mode 100644 gcc/testsuite/gcc.dg/sso/t5.c create mode 100644 gcc/testsuite/gcc.dg/sso/t6.c create mode 100644 gcc/testsuite/gcc.dg/sso/t7.c create mode 100644 gcc/testsuite/gcc.dg/sso/t8.c create mode 100644 gcc/testsuite/gcc.dg/sso/t9.c create mode 100644 gcc/testsuite/gcc.dg/sso/u5.c create mode 100644 gcc/testsuite/gcc.dg/sso/u6.c create mode 100644 gcc/testsuite/gcc.dg/vect/bb-slp-38.c create mode 100644 gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqtbX.c delete mode 100644 gcc/testsuite/gcc.target/arm/mincmp.c create mode 100644 gcc/testsuite/gcc.target/i386/addr-space-1.c create mode 100644 gcc/testsuite/gcc.target/i386/addr-space-2.c create mode 100644 gcc/testsuite/gcc.target/i386/addr-space-3.c create mode 100644 gcc/testsuite/gcc.target/i386/movbe-3.c create mode 100644 gcc/testsuite/gfortran.dg/allocate_with_arrayspec_1.f90 create mode 100644 gcc/testsuite/gfortran.dg/graphite/PR53852.f90 create mode 100644 gcc/testsuite/gfortran.dg/graphite/PR67518.f90 create mode 100644 gcc/testsuite/gfortran.dg/pr66465.f90 create mode 100644 gcc/testsuite/gfortran.dg/pr68053.f90 create mode 100644 gcc/testsuite/gfortran.dg/pr68151.f90 create mode 100644 gcc/testsuite/gfortran.dg/pr68153.f90 create mode 100644 gcc/testsuite/gfortran.dg/pr68224.f90 create mode 100644 gcc/testsuite/gfortran.dg/proc_ptr_47.f90 create mode 100644 gcc/testsuite/gnat.dg/specs/sso1.ads create mode 100644 gcc/testsuite/gnat.dg/specs/sso2.ads create mode 100644 gcc/testsuite/gnat.dg/sso/conv1.adb create mode 100644 gcc/testsuite/gnat.dg/sso/dump.adb create mode 100644 gcc/testsuite/gnat.dg/sso/dump.ads create mode 100644 gcc/testsuite/gnat.dg/sso/init1.ads create mode 100644 gcc/testsuite/gnat.dg/sso/init10.ads create mode 100644 gcc/testsuite/gnat.dg/sso/init11.ads create mode 100644 gcc/testsuite/gnat.dg/sso/init12.ads create mode 100644 gcc/testsuite/gnat.dg/sso/init13.ads create mode 100644 gcc/testsuite/gnat.dg/sso/init2.ads create mode 100644 gcc/testsuite/gnat.dg/sso/init3.ads create mode 100644 gcc/testsuite/gnat.dg/sso/init4.ads create mode 100644 gcc/testsuite/gnat.dg/sso/init5.ads create mode 100644 gcc/testsuite/gnat.dg/sso/init6.ads create mode 100644 gcc/testsuite/gnat.dg/sso/init7.ads create mode 100644 gcc/testsuite/gnat.dg/sso/init8.ads create mode 100644 gcc/testsuite/gnat.dg/sso/init9.ads create mode 100644 gcc/testsuite/gnat.dg/sso/p1.adb create mode 100644 gcc/testsuite/gnat.dg/sso/p10.adb create mode 100644 gcc/testsuite/gnat.dg/sso/p11.adb create mode 100644 gcc/testsuite/gnat.dg/sso/p12.adb create mode 100644 gcc/testsuite/gnat.dg/sso/p13.adb create mode 100644 gcc/testsuite/gnat.dg/sso/p2.adb create mode 100644 gcc/testsuite/gnat.dg/sso/p3.adb create mode 100644 gcc/testsuite/gnat.dg/sso/p4.adb create mode 100644 gcc/testsuite/gnat.dg/sso/p5.adb create mode 100644 gcc/testsuite/gnat.dg/sso/p6.adb create mode 100644 gcc/testsuite/gnat.dg/sso/p7.adb create mode 100644 gcc/testsuite/gnat.dg/sso/p8.adb create mode 100644 gcc/testsuite/gnat.dg/sso/p9.adb create mode 100644 gcc/testsuite/gnat.dg/sso/q1.adb create mode 100644 gcc/testsuite/gnat.dg/sso/q10.adb create mode 100644 gcc/testsuite/gnat.dg/sso/q11.adb create mode 100644 gcc/testsuite/gnat.dg/sso/q12.adb create mode 100644 gcc/testsuite/gnat.dg/sso/q13.adb create mode 100644 gcc/testsuite/gnat.dg/sso/q2.adb create mode 100644 gcc/testsuite/gnat.dg/sso/q3.adb create mode 100644 gcc/testsuite/gnat.dg/sso/q4.adb create mode 100644 gcc/testsuite/gnat.dg/sso/q5.adb create mode 100644 gcc/testsuite/gnat.dg/sso/q6.adb create mode 100644 gcc/testsuite/gnat.dg/sso/q7.adb create mode 100644 gcc/testsuite/gnat.dg/sso/q8.adb create mode 100644 gcc/testsuite/gnat.dg/sso/q9.adb create mode 100644 gcc/testsuite/gnat.dg/sso/r11.adb create mode 100644 gcc/testsuite/gnat.dg/sso/r12.adb create mode 100644 gcc/testsuite/gnat.dg/sso/r3.adb create mode 100644 gcc/testsuite/gnat.dg/sso/r5.adb create mode 100644 gcc/testsuite/gnat.dg/sso/r6.adb create mode 100644 gcc/testsuite/gnat.dg/sso/r7.adb create mode 100644 gcc/testsuite/gnat.dg/sso/r8.adb create mode 100644 gcc/testsuite/gnat.dg/sso/s11.adb create mode 100644 gcc/testsuite/gnat.dg/sso/s12.adb create mode 100644 gcc/testsuite/gnat.dg/sso/s3.adb create mode 100644 gcc/testsuite/gnat.dg/sso/s5.adb create mode 100644 gcc/testsuite/gnat.dg/sso/s6.adb create mode 100644 gcc/testsuite/gnat.dg/sso/s7.adb create mode 100644 gcc/testsuite/gnat.dg/sso/s8.adb create mode 100644 gcc/testsuite/gnat.dg/sso/sso.exp create mode 100644 gcc/testsuite/gnat.dg/sso/t1.adb create mode 100644 gcc/testsuite/gnat.dg/sso/t10.adb create mode 100644 gcc/testsuite/gnat.dg/sso/t11.adb create mode 100644 gcc/testsuite/gnat.dg/sso/t12.adb create mode 100644 gcc/testsuite/gnat.dg/sso/t13.adb create mode 100644 gcc/testsuite/gnat.dg/sso/t2.adb create mode 100644 gcc/testsuite/gnat.dg/sso/t3.adb create mode 100644 gcc/testsuite/gnat.dg/sso/t4.adb create mode 100644 gcc/testsuite/gnat.dg/sso/t5.adb create mode 100644 gcc/testsuite/gnat.dg/sso/t6.adb create mode 100644 gcc/testsuite/gnat.dg/sso/t7.adb create mode 100644 gcc/testsuite/gnat.dg/sso/t8.adb create mode 100644 gcc/testsuite/gnat.dg/sso/t9.adb create mode 100644 gcc/testsuite/gnat.dg/sso/u11.adb create mode 100644 gcc/testsuite/gnat.dg/sso/u5.adb create mode 100644 gcc/testsuite/gnat.dg/sso/u6.adb create mode 100644 gcc/testsuite/gnat.dg/sso1.adb create mode 100644 gcc/testsuite/gnat.dg/sso2.adb create mode 100644 gcc/testsuite/gnat.dg/sso2.ads create mode 100644 gcc/testsuite/gnat.dg/sso3.adb create mode 100644 gcc/testsuite/gnat.dg/sso4.adb create mode 100644 gcc/testsuite/gnat.dg/sso5.adb create mode 100644 gcc/testsuite/gnat.dg/sso6.adb create mode 100644 gcc/testsuite/gnat.dg/sso7.adb create mode 100644 libgcc/config/rs6000/atexit.c create mode 100644 libgo/go/syscall/libcall_bsd.go diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f01e8ec1263..d0b119f0c5b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,839 @@ +2015-11-09 Richard Henderson + + * config/i386/i386-c.c (ix86_target_macros): Define __SEG_FS, + __SEG_GS, __SEG_TLS. + (ix86_register_pragmas): Register address spaces __seg_fs, + __seg_gs, __seg_tls. + * config/i386/i386-protos.h (enum ix86_address_seg): Remove. + (ADDR_SPACE_SEG_FS, ADDR_SPACE_SEG_GS, ADDR_SPACE_SEG_TLS): New. + (struct ix86_address): Use addr_space_t instead of ix86_address_seg. + * config/i386/i386.c (ix86_decompose_address): Likewise. + (ix86_legitimate_address_p): Likewise. + (memory_address_length): Likewise. Check mem address space too. + (ix86_print_operand): Use ix86_print_operand_address_as. + (ix86_print_operand_address_as): Rename from + ix86_print_operand_address, add new addr_space_t parameter. + Validate that either the parameter or the ix86_address segment + is default address space. Handle ADDR_SPACE_SEG_TLS. + (ix86_print_operand_address): New. + (ix86_addr_space_subset_p, TARGET_ADDR_SPACE_SUBSET_P): New. + (ix86_addr_space_convert, TARGET_ADDR_SPACE_CONVERT): New. + (ix86_addr_space_debug, TARGET_ADDR_SPACE_DEBUG): New. + (ix86_addr_space_zero_address_valid): New. + (TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID): New. + * config/i386/i386.h (DEFAULT_TLS_SEG_REG): Use addr_space_t constants. + * config/i386/rdos.h (DEFAULT_TLS_SEG_REG): Likewise. + * config/i386/predicates.md (address_no_seg_operand): Likewise. + (vsib_address_operand): Likewise. + (address_mpx_no_base_operand): Likewise. + (address_mpx_no_index_operand): Likewise. + * doc/extend.texi (x86 Named Address Spaces): New section. + + * config/i386/i386.c (ix86_check_no_addr_space): New. + (decide_alg): Add have_as parameter. + (alg_usable_p): Likewise; disable rep algorithms if set. + (ix86_expand_set_or_movmem): Notice if either MEM has a + non-default address space. + (ix86_expand_strlen): Likewise. + * config/i386/i386.md (strmov, strset): Likewise. + (*strmovdi_rex_1): Use ix86_check_no_addr_space. + (*strmovsi_1, *strmovqi_1, *rep_movdi_rex64, *rep_movsi, *rep_movqi, + *strsetdi_rex_1, *strsetsi_1, *strsethi_1, *strsetqi_1, + *rep_stosdi_rex64, *rep_stossi, *rep_stosqi, *cmpstrnqi_nz_1, + *cmpstrnqi_1, *strlenqi_1): Likewise. + + * config/i386/i386.md (*movabs_1): Print the full memory rtx. + (*movabs_2): Likewise. + + * dwarf2out.c (modified_type_die): Pass the address space number + through TARGET_ADDR_SPACE_DEBUG to produce the dwarf address class. + * target.def (TARGET_ADDR_SPACE_DEBUG): New. + * targhooks.c (default_addr_space_debug): New. + * targhooks.h (default_addr_space_debug): Declare. + * doc/tm.texi.in (TARGET_ADDR_SPACE_DEBUG): Mark it. + * doc/tm.texi: Rebuild. + + * gimple.c (check_loadstore): Return false when 0 is a valid address. + * fold-const.c (const_unop) [ADDR_SPACE_CONVERT_EXPR]: Do not fold + null when 0 is valid in the source address space. + * target.def (TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID): New. + * targhooks.c (default_addr_space_zero_address_valid): New. + * targhooks.h (default_addr_space_zero_address_valid): Declare. + * doc/tm.texi.in (TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID): Mark it. + * doc/tm.texi: Rebuild. + + * cselib.c (add_mem_for_addr): Compare address spaces when + matching memories. + (cselib_lookup_mem): Likewise. + * fold-const.c (operand_equal_p): Check address spaces of + pointer types before checking integer constants. + + PR tree-opt/66768 + * tree-ssa-address.c (create_mem_ref_raw): Use a pointer of + the correct type for the base. + +2015-11-09 Jeff Law + + * tree-into-ssa.c (names_to_release): No longer static. + * tree-into-ssa.h (names_to_release): Declare. + * tree-ssanames.c (verify_ssaname_freelists): New debug function. + (release_free_names_and_compact_live_names): New function extracted + from pass_release_ssa_names::execute. + (pass_release_ssa_names::execute): Use it. + +2015-11-09 Alan Modra + + * gensupport.c (add_mnemonic_string): Make len param a size_t. + (gen_mnemonic_setattr): Make "size" var a size_t. Use + obstack_blank_fast to shrink obstack. Cast obstack_next_free + return value. + +2015-11-09 Segher Boessenkool + + PR rtl-optimization/68182 + * gcc/bb-reorder.c (reorder_basic_blocks_simple): Treat a conditional + branch with only one successor just like unconditional branches. + +2015-11-08 Jeff Law + + * tree-ssa-threadupdate.c (register_jump_thraed): Assert that a + non-FSM path has no edges marked with EDGE_DFS_BACK. + (ssa_redirect_edges): No longer call mark_loop_for_removal. + (thread_single_edge, def_split_header_continue_p): Remove. + (bb_ends_with_multiway_branch): Likewise. + (thread_through_loop_header): Remove cases of threading from + latch through the header. Simplify knowing we won't thread + the latch. + (thread_through_all_blocks): Simplify knowing that only the FSM + threader needs to handle backedges. + +2015-11-08 Eric Botcazou + + * doc/extend.texi (type attributes): Document scalar_storage_order. + (Structure-Packing Pragmas): Rename into... + (Structure-Layout Pragmas): ...this. Document scalar_storage_order. + * doc/invoke.texi (C Dialect Options): Document -fsso-struct + (Warnings): Document -Wno-scalar-storage-order. + * flag-types.h (enum scalar_storage_order_kind): New enumeration. + * calls.c (store_unaligned_arguments_into_pseudos): Adjust calls to + extract_bit_field and store_bit_field. + (initialize_argument_information): Adjust call to store_expr. + (load_register_parameters): Adjust call to extract_bit_field. + * expmed.c (check_reverse_storage_order_support): New function. + (check_reverse_float_storage_order_support): Likewise. + (flip_storage_order): Likewise. + (store_bit_field_1): Add REVERSE parameter. Flip the storage order + of the value if it is true. Pass REVERSE to recursive call after + adjusting the target offset. + Do not use extraction or movstrict instruction if REVERSE is true. + Pass REVERSE to store_fixed_bit_field. + (store_bit_field): Add REVERSE parameter and pass to it to above. + (store_fixed_bit_field): Add REVERSE parameter and pass to it to + store_split_bit_field and store_fixed_bit_field_1. + (store_fixed_bit_field_1): Add REVERSE parameter. Flip the storage + order of the value if it is true and adjust the target offset. + (store_split_bit_field): Add REVERSE parameter and pass it to + store_fixed_bit_field. Adjust the target offset if it is true. + (extract_bit_field_1): Add REVERSE parameter. Flip the storage order + of the value if it is true. Pass REVERSE to recursive call after + adjusting the target offset. + Do not use extraction or subreg instruction if REVERSE is true. + Pass REVERSE to extract_fixed_bit_field. + (extract_bit_field): Add REVERSE parameter and pass to it to above. + (extract_fixed_bit_field): Add REVERSE parameter and pass to it to + extract_split_bit_field and extract_fixed_bit_field_1. + (extract_fixed_bit_field_1): Add REVERSE parameter. Flip the storage + order of the value if it is true and adjust the target offset. + (extract_split_bit_field): Add REVERSE parameter and pass it to + extract_fixed_bit_field. Adjust the target offset if it is true. + * expmed.h (flip_storage_order): Declare. + (store_bit_field): Adjust prototype. + (extract_bit_field): Likewise. + * expr.c (emit_group_load_1): Adjust calls to extract_bit_field. + (emit_group_store): Adjust call to store_bit_field. + (copy_blkmode_from_reg): Likewise. + (copy_blkmode_to_reg): Likewise. + (write_complex_part): Likewise. + (read_complex_part): Likewise. + (optimize_bitfield_assignment_op): Add REVERSE parameter. Assert + that it isn't true if the target is a register. + : If it is, do not optimize unless bitsize is equal to 1, + and flip the storage order of the value. + : Flip the storage order of the value. + (get_bit_range): Adjust call to get_inner_reference. + (expand_assignment): Adjust calls to get_inner_reference, store_expr, + optimize_bitfield_assignment_op and store_field. Handle MEM_EXPRs + with reverse storage order. + (store_expr_with_bounds): Add REVERSE parameter and pass it to + recursive calls and call to store_bit_field. Force the value into a + register if it is true and then flip the storage order of the value. + (store_expr): Add REVERSE parameter and pass it to above. + (categorize_ctor_elements_1): Adjust call to + initializer_constant_valid_p. + (store_constructor_field): Add REVERSE parameter and pass it to + recursive calls and call to store_field. + (store_constructor): Add REVERSE parameter and pass it to calls to + store_constructor_field and store_expr. Set it to true for an + aggregate type with TYPE_REVERSE_STORAGE_ORDER. + (store_field): Add REVERSE parameter and pass it to recursive calls + and calls to store_expr and store_bit_field. Temporarily flip the + storage order of the value with record type and integral mode and + adjust the shift if it is true. + (get_inner_reference): Add PREVERSEP parameter and set it to true + upon encoutering a reference with reverse storage order. + (expand_expr_addr_expr_1): Adjust call to get_inner_reference. + (expand_constructor): Adjust call to store_constructor. + (expand_expr_real_2) : Pass TYPE_REVERSE_STORAGE_ORDER + of the union type to store_expr in the MEM case and assert that it + isn't set in the REG case. Adjust call to store_field. + (expand_expr_real_1) : Handle reverse storage order. + : Add REVERSEP variable and adjust calls to + get_inner_reference and extract_bit_field. Temporarily flip the + storage order of the value with record type and integral mode and + adjust the shift if it is true. Flip the storage order of the value + at the end if it is true. + : Add REVERSEP variable and adjust call to + get_inner_reference. Do not fetch an inner reference if it is true. + * expr.h (store_expr_with_bounds): Ajust prototype. + (store_expr): Likewise. + * fold-const.c (make_bit_field_ref): Add REVERSEP parameter and set + REF_REVERSE_STORAGE_ORDER on the reference according to it. + (optimize_bit_field_compare): Deal with reverse storage order. + Adjust calls to get_inner_reference and make_bit_field_ref. + (decode_field_reference): Add PREVERSEP parameter and adjust call to + get_inner_reference. + (fold_truth_andor_1): Deal with reverse storage order. Adjust calls + to decode_field_reference and make_bit_field_ref. + (fold_unary_loc) : Adjust call to get_inner_reference. + : Propagate the REF_REVERSE_STORAGE_ORDER flag. + (fold_comparison): Adjust call to get_inner_reference. + (split_address_to_core_and_offset): Adjust call to + get_inner_reference. + * gimple-expr.c (useless_type_conversion_p): Return false for array + types with different TYPE_REVERSE_STORAGE_ORDER flag. + * gimplify.c (gimplify_expr) : Propagate the + REF_REVERSE_STORAGE_ORDER flag. + * lto-streamer-out.c (hash_tree): Deal with + TYPE_REVERSE_STORAGE_ORDER. + * output.h (assemble_real): Adjust prototype. + * print-tree.c (print_node): Convey TYPE_REVERSE_STORAGE_ORDER. + * stor-layout.c (finish_record_layout): Propagate the + TYPE_REVERSE_STORAGE_ORDER flag to the variants. + * tree-core.h (TYPE_REVERSE_STORAGE_ORDER): Document. + (TYPE_SATURATING): Adjust. + (REF_REVERSE_STORAGE_ORDER): Document. + * tree-dfa.c (get_ref_base_and_extent): Add PREVERSE parameter and + set it to true upon encoutering a reference with reverse storage + order. + * tree-dfa.h (get_ref_base_and_extent): Adjust prototype. + * tree-inline.c (remap_gimple_op_r): Propagate the + REF_REVERSE_STORAGE_ORDER flag. + (copy_tree_body_r): Likewise. + * tree-outof-ssa.c (insert_value_copy_on_edge): Adjust call to + store_expr. + * tree-streamer-in.c (unpack_ts_base_value_fields): Deal with + TYPE_REVERSE_STORAGE_ORDER and REF_REVERSE_STORAGE_ORDER. + * tree-streamer-out.c (pack_ts_base_value_fields): Likewise. + * tree.c (stabilize_reference) : Propagate the + REF_REVERSE_STORAGE_ORDER flag. + (verify_type_variant): Deal with TYPE_REVERSE_STORAGE_ORDER. + (gimple_canonical_types_compatible_p): Likewise. + * tree.h (TYPE_REVERSE_STORAGE_ORDER): New flag. + (TYPE_SATURATING): Adjust. + (REF_REVERSE_STORAGE_ORDER): New flag. + (reverse_storage_order_for_component_p): New inline predicate. + (storage_order_barrier_p): Likewise. + (get_inner_reference): Adjust prototype. + * varasm.c: Include expmed.h. + (assemble_variable_contents): Adjust call to output_constant. + (assemble_real): Add REVERSE parameter. Flip the storage + order of the value if REVERSE is true. + (compare_constant) : Compare TYPE_REVERSE_STORAGE_ORDER. + (assemble_constant_contents): Adjust call to output_constant. + (output_constant_pool_2): Adjust call to assemble_real. + (initializer_constant_valid_p_1) : Deal with + TYPE_REVERSE_STORAGE_ORDER. + (initializer_constant_valid_p): Add REVERSE parameter. + (output_constant): Add REVERSE parameter. + : Flip the storage order of the value if REVERSE is true. + : Adjust call to assemble_real. + : Pass it to recursive calls. + : Likewise. Adjust call to output_constructor. + : Likewise. Adjust call to output_constructor. + (struct oc_local_state): Add REVERSE field. + (output_constructor_array_range): Adjust calls to output_constant. + (output_constructor_regular_field): Likewise. + (output_constructor_bitfield): Adjust call to output_constructor. + Flip the storage order of the value if REVERSE is true. + (output_constructor): Add REVERSE parameter. Set it to true for an + aggregate type with TYPE_REVERSE_STORAGE_ORDER. Adjust call to + output_constructor_bitfield. + * varasm.h (initializer_constant_valid_p): Default REVERSE to false. + * asan.c (instrument_derefs): Adjust call to get_inner_reference. + * builtins.c (get_object_alignment_2): Likewise. + * cfgexpand.c (expand_debug_expr): Adjust call to get_inner_reference + and get_ref_base_and_extent. + * dbxout.c (dbxout_expand_expr): Likewise. + * dwarf2out.c (add_var_loc_to_decl): Likewise. + (loc_list_for_address_of_addr_expr_of_indirect_ref): Likewise. + (loc_list_from_tree): Likewise. + (fortran_common): Likewise. + * gimple-fold.c (gimple_fold_builtin_memory_op): Adjust calls to + get_ref_base_and_extent. + (get_base_constructor): Likewise. + (fold_const_aggregate_ref_1): Likewise. + * gimple-laddress.c (pass_laddress::execute): Adjust call to + get_inner_reference. + * gimple-ssa-strength-reduction.c (slsr_process_ref): Adjust call to + get_inner_reference and bail out on reverse storage order. + * ifcvt.c (noce_emit_move_insn): Adjust calls to store_bit_field. + * ipa-cp.c (ipa_get_jf_ancestor_result): Adjust call to + build_ref_for_offset. + * ipa-polymorphic-call.c (set_by_invariant): Adjust call to + get_ref_base_and_extent. + (ipa_polymorphic_call_context): Likewise. + (extr_type_from_vtbl_ptr_store): Likewise. + (check_stmt_for_type_change): Likewise. + (get_dynamic_type): Likewise. + * ipa-prop.c (ipa_load_from_parm_agg_1): Adjust call to + get_ref_base_and_extent. + (compute_complex_assign_jump_func): Likewise. + (get_ancestor_addr_info): Likewise. + (compute_known_type_jump_func): Likewise. + (determine_known_aggregate_parts): Likewise. + (ipa_get_adjustment_candidate): Likewise. + (ipa_modify_call_arguments): Set REF_REVERSE_STORAGE_ORDER on + MEM_REF. + * ipa-prop.h (ipa_parm_adjustment): Add REVERSE field. + (build_ref_for_offset): Adjust prototype. + * simplify-rtx.c (delegitimize_mem_from_attrs): Adjust call to + get_inner_reference. + * tree-affine.c (tree_to_aff_combination): Adjust call to + get_inner_reference. + (get_inner_reference_aff): Likewise. + * tree-data-ref.c (split_constant_offset_1): Likewise. + (dr_analyze_innermost): Likewise. Bail out if reverse storage order. + * tree-scalar-evolution.c (interpret_rhs_expr): Adjust call to + get_inner_reference. + * tree-sra.c (struct access): Add REVERSE and move WRITE around. + (dump_access): Print new fields. + (create_access): Adjust call to get_ref_base_and_extent and set the + REVERSE flag according to the result. + (completely_scalarize_record): Set the REVERSE flag. + (scalarize_elem): Add REVERSE parameter. + (build_access_from_expr_1): Preserve storage order barriers. + (build_accesses_from_assign): Likewise. + (build_ref_for_offset): Add REVERSE parameter and set the + REF_REVERSE_STORAGE_ORDER flag accordingly. + (build_ref_for_model): Adjust call to build_ref_for_offset and clear + the REF_REVERSE_STORAGE_ORDER flag if there are components. + (analyze_access_subtree): Likewise. + (create_artificial_child_access): Set the REVERSE flag. + (get_access_for_expr): Adjust call to get_ref_base_and_extent. + (turn_representatives_into_adjustments): Propagate REVERSE flag. + (ipa_sra_check_caller): Adjust call to get_inner_reference. + * tree-ssa-alias.c (ao_ref_base): Adjust call to + get_ref_base_and_extent. + (aliasing_component_refs_p): Likewise. + (stmt_kills_ref_p_1): Likewise. + * tree-ssa-dce.c (mark_aliased_reaching_defs_necessary_1): Likewise. + * tree-ssa-loop-ivopts.c (may_be_nonaddressable_p) : New. + Return true if reverse storage order. + : Likewise. + : Likewise. + : Likewise. + : Likewise. + (split_address_cost): Likewise. Bail out if reverse storage order. + * tree-ssa-math-opts.c (find_bswap_or_nop_load): Adjust call to + get_inner_reference. Bail out if reverse storage order. + (bswap_replace): Adjust call to get_inner_reference. + * tree-ssa-pre.c (create_component_ref_by_pieces_1) : Set + the REF_REVERSE_STORAGE_ORDER flag. + : Likewise. + * tree-ssa-sccvn.c (vn_reference_eq): Return false on storage order + barriers. + (copy_reference_ops_from_ref) : Set REVERSE field according + to the REF_REVERSE_STORAGE_ORDER flag. + : Likewise. + : Set it for storage order barriers. + (contains_storage_order_barrier_p): New predicate. + (vn_reference_lookup_3): Adjust calls to get_ref_base_and_extent. + Punt on storage order barriers if necessary. + * tree-ssa-sccvn.h (struct vn_reference_op_struct): Add REVERSE. + * tree-ssa-structalias.c (get_constraint_for_component_ref): Adjust + call to get_ref_base_and_extent. + (do_structure_copy): Likewise. + * tree-vect-data-refs.c (vect_check_gather): Adjust call to + get_inner_reference. + (vect_analyze_data_refs): Likewise. Bail out if reverse storage + order. + * tsan.c (instrument_expr): Adjust call to get_inner_reference. + * ubsan.c (instrument_bool_enum_load): Likewise. + (instrument_object_size): Likewise. + * var-tracking.c (track_expr_p): Adjust call to + get_ref_base_and_extent + * config/mips/mips.c (r10k_safe_mem_expr_p): Adjust call to + get_inner_reference. + * config/s390/s390.c (s390_expand_atomic): Adjust call to + store_bit_field. + * config/tilegx/tilegx.c (tilegx_expand_unaligned_load): Adjust call to + extract_bit_field. + * config/tilepro/tilepro.c (tilepro_expand_unaligned_load): Likewise. + +2015-11-07 Eric Botcazou + + * config/sparc/sparc.opt (mfix-at697f): Add final period. + +2015-11-07 Segher Boessenkool + + PR rtl-optimization/67864 + * common/config/i386/i386-common.c (ix86_option_optimization_table) + : Use REORDER_BLOCKS_ALGORITHM_STC + at -Os and up. + +2015-11-07 Richard Sandiford + + * trans-mem.c (is_tm_pure_call): Use gimple_call_flags for + internal functions. + +2015-11-07 Richard Sandiford + + * builtins.def: #undef DEF_BUILTIN and DEF_BUILTIN_CHKP + * builtins.c, genmatch.c, tree-core.h: Don't undef them here. + +2015-11-07 Richard Sandiford + + * internal-fn.def: #undef DEF_INTERNAL_FN at the end. + * internal-fn.c: Don't undef it here. + * tree-core.h: Likewise. + +2015-11-07 Richard Sandiford + + * builtins.c (fold_builtin_nan): Delete. + (fold_builtin_memcmp): Remove case where both arguments are constant. + (fold_builtin_strcmp, fold_builtin_strncmp): Likewise. + (fold_builtin_strspn, fold_builtin_strcspn): Likewise. + (fold_builtin_1): Remove BUILT_IN_NAN* handling. + * fold-const-call.c: Include fold-const.h. + (host_size_t_cst_p): New function. + (build_cmp_result, fold_const_builtin_nan): Likewise. + (fold_const_call_1): New function, split out from... + (fold_const_call): ...here (for all three interfaces). Handle + constant nan, nans, strlen, strcmp, strncmp, strspn and strcspn. + +2015-11-07 Richard Sandiford + + * builtins.c (fold_builtin_bitop, fold_builtin_bswap): Delete. + (fold_builtin_1): Don't call them. + * fold-const-call.c: Include tm.h. + (fold_const_call_ss): New variant for integer-to-integer folds. + (fold_const_call): Call it. + +2015-11-07 Richard Sandiford + + * builtins.c (fold_builtin_classify): Move constant cases to... + * fold-const-call.c (fold_const_call_ss): ...here. + +2015-11-07 Richard Sandiford + + * builtins.h (c_getstr): Move to... + * fold-const.h (c_getstr): ...here. + * builtins.c (c_getstr): Move to... + * fold-const.c (c_getstr): ...here. + +2015-11-07 Richard Sandiford + + * builtins.def (BUILTIN_RINT, BUILTIN_RINTF, BUILTIN_RINTL): Use + ATTR_MATHFN_FPROUNDING rather than ATTR_MATHFN_FPROUNDING_ERRNO. + +2015-11-07 Richard Sandiford + + * tree-call-cdce.c (shrink_wrap_one_built_in_call): Try to update + the dominance info; free it if we can't. + (pass_call_cdce::execute): Don't free the dominance info here. + +2015-11-06 Jeff Law + + * tree-ssa-threadedge.c (dummy_simplify): Remove. + (thread_around_empty_blocks): Remove backedge_seen_p argument. + If we thread to a backedge, then return false. Update recursive + call to eliminate backedge_seen_p argument. + (thread_through_normal_block): Remove backedge_seen_p argument. + Remove backedge_seen_p argument from calls to + thread_around_empty_blocks. Remove checks on backedge_seen_p. + If we thread to a backedge, then return 0. + (thread_across_edge): Remove bookkeeping for backedge_seen. Don't + pass it to thread_through_normal_block or thread_through_empty_blocks. + For joiner handling, if we see a backedge, do not try normal + threading. + +2015-11-06 Abderrazek Zaafrani + + * graphite-optimize-isl.c (optimize_isl): Call isl_union_map_is_equal. + * graphite-poly.c (new_scop): Initialize original_schedule. + (free_scop): Free original_schedule. + * graphite-poly.h (struct scop): Add field original_schedule. + * graphite-sese-to-poly.c (build_scop_original_schedule): New. + (build_poly_scop): Call build_scop_original_schedule. + +2015-11-06 Abderrazek Zaafrani + + * graphite-sese-to-poly.c (build_pbb_scattering_polyhedrons): Remove. + (build_pbb_minimal_scattering_polyhedrons): New. + (build_scop_scattering): Remove. + (build_scop_minimal_scattering): New. + (build_scop_scattering): Call build_pbb_minimal_scattering_polyhedrons. + (build_poly_scop): Call build_scop_minimal_scattering. + +2015-11-06 Jeff Law + + * cfg-flags.def (IGNORE): New edge flag. + * tree-vrp.c (identify_jump_threads): Mark and clear edges + scheduled for removal with EDGE_IGNORE around call into + jump threader. Do no thread across edges with EDGE_IGNORE, + but do allow threading across those with EDGE_DFS_BACK. + +2015-11-06 David Wohlferd + + * doc/md.texi (multi-alternative constraints): Don't document + alternatives inherently tied to reload for the user documentation. + +2015-11-06 Michael Collison + + Revert: + 2015-08-01 Michael Collison + + * config/arm/arm.md (*arm_smin_cmp): New pattern. + (*arm_umin_cmp): Likewise. + +2015-11-06 Jakub Jelinek + + * gimplify.c (gimplify_omp_ordered): Fix up diagnostics + wording. + * omp-low.c (check_omp_nesting_restrictions): Update for the + various new OpenMP 4.5 nesting restrictions, clarified + nesting glossary, closely nested region relationship clarified + to mean explicit or implicit parallel regions (target/teams), + use % or %qs where appropriate. + +2015-11-06 Aditya Kumar + Sebastian Pop + + * graphite-scop-detection.c (loop_is_valid_scop): Call + optimize_loop_nest_for_speed_p. + +2015-11-06 Aditya Kumar + Sebastian Pop + + * graphite-optimize-isl.c (optimize_isl): Call + isl_options_set_schedule_maximize_band_depth. + +2015-11-06 Aditya Kumar + Sebastian Pop + + * graphite-scop-detection.c (scop_detection::merge_sese): Entry + and exit edges should not be a part of irreducible loop. + (scop_detection::can_represent_loop_1): Loops should not be + irreducible. + (scop_detection::harmful_stmt_in_region): All the basic block + should belong to reducible loops. + +2015-11-06 Christophe Lyon + + * config/aarch64/aarch64-simd-builtins.def: Update builtins + tables: add tbl3v16qi, qtbl[34]*, tbx4v16qi, qtbx[34]*. + * config/aarch64/aarch64-simd.md (aarch64_tbl3v8qi): Rename to... + (aarch64_tbl3) ... this, which supports v16qi too. + (aarch64_tbx4v8qi): Rename to... + aarch64_tbx4): ... this. + (aarch64_qtbl3): New pattern. + (aarch64_qtbx3): New pattern. + (aarch64_qtbl4): New pattern. + (aarch64_qtbx4): New pattern. + * config/aarch64/arm_neon.h (vqtbl2_s8, vqtbl2_u8, vqtbl2_p8) + (vqtbl2q_s8, vqtbl2q_u8, vqtbl2q_p8, vqtbl3_s8, vqtbl3_u8) + (vqtbl3_p8, vqtbl3q_s8, vqtbl3q_u8, vqtbl3q_p8, vqtbl4_s8) + (vqtbl4_u8, vqtbl4_p8, vqtbl4q_s8, vqtbl4q_u8, vqtbl4q_p8) + (vqtbx2_s8, vqtbx2_u8, vqtbx2_p8, vqtbx2q_s8, vqtbx2q_u8) + (vqtbx2q_p8, vqtbx3_s8, vqtbx3_u8, vqtbx3_p8, vqtbx3q_s8) + (vqtbx3q_u8, vqtbx3q_p8, vqtbx4_s8, vqtbx4_u8, vqtbx4_p8) + (vqtbx4q_s8, vqtbx4q_u8, vqtbx4q_p8): Rewrite using builtin + functions. + +2015-11-06 Mike Stump + + PR debug/66728 + * dwarf2out.c (get_full_len): Return a value based upon the actual + precision needed for the value. + (add_const_value_attribute): Use a maximal wide-int for + CONST_WIDE_INTs, not VOIDmode. + (output_die): Don't ever output NULL with printf. + + * rtl.h (get_precision of rtx_mode_t): Ensure we never process + BLKmode nor VOIDmode values. + +2015-11-06 David Malcolm + + * diagnostic-color.c (color_dict): Eliminate "caret"; add "range1" + and "range2". + (parse_gcc_colors): Update comment to describe default GCC_COLORS. + * diagnostic-core.h (warning_at_rich_loc): New declaration. + (error_at_rich_loc): New declaration. + (permerror_at_rich_loc): New declaration. + (inform_at_rich_loc): New declaration. + * diagnostic-show-locus.c (adjust_line): Delete. + (struct point_state): New struct. + (class colorizer): New class. + (class layout_point): New class. + (class layout_range): New class. + (struct line_bounds): New. + (class layout): New class. + (colorizer::colorizer): New ctor. + (colorizer::~colorizer): New dtor. + (layout::layout): New ctor. + (layout::print_source_line): New method. + (layout::print_annotation_line): New method. + (layout::get_state_at_point): New method. + (layout::get_x_bound_for_row): New method. + (diagnostic_show_locus): Reimplement in terms of class layout. + (diagnostic_print_caret_line): Delete. + * diagnostic.c (diagnostic_initialize): Replace + MAX_LOCATIONS_PER_MESSAGE with rich_location::MAX_RANGES. + (diagnostic_set_info_translated): Convert param from location_t + to rich_location *. Eliminate calls to set_location on the + message in favor of storing the rich_location ptr there. + (diagnostic_set_info): Convert param from location_t to + rich_location *. + (diagnostic_build_prefix): Break out array into... + (diagnostic_kind_color): New variable. + (diagnostic_get_color_for_kind): New function. + (diagnostic_report_diagnostic): Colorize the option_text + using the color for the severity. + (diagnostic_append_note): Update for change in signature of + diagnostic_set_info. + (diagnostic_append_note_at_rich_loc): New function. + (emit_diagnostic): Update for change in signature of + diagnostic_set_info. + (inform): Likewise. + (inform_at_rich_loc): New function. + (inform_n): Update for change in signature of diagnostic_set_info. + (warning): Likewise. + (warning_at): Likewise. + (warning_at_rich_loc): New function. + (warning_n): Update for change in signature of diagnostic_set_info. + (pedwarn): Likewise. + (permerror): Likewise. + (permerror_at_rich_loc): New function. + (error): Update for change in signature of diagnostic_set_info. + (error_n): Likewise. + (error_at): Likewise. + (error_at_rich_loc): New function. + (sorry): Update for change in signature of diagnostic_set_info. + (fatal_error): Likewise. + (internal_error): Likewise. + (internal_error_no_backtrace): Likewise. + (source_range::debug): New function. + * diagnostic.h (struct diagnostic_info): Eliminate field + "override_column". Add field "richloc". + (struct diagnostic_context): Add field "colorize_source_p". + (diagnostic_override_column): Delete. + (diagnostic_set_info): Convert param from location_t to + rich_location *. + (diagnostic_set_info_translated): Likewise. + (diagnostic_append_note_at_rich_loc): New function. + (diagnostic_num_locations): New function. + (diagnostic_expand_location): Get the location from the + rich_location. + (diagnostic_print_caret_line): Delete. + (diagnostic_get_color_for_kind): New declaration. + * genmatch.c (linemap_client_expand_location_to_spelling_point): New. + (error_cb): Update for change in signature of "error" callback. + (fatal_at): Likewise. + (warning_at): Likewise. + * input.c (linemap_client_expand_location_to_spelling_point): New. + * pretty-print.c (text_info::set_range): New method. + (text_info::get_location): New method. + * pretty-print.h (MAX_LOCATIONS_PER_MESSAGE): Eliminate this macro. + (struct text_info): Eliminate "locations" array in favor of + "m_richloc", a rich_location *. + (textinfo::set_location): Add a "caret_p" param, and reimplement + in terms of a call to set_range. + (textinfo::get_location): Eliminate inline implementation in favor of + an out-of-line reimplementation. + (textinfo::set_range): New method. + * rtl-error.c (diagnostic_for_asm): Update for change in signature + of diagnostic_set_info. + * tree-diagnostic.c (default_tree_printer): Update for new + "caret_p" param for textinfo::set_location. + * tree-pretty-print.c (percent_K_format): Likewise. + +2015-11-06 Ramana Radhakrishnan + + Properly apply. + 2015-11-05 Ramana Radhakrishnan + * config/aarch64/aarch64.c + (aarch64_can_use_per_function_literal_pools_p): New. + (aarch64_use_blocks_for_constant_p): Adjust declaration + and use aarch64_can_use_function_literal_pools_p. + (aarch64_select_rtx_section): Update. + +2015-11-06 Ramana Radhakrishnan + + * config/arm/arm-ldmstm.ml: Rewrite to generate unified asm templates. + * config/arm/arm.c (arm_asm_trampoline_template): Make unified asm safe. + (arm_output_multireg_pop): Likewise. + (output_move_double): Likewise. + (output_move_quad): Likewise. + (output_return_instruction): Likewise. + (arm_print_operand): Remove support for %( and %. print modifiers. + (arm_output_shift): Make unified asm. + (arm_declare_function_name): Likewise. + * config/arm/arm.h (TARGET_UNIFIED_ASM): Delete. + (ASM_APP_OFF): Adjust. + (ASM_OUTPUT_REG_PUSH): Undo special casing for TARGET_ARM. + (ASM_OUTPUT_REG_POP): Likewise. + * config/arm/arm.md: Adjust uses of %., %(, %) + * config/arm/sync.md: Likewise. + * config/arm/thumb2.md: Likewise. + * config/arm/ldmstm.md: Regenerate. + * config/arm/arm.opt (masm-unified-syntax): Do not special case Thumb. + * doc/invoke.texi (masm-unified-syntax): Update documentation. + +2015-11-06 David Malcolm + + * input.c (dump_line_table_statistics): Dump stats on adhoc table. + +2015-11-07 Jan Hubicka + + * tree-core.h (size_type_kind): Remove OEP_CONSTANT_ADDRESS_OF and + add OEP_MATCH_SIDE_EFFECTS. + * fold-const.c (operand_equal_p): Update documentation; handle + OEP_MATCH_SIDE_EFFECTS. + * tree-ssa-tail-merge.c (gimple_operand_equal_value_p): Use + OEP_MATCH_SIDE_EFFECTS. + +2015-11-06 Benedikt Huber + Philipp Tomsich + + * config/aarch64/aarch64-builtins.c: Builtins for rsqrt and rsqrtf. + * config/aarch64/aarch64-protos.h: Declare. + * config/aarch64/aarch64-simd.md: Matching expressions for frsqrte and + frsqrts. + * config/aarch64/aarch64-tuning-flags.def: Added recip_sqrt. + * config/aarch64/aarch64.c: New functions. Emit rsqrt estimation code when + applicable. + * config/aarch64/aarch64.md: Added enum entries. + * config/aarch64/aarch64.opt: Added option -mlow-precision-recip-sqrt. + * testsuite/gcc.target/aarch64/rsqrt_asm_check_common.h: Common macros for + assembly checks. + * testsuite/gcc.target/aarch64/rsqrt_asm_check_negative_1.c: Make sure + frsqrts and frsqrte are not emitted. + * testsuite/gcc.target/aarch64/rsqrt_asm_check_1.c: Make sure frsqrts and + frsqrte are emitted. + * testsuite/gcc.target/aarch64/rsqrt_1.c: Functional tests for rsqrt. + +2015-11-07 Jan Hubicka + + PR ipa/68057 + PR ipa/68220 + * ipa-polymorphic-call.c + (ipa_polymorphic_call_context::restrict_to_inner_type): Fix ordering + issue when offset is out of range. + (contains_type_p): Fix out of range check, clear dynamic flag. + +2015-11-06 Arnout Vandecappelle + + * config.gcc (e6500): Fix cpu_is_64bit typo. + +2015-11-06 Alan Lawrence + + * tree-sra.c (completely_scalarize): Properly handle negative array + indices using offset_int. + +2015-11-06 Richard Biener + + * alloc-pool.h (object_allocator::allocate): Default-initialize + object. + +2015-11-06 Richard Biener + + * tree-ssa-sccvn.c (class sccvn_dom_walker): Add destructor. + * lra.c (init_reg_info): Truncate copy_vec instead of + re-allocating a new one and leaking the old. + * ipa-inline-analysis.c (estimate_function_body_sizes): Free + bb_infos vec. + * sched-deps.c (sched_deps_finish): Free the dn/dl pools. + * postreload-gcse.c (free_mem): Free modify_mem_list and + canon_modify_mem_list. + +2015-11-06 Ilya Enkovich + + PR tree-optimization/68145 + * tree-vect-stmts.c (vectorizable_operation): Fix + determination for booleans. + +2015-11-06 Tom de Vries + + * tree-cfg.c (gimple_split_block_before_cond_jump): Split before + cond_jump, instead of split after last nondebug insn before cond_jump. + * tree-parloops.c (transform_to_exit_first_loop_alt): Verify ssa before + returning. + +2015-11-06 Kyrylo Tkachov + + PR target/68088 + * config/arm/aarch-common.c (aarch_accumulator_forwarding): Strip + subregs from accumulator and make sure it's a register. + +2015-11-06 Simon Dardis + + * config/mips/loongson.md (vec_loongson_extract_lo_): New, extract + low part to scalar. + (reduc_uplus_): Remove. + (reduc_plus_scal_): Rename from reduc_splus_, Use vec + loongson_extract_lo_. + (reduc_smax_scal_, reduc_smin_scal_): Rename from + reduc_smax_, reduc_smax_, use vec + loongson_extract_lo_. + (reduc_umax_scal_, reduc_umin_scal_): Rename. + +2015-11-06 Richard Biener + + * tree-vectorizer.h (struct _bb_vec_info): Add region_begin/end + members. + (vect_stmt_in_region_p): Declare. + * tree-vect-slp.c (new_bb_vec_info): Work on a region. + (destroy_bb_vec_info): Likewise. + (vect_bb_slp_scalar_cost): Use vect_stmt_in_region_p. + (vect_get_and_check_slp_defs): Likewise. + (vect_slp_analyze_bb_1): Refactor to make it work on sub-BBs. + (vect_slp_bb): Likewise. + * tree-vect-patterns.c (vect_same_loop_or_bb_p): Implement + in terms of vect_stmt_in_region_p. + (vect_pattern_recog): Iterate over the BB region. + * tree-vect-stmts.c (vect_is_simple_use): Use vect_stmt_in_region_p. + * tree-vectorizer.c (vect_stmt_in_region_p): New function. + (pass_slp_vectorize::execute): Initialize all stmt UIDs to -1. + * config/i386/i386.c: Include gimple-iterator.h. + * config/aarch64/aarch64.c: Likewise. + +2015-11-06 Alexandre Oliva + + PR rtl-optimization/67753 + PR rtl-optimization/64164 + * function.c (assign_parm_setup_block): Avoid allocating a + stack slot if we don't have an ABI-reserved one. Emit the + copy to target_reg in the conversion seq if the copy from + entry_parm is in it too. Don't use the conversion seq to copy + a PARALLEL to a REG or a CONCAT. + +2015-11-06 Richard Biener + + * tree-hash-traits.h (tree_operand_hash): Provide equal, not + equal_keys. + 2015-11-05 Cesar Philippidis Thomas Schwinge James Norris @@ -17,8 +853,7 @@ 2015-11-05 Martin Sebor PR c++/67942 - * invoke.texi (-Wplacement-new): Document new option. - * gcc/testsuite/g++.dg/warn/Wplacement-new-size.C: New test. + * doc/invoke.texi (-Wplacement-new): Document new option. 2015-11-05 Alan Lawrence @@ -422,7 +1257,7 @@ * tree-ssa.c (gimple_uses_undefined_value_p): New. * tree-ssa.h (gimple_uses_undefined_value_p): Declare. -2015-11-02 Jeff Law +2015-11-02 Jeff Law * tree-ssa-threadupdate.c (valid_jump_thread_path): Also detect cases where the loop latch edge is in the middle of an FSM path. @@ -486,7 +1321,7 @@ PR middle-end/68166 * fold-const.c: Include "md5.h". -2015-11-01 Jeff Law +2015-11-01 Jeff Law * vmsdbgout.c: Revert unused header file reduction patch. @@ -535,7 +1370,7 @@ * tree-ssa-structalias.c (ipa_pta_execute): Use make_copy_constraint. -2015-10-30 Jeff Law +2015-10-30 Jeff Law Nathan Sidwell * config/nvptx/nvptx.h (HARD_REGNO_NREGS): Avoid warning on unused diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 4d10d51aefc..563100ef632 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20151106 +20151109 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 22afbdc1b10..ca1cb618be6 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,32 @@ +2015-11-08 Eric Botcazou + + * gcc-interface/gigi.h (set_reverse_storage_order_on_pad_type): + Declare. + * gcc-interface/decl.c (gnat_to_gnu_entity) : Set the + storage order on the enclosing record for a packed array type. + : Set the storage order. + : Likewise. + : Likewise. + : Likewise. + (gnat_to_gnu_component_type): Set the reverse storage order on a + padded type built for a non-bit-packed array. + (gnat_to_gnu_field): Likewise. + (components_to_record): Deal with TYPE_REVERSE_STORAGE_ORDER. + * gcc-interface/utils.c (make_packable_type): Likewise. + (pad_type_hasher::equal): Likewise. + (gnat_types_compatible_p): Likewise. + (unchecked_convert): Likewise. + (set_reverse_storage_order_on_pad_type): New public function. + * gcc-interface/trans.c (Attribute_to_gnu): Adjust call to + get_inner_reference. + * gcc-interface/utils2.c (build_unary_op): Likewise. + (gnat_build_constructor): Deal with TYPE_REVERSE_STORAGE_ORDER. + (gnat_rewrite_reference): Propagate REF_REVERSE_STORAGE_ORDER. + +2015-11-07 Richard Sandiford + + * gcc-interface/utils.c: Don't undef DEF_BUILTIN. + 2015-10-29 Andrew MacLeod * gcc-interface/decl.c: Reorder #include's and remove duplicates. diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 7f15b7cdf93..627eace9dd2 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -1805,6 +1805,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) TYPE_ALIGN (gnu_type) = align > 0 ? align : TYPE_ALIGN (gnu_field_type); + /* Propagate the reverse storage order flag to the record type so + that the required byte swapping is performed when retrieving the + enclosed modular value. */ + TYPE_REVERSE_STORAGE_ORDER (gnu_type) + = Reverse_Storage_Order (Original_Array_Type (gnat_entity)); + relate_alias_sets (gnu_type, gnu_field_type, ALIAS_SET_COPY); /* Don't declare the field as addressable since we won't be taking @@ -2152,8 +2158,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) for (index = ndim - 1; index >= 0; index--) { tem = build_nonshared_array_type (tem, gnu_index_types[index]); - if (Reverse_Storage_Order (gnat_entity) && !GNAT_Mode) - sorry ("non-default Scalar_Storage_Order"); + if (index == ndim - 1) + TYPE_REVERSE_STORAGE_ORDER (tem) + = Reverse_Storage_Order (gnat_entity); TYPE_MULTI_ARRAY_P (tem) = (index > 0); if (array_type_has_nonaliased_component (tem, gnat_entity)) TYPE_NONALIASED_COMPONENT (tem) = 1; @@ -2516,6 +2523,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) { gnu_type = build_nonshared_array_type (gnu_type, gnu_index_types[index]); + if (index == ndim - 1) + TYPE_REVERSE_STORAGE_ORDER (gnu_type) + = Reverse_Storage_Order (gnat_entity); TYPE_MULTI_ARRAY_P (gnu_type) = (index > 0); if (array_type_has_nonaliased_component (gnu_type, gnat_entity)) TYPE_NONALIASED_COMPONENT (gnu_type) = 1; @@ -2876,8 +2886,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) gnu_type = make_node (tree_code_for_record_type (gnat_entity)); TYPE_NAME (gnu_type) = gnu_entity_name; TYPE_PACKED (gnu_type) = (packed != 0) || has_rep; - if (Reverse_Storage_Order (gnat_entity) && !GNAT_Mode) - sorry ("non-default Scalar_Storage_Order"); + TYPE_REVERSE_STORAGE_ORDER (gnu_type) + = Reverse_Storage_Order (gnat_entity); process_attributes (&gnu_type, &attr_list, true, gnat_entity); if (!definition) @@ -3287,6 +3297,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) gnu_type = make_node (RECORD_TYPE); TYPE_NAME (gnu_type) = gnu_entity_name; TYPE_PACKED (gnu_type) = TYPE_PACKED (gnu_base_type); + TYPE_REVERSE_STORAGE_ORDER (gnu_type) + = Reverse_Storage_Order (gnat_entity); process_attributes (&gnu_type, &attr_list, true, gnat_entity); /* Set the size, alignment and alias set of the new type to @@ -3341,6 +3353,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) TYPE_NAME (new_variant) = concat_name (TYPE_NAME (gnu_type), IDENTIFIER_POINTER (suffix)); + TYPE_REVERSE_STORAGE_ORDER (new_variant) + = TYPE_REVERSE_STORAGE_ORDER (gnu_type); copy_and_substitute_in_size (new_variant, old_variant, gnu_subst_list); v->new_type = new_variant; @@ -5548,6 +5562,16 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition, gnat_array); } + /* If the component type is a padded type made for a non-bit-packed array + of scalars with reverse storage order, we need to propagate the reverse + storage order to the padding type since it is the innermost enclosing + aggregate type around the scalar. */ + if (TYPE_IS_PADDING_P (gnu_type) + && Reverse_Storage_Order (gnat_array) + && !Is_Bit_Packed_Array (gnat_array) + && Is_Scalar_Type (gnat_type)) + gnu_type = set_reverse_storage_order_on_pad_type (gnu_type); + if (Has_Volatile_Components (gnat_array)) { const int quals @@ -6718,6 +6742,15 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed, else gnu_pos = NULL_TREE; + /* If the field's type is a padded type made for a scalar field of a record + type with reverse storage order, we need to propagate the reverse storage + order to the padding type since it is the innermost enclosing aggregate + type around the scalar. */ + if (TYPE_IS_PADDING_P (gnu_field_type) + && TYPE_REVERSE_STORAGE_ORDER (gnu_record_type) + && Is_Scalar_Type (gnat_field_type)) + gnu_field_type = set_reverse_storage_order_on_pad_type (gnu_field_type); + gcc_assert (TREE_CODE (gnu_field_type) != RECORD_TYPE || !TYPE_CONTAINS_TEMPLATE_P (gnu_field_type)); @@ -7034,6 +7067,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list, TYPE_NAME (gnu_union_type) = gnu_union_name; TYPE_ALIGN (gnu_union_type) = 0; TYPE_PACKED (gnu_union_type) = TYPE_PACKED (gnu_record_type); + TYPE_REVERSE_STORAGE_ORDER (gnu_union_type) + = TYPE_REVERSE_STORAGE_ORDER (gnu_record_type); } /* If all the fields down to this level have a rep clause, find out @@ -7085,6 +7120,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list, record actually gets only the alignment required. */ TYPE_ALIGN (gnu_variant_type) = TYPE_ALIGN (gnu_record_type); TYPE_PACKED (gnu_variant_type) = TYPE_PACKED (gnu_record_type); + TYPE_REVERSE_STORAGE_ORDER (gnu_variant_type) + = TYPE_REVERSE_STORAGE_ORDER (gnu_record_type); /* Similarly, if the outer record has a size specified and all the fields have a rep clause, we can propagate the size. */ @@ -7177,6 +7214,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list, position at this level. */ tree gnu_rep_type = make_node (RECORD_TYPE); tree gnu_rep_part; + TYPE_REVERSE_STORAGE_ORDER (gnu_rep_type) + = TYPE_REVERSE_STORAGE_ORDER (gnu_variant_type); finish_record_type (gnu_rep_type, NULL_TREE, 0, debug_info); gnu_rep_part = create_rep_part (gnu_rep_type, gnu_variant_type, @@ -7384,6 +7423,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list, gnu_field_list = gnu_rep_list; else { + TYPE_REVERSE_STORAGE_ORDER (gnu_rep_type) + = TYPE_REVERSE_STORAGE_ORDER (gnu_record_type); finish_record_type (gnu_rep_type, gnu_rep_list, 1, debug_info); /* If FIRST_FREE_POS is nonzero, we need to ensure that the fields diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index 9420fd83f75..d7a25662e80 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -154,6 +154,9 @@ extern tree maybe_pad_type (tree type, tree size, unsigned int align, bool is_user_type, bool definition, bool set_rm_size); +/* Return a copy of the padded TYPE but with reverse storage order. */ +extern tree set_reverse_storage_order_on_pad_type (tree type); + enum alias_set_op { ALIAS_SET_COPY, diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 946c91a5df9..5c093fbf161 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -2172,7 +2172,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute) tree gnu_field_offset; tree gnu_inner; machine_mode mode; - int unsignedp, volatilep; + int unsignedp, reversep, volatilep; gnu_result_type = get_unpadded_type (Etype (gnat_node)); gnu_prefix = remove_conversions (gnu_prefix, true); @@ -2194,7 +2194,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute) && TREE_CODE (gnu_prefix) == FIELD_DECL)); get_inner_reference (gnu_prefix, &bitsize, &bitpos, &gnu_offset, - &mode, &unsignedp, &volatilep, false); + &mode, &unsignedp, &reversep, &volatilep, false); if (TREE_CODE (gnu_prefix) == COMPONENT_REF) { diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 8617a876ae6..224dc002bdb 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -957,6 +957,7 @@ make_packable_type (tree type, bool in_record) TYPE_NAME (new_type) = TYPE_NAME (type); TYPE_JUSTIFIED_MODULAR_P (new_type) = TYPE_JUSTIFIED_MODULAR_P (type); TYPE_CONTAINS_TEMPLATE_P (new_type) = TYPE_CONTAINS_TEMPLATE_P (type); + TYPE_REVERSE_STORAGE_ORDER (new_type) = TYPE_REVERSE_STORAGE_ORDER (type); if (TREE_CODE (type) == RECORD_TYPE) TYPE_PADDING_P (new_type) = TYPE_PADDING_P (type); @@ -1175,14 +1176,15 @@ pad_type_hasher::equal (pad_type_hash *t1, pad_type_hash *t2) type1 = t1->type; type2 = t2->type; - /* We consider that the padded types are equivalent if they pad the same - type and have the same size, alignment and RM size. Taking the mode - into account is redundant since it is determined by the others. */ + /* We consider that the padded types are equivalent if they pad the same type + and have the same size, alignment, RM size and storage order. Taking the + mode into account is redundant since it is determined by the others. */ return TREE_TYPE (TYPE_FIELDS (type1)) == TREE_TYPE (TYPE_FIELDS (type2)) && TYPE_SIZE (type1) == TYPE_SIZE (type2) && TYPE_ALIGN (type1) == TYPE_ALIGN (type2) - && TYPE_ADA_SIZE (type1) == TYPE_ADA_SIZE (type2); + && TYPE_ADA_SIZE (type1) == TYPE_ADA_SIZE (type2) + && TYPE_REVERSE_STORAGE_ORDER (type1) == TYPE_REVERSE_STORAGE_ORDER (type2); } /* Look up the padded TYPE in the hash table and return its canonical version @@ -1452,6 +1454,31 @@ built: return record; } + +/* Return a copy of the padded TYPE but with reverse storage order. */ + +tree +set_reverse_storage_order_on_pad_type (tree type) +{ + tree field, canonical_pad_type; + +#ifdef ENABLE_CHECKING + /* If the inner type is not scalar then the function does nothing. */ + tree inner_type = TREE_TYPE (TYPE_FIELDS (type)); + gcc_assert (!AGGREGATE_TYPE_P (inner_type) && !VECTOR_TYPE_P (inner_type)); +#endif + + /* This is required for the canonicalization. */ + gcc_assert (TREE_CONSTANT (TYPE_SIZE (type))); + + field = copy_node (TYPE_FIELDS (type)); + type = copy_type (type); + DECL_CONTEXT (field) = type; + TYPE_FIELDS (type) = field; + TYPE_REVERSE_STORAGE_ORDER (type) = 1; + canonical_pad_type = lookup_and_insert_pad_type (type); + return canonical_pad_type ? canonical_pad_type : type; +} /* Relate the alias sets of GNU_NEW_TYPE and GNU_OLD_TYPE according to OP. If this is a multi-dimensional array type, do this recursively. @@ -3357,7 +3384,7 @@ gnat_types_compatible_p (tree t1, tree t2) return 1; /* Array types are also compatible if they are constrained and have the same - domain(s) and the same component type. */ + domain(s), the same component type and the same scalar storage order. */ if (code == ARRAY_TYPE && (TYPE_DOMAIN (t1) == TYPE_DOMAIN (t2) || (TYPE_DOMAIN (t1) @@ -3368,7 +3395,8 @@ gnat_types_compatible_p (tree t1, tree t2) TYPE_MAX_VALUE (TYPE_DOMAIN (t2))))) && (TREE_TYPE (t1) == TREE_TYPE (t2) || (TREE_CODE (TREE_TYPE (t1)) == ARRAY_TYPE - && gnat_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))))) + && gnat_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))) + && TYPE_REVERSE_STORAGE_ORDER (t1) == TYPE_REVERSE_STORAGE_ORDER (t2)) return 1; return 0; @@ -4849,17 +4877,38 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) } /* If we are converting to an integral type whose precision is not equal - to its size, first unchecked convert to a record type that contains an - field of the given precision. Then extract the field. */ + to its size, first unchecked convert to a record type that contains a + field of the given precision. Then extract the result from the field. + + There is a subtlety if the source type is an aggregate type with reverse + storage order because its representation is not contiguous in the native + storage order, i.e. a direct unchecked conversion to an integral type + with N bits of precision cannot read the first N bits of the aggregate + type. To overcome it, we do an unchecked conversion to an integral type + with reverse storage order and return the resulting value. This also + ensures that the result of the unchecked conversion doesn't depend on + the endianness of the target machine, but only on the storage order of + the aggregate type. + + Finally, for the sake of consistency, we do the unchecked conversion + to an integral type with reverse storage order as soon as the source + type is an aggregate type with reverse storage order, even if there + are no considerations of precision or size involved. */ else if (INTEGRAL_TYPE_P (type) && TYPE_RM_SIZE (type) - && 0 != compare_tree_int (TYPE_RM_SIZE (type), - GET_MODE_BITSIZE (TYPE_MODE (type)))) + && (0 != compare_tree_int (TYPE_RM_SIZE (type), + GET_MODE_BITSIZE (TYPE_MODE (type))) + || (AGGREGATE_TYPE_P (etype) + && TYPE_REVERSE_STORAGE_ORDER (etype)))) { tree rec_type = make_node (RECORD_TYPE); unsigned HOST_WIDE_INT prec = TREE_INT_CST_LOW (TYPE_RM_SIZE (type)); tree field_type, field; + if (AGGREGATE_TYPE_P (etype)) + TYPE_REVERSE_STORAGE_ORDER (rec_type) + = TYPE_REVERSE_STORAGE_ORDER (etype); + if (TYPE_UNSIGNED (type)) field_type = make_unsigned_type (prec); else @@ -4878,11 +4927,16 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) /* Similarly if we are converting from an integral type whose precision is not equal to its size, first copy into a field of the given precision - and unchecked convert the record type. */ + and unchecked convert the record type. + + The same considerations as above apply if the target type is an aggregate + type with reverse storage order and we also proceed similarly. */ else if (INTEGRAL_TYPE_P (etype) && TYPE_RM_SIZE (etype) - && 0 != compare_tree_int (TYPE_RM_SIZE (etype), - GET_MODE_BITSIZE (TYPE_MODE (etype)))) + && (0 != compare_tree_int (TYPE_RM_SIZE (etype), + GET_MODE_BITSIZE (TYPE_MODE (etype))) + || (AGGREGATE_TYPE_P (type) + && TYPE_REVERSE_STORAGE_ORDER (type)))) { tree rec_type = make_node (RECORD_TYPE); unsigned HOST_WIDE_INT prec = TREE_INT_CST_LOW (TYPE_RM_SIZE (etype)); @@ -4890,6 +4944,10 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) vec_alloc (v, 1); tree field_type, field; + if (AGGREGATE_TYPE_P (type)) + TYPE_REVERSE_STORAGE_ORDER (rec_type) + = TYPE_REVERSE_STORAGE_ORDER (type); + if (TYPE_UNSIGNED (etype)) field_type = make_unsigned_type (prec); else @@ -6040,7 +6098,6 @@ install_builtin_functions (void) BOTH_P, FALLBACK_P, NONANSI_P, \ built_in_attributes[(int) ATTRS], IMPLICIT); #include "builtins.def" -#undef DEF_BUILTIN } /* ----------------------------------------------------------------------- * diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c index 47446ba8969..73a9b10d26f 100644 --- a/gcc/ada/gcc-interface/utils2.c +++ b/gcc/ada/gcc-interface/utils2.c @@ -1408,11 +1408,11 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand) HOST_WIDE_INT bitpos; tree offset, inner; machine_mode mode; - int unsignedp, volatilep; + int unsignedp, reversep, volatilep; inner = get_inner_reference (operand, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, - false); + &mode, &unsignedp, &reversep, + &volatilep, false); /* If INNER is a padding type whose field has a self-referential size, convert to that inner type. We know the offset is zero @@ -1916,7 +1916,9 @@ gnat_build_constructor (tree type, vec *v) || (TREE_CODE (type) == RECORD_TYPE && CONSTRUCTOR_BITFIELD_P (obj) && !initializer_constant_valid_for_bitfield_p (val)) - || !initializer_constant_valid_p (val, TREE_TYPE (val))) + || !initializer_constant_valid_p (val, + TREE_TYPE (val), + TYPE_REVERSE_STORAGE_ORDER (type))) allconstant = false; if (!TREE_READONLY (val)) @@ -2749,6 +2751,7 @@ gnat_rewrite_reference (tree ref, rewrite_fn func, void *data, tree *init) gnat_rewrite_reference (TREE_OPERAND (ref, 0), func, data, init), TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2)); + REF_REVERSE_STORAGE_ORDER (result) = REF_REVERSE_STORAGE_ORDER (ref); break; case ARRAY_REF: diff --git a/gcc/alloc-pool.h b/gcc/alloc-pool.h index 0dc05cdb719..bf9b0ebd6ee 100644 --- a/gcc/alloc-pool.h +++ b/gcc/alloc-pool.h @@ -480,7 +480,7 @@ public: inline T * allocate () ATTRIBUTE_MALLOC { - return ::new (m_allocator.allocate ()) T (); + return ::new (m_allocator.allocate ()) T; } inline void diff --git a/gcc/asan.c b/gcc/asan.c index 869a0002f1e..0df5e3234b5 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -1779,9 +1779,9 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t, HOST_WIDE_INT bitsize, bitpos; tree offset; machine_mode mode; - int volatilep = 0, unsignedp = 0; - tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + int unsignedp, reversep, volatilep = 0; + tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode, + &unsignedp, &reversep, &volatilep, false); if (TREE_CODE (t) == COMPONENT_REF && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE) diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index 5f1c2ccc6cb..950b1a1089d 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -2304,7 +2304,9 @@ reorder_basic_blocks_simple (void) if (JUMP_P (end) && extract_asm_operands (end)) continue; - if (any_condjump_p (end)) + if (single_succ_p (bb)) + edges[n++] = EDGE_SUCC (bb, 0); + else if (any_condjump_p (end)) { edge e0 = EDGE_SUCC (bb, 0); edge e1 = EDGE_SUCC (bb, 1); @@ -2315,8 +2317,6 @@ reorder_basic_blocks_simple (void) edges[n++] = e0; edges[n++] = e1; } - else if (single_succ_p (bb)) - edges[n++] = EDGE_SUCC (bb, 0); } /* Sort the edges, the most desirable first. When optimizing for size diff --git a/gcc/builtins.c b/gcc/builtins.c index 8f0717c7e1b..85b251ae092 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -78,7 +78,6 @@ const char * built_in_names[(int) END_BUILTINS] = { #include "builtins.def" }; -#undef DEF_BUILTIN /* Setup an array of builtin_info_type, make sure each element decl is initialized to NULL_TREE. */ @@ -143,12 +142,10 @@ static tree fold_builtin_constant_p (tree); static tree fold_builtin_classify_type (tree); static tree fold_builtin_strlen (location_t, tree, tree); static tree fold_builtin_inf (location_t, tree, int); -static tree fold_builtin_nan (tree, tree, int); static tree rewrite_call_expr (location_t, tree, int, tree, int, ...); static bool validate_arg (const_tree, enum tree_code code); static rtx expand_builtin_fabs (tree, rtx, rtx); static rtx expand_builtin_signbit (tree, rtx); -static tree fold_builtin_bitop (tree, tree); static tree fold_builtin_strchr (location_t, tree, tree, tree); static tree fold_builtin_memchr (location_t, tree, tree, tree, tree); static tree fold_builtin_memcmp (location_t, tree, tree, tree); @@ -255,14 +252,14 @@ get_object_alignment_2 (tree exp, unsigned int *alignp, HOST_WIDE_INT bitsize, bitpos; tree offset; machine_mode mode; - int unsignedp, volatilep; + int unsignedp, reversep, volatilep; unsigned int align = BITS_PER_UNIT; bool known_alignment = false; /* Get the innermost object and the constant (bitpos) and possibly variable (offset) offset of the access. */ - exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, true); + exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode, + &unsignedp, &reversep, &volatilep, true); /* Extract alignment information from the innermost object and possibly adjust bitpos and offset. */ @@ -616,27 +613,6 @@ c_strlen (tree src, int only_value) return ssize_int (strlen (ptr + offset)); } -/* Return a char pointer for a C string if it is a string constant - or sum of string constant and integer constant. */ - -const char * -c_getstr (tree src) -{ - tree offset_node; - - src = string_constant (src, &offset_node); - if (src == 0) - return 0; - - if (offset_node == 0) - return TREE_STRING_POINTER (src); - else if (!tree_fits_uhwi_p (offset_node) - || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0) - return 0; - - return TREE_STRING_POINTER (src) + tree_to_uhwi (offset_node); -} - /* Return a constant integer corresponding to target reading GET_MODE_BITSIZE (MODE) bits from string constant STR. */ @@ -7286,26 +7262,6 @@ fold_builtin_inf (location_t loc, tree type, int warn) return build_real (type, real); } -/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */ - -static tree -fold_builtin_nan (tree arg, tree type, int quiet) -{ - REAL_VALUE_TYPE real; - const char *str; - - if (!validate_arg (arg, POINTER_TYPE)) - return NULL_TREE; - str = c_getstr (arg); - if (!str) - return NULL_TREE; - - if (!real_nan (&real, str, quiet, TYPE_MODE (type))) - return NULL_TREE; - - return build_real (type, real); -} - /* Fold function call to builtin sincos, sincosf, or sincosl. Return NULL_TREE if no simplification can be made. */ @@ -7353,99 +7309,6 @@ fold_builtin_sincos (location_t loc, fold_build1_loc (loc, REALPART_EXPR, type, call))); } -/* Fold function call to builtin ffs, clz, ctz, popcount and parity - and their long and long long variants (i.e. ffsl and ffsll). ARG is - the argument to the call. Return NULL_TREE if no simplification can - be made. */ - -static tree -fold_builtin_bitop (tree fndecl, tree arg) -{ - if (!validate_arg (arg, INTEGER_TYPE)) - return NULL_TREE; - - /* Optimize for constant argument. */ - if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg)) - { - tree type = TREE_TYPE (arg); - int result; - - switch (DECL_FUNCTION_CODE (fndecl)) - { - CASE_INT_FN (BUILT_IN_FFS): - result = wi::ffs (arg); - break; - - CASE_INT_FN (BUILT_IN_CLZ): - if (wi::ne_p (arg, 0)) - result = wi::clz (arg); - else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result)) - result = TYPE_PRECISION (type); - break; - - CASE_INT_FN (BUILT_IN_CTZ): - if (wi::ne_p (arg, 0)) - result = wi::ctz (arg); - else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result)) - result = TYPE_PRECISION (type); - break; - - CASE_INT_FN (BUILT_IN_CLRSB): - result = wi::clrsb (arg); - break; - - CASE_INT_FN (BUILT_IN_POPCOUNT): - result = wi::popcount (arg); - break; - - CASE_INT_FN (BUILT_IN_PARITY): - result = wi::parity (arg); - break; - - default: - gcc_unreachable (); - } - - return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result); - } - - return NULL_TREE; -} - -/* Fold function call to builtin_bswap and the short, long and long long - variants. Return NULL_TREE if no simplification can be made. */ -static tree -fold_builtin_bswap (tree fndecl, tree arg) -{ - if (! validate_arg (arg, INTEGER_TYPE)) - return NULL_TREE; - - /* Optimize constant value. */ - if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg)) - { - tree type = TREE_TYPE (TREE_TYPE (fndecl)); - - switch (DECL_FUNCTION_CODE (fndecl)) - { - case BUILT_IN_BSWAP16: - case BUILT_IN_BSWAP32: - case BUILT_IN_BSWAP64: - { - signop sgn = TYPE_SIGN (type); - tree result = - wide_int_to_tree (type, - wide_int::from (arg, TYPE_PRECISION (type), - sgn).bswap ()); - return result; - } - default: - gcc_unreachable (); - } - } - - return NULL_TREE; -} - /* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the arguments to the call, and TYPE is its return type. Return NULL_TREE if no simplification can be made. */ @@ -7493,8 +7356,6 @@ fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type) static tree fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len) { - const char *p1, *p2; - if (!validate_arg (arg1, POINTER_TYPE) || !validate_arg (arg2, POINTER_TYPE) || !validate_arg (len, INTEGER_TYPE)) @@ -7509,25 +7370,6 @@ fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len) if (operand_equal_p (arg1, arg2, 0)) return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len); - p1 = c_getstr (arg1); - p2 = c_getstr (arg2); - - /* If all arguments are constant, and the value of len is not greater - than the lengths of arg1 and arg2, evaluate at compile-time. */ - if (tree_fits_uhwi_p (len) && p1 && p2 - && compare_tree_int (len, strlen (p1) + 1) <= 0 - && compare_tree_int (len, strlen (p2) + 1) <= 0) - { - const int r = memcmp (p1, p2, tree_to_uhwi (len)); - - if (r > 0) - return integer_one_node; - else if (r < 0) - return integer_minus_one_node; - else - return integer_zero_node; - } - /* If len parameter is one, return an expression corresponding to (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */ if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1) @@ -7560,8 +7402,6 @@ fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len) static tree fold_builtin_strcmp (location_t loc, tree arg1, tree arg2) { - const char *p1, *p2; - if (!validate_arg (arg1, POINTER_TYPE) || !validate_arg (arg2, POINTER_TYPE)) return NULL_TREE; @@ -7570,21 +7410,8 @@ fold_builtin_strcmp (location_t loc, tree arg1, tree arg2) if (operand_equal_p (arg1, arg2, 0)) return integer_zero_node; - p1 = c_getstr (arg1); - p2 = c_getstr (arg2); - - if (p1 && p2) - { - const int i = strcmp (p1, p2); - if (i < 0) - return integer_minus_one_node; - else if (i > 0) - return integer_one_node; - else - return integer_zero_node; - } - /* If the second arg is "", return *(const unsigned char*)arg1. */ + const char *p2 = c_getstr (arg2); if (p2 && *p2 == '\0') { tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); @@ -7599,6 +7426,7 @@ fold_builtin_strcmp (location_t loc, tree arg1, tree arg2) } /* If the first arg is "", return -*(const unsigned char*)arg2. */ + const char *p1 = c_getstr (arg1); if (p1 && *p1 == '\0') { tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); @@ -7623,8 +7451,6 @@ fold_builtin_strcmp (location_t loc, tree arg1, tree arg2) static tree fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len) { - const char *p1, *p2; - if (!validate_arg (arg1, POINTER_TYPE) || !validate_arg (arg2, POINTER_TYPE) || !validate_arg (len, INTEGER_TYPE)) @@ -7639,22 +7465,9 @@ fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len) if (operand_equal_p (arg1, arg2, 0)) return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len); - p1 = c_getstr (arg1); - p2 = c_getstr (arg2); - - if (tree_fits_uhwi_p (len) && p1 && p2) - { - const int i = strncmp (p1, p2, tree_to_uhwi (len)); - if (i > 0) - return integer_one_node; - else if (i < 0) - return integer_minus_one_node; - else - return integer_zero_node; - } - /* If the second arg is "", and the length is greater than zero, return *(const unsigned char*)arg1. */ + const char *p2 = c_getstr (arg2); if (p2 && *p2 == '\0' && TREE_CODE (len) == INTEGER_CST && tree_int_cst_sgn (len) == 1) @@ -7672,6 +7485,7 @@ fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len) /* If the first arg is "", and the length is greater than zero, return -*(const unsigned char*)arg2. */ + const char *p1 = c_getstr (arg1); if (p1 && *p1 == '\0' && TREE_CODE (len) == INTEGER_CST && tree_int_cst_sgn (len) == 1) @@ -8039,7 +7853,6 @@ static tree fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index) { tree type = TREE_TYPE (TREE_TYPE (fndecl)); - REAL_VALUE_TYPE r; if (!validate_arg (arg, REAL_TYPE)) return NULL_TREE; @@ -8050,16 +7863,6 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index) if (!HONOR_INFINITIES (arg)) return omit_one_operand_loc (loc, type, integer_zero_node, arg); - if (TREE_CODE (arg) == REAL_CST) - { - r = TREE_REAL_CST (arg); - if (real_isinf (&r)) - return real_compare (GT_EXPR, &r, &dconst0) - ? integer_one_node : integer_minus_one_node; - else - return integer_zero_node; - } - return NULL_TREE; case BUILT_IN_ISINF_SIGN: @@ -8099,24 +7902,12 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index) && !HONOR_INFINITIES (arg)) return omit_one_operand_loc (loc, type, integer_one_node, arg); - if (TREE_CODE (arg) == REAL_CST) - { - r = TREE_REAL_CST (arg); - return real_isfinite (&r) ? integer_one_node : integer_zero_node; - } - return NULL_TREE; case BUILT_IN_ISNAN: if (!HONOR_NANS (arg)) return omit_one_operand_loc (loc, type, integer_zero_node, arg); - if (TREE_CODE (arg) == REAL_CST) - { - r = TREE_REAL_CST (arg); - return real_isnan (&r) ? integer_one_node : integer_zero_node; - } - arg = builtin_save_expr (arg); return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg); @@ -8399,28 +8190,6 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0) CASE_FLT_FN (BUILT_IN_CARG): return fold_builtin_carg (loc, arg0, type); - CASE_FLT_FN (BUILT_IN_NAN): - case BUILT_IN_NAND32: - case BUILT_IN_NAND64: - case BUILT_IN_NAND128: - return fold_builtin_nan (arg0, type, true); - - CASE_FLT_FN (BUILT_IN_NANS): - return fold_builtin_nan (arg0, type, false); - - case BUILT_IN_BSWAP16: - case BUILT_IN_BSWAP32: - case BUILT_IN_BSWAP64: - return fold_builtin_bswap (fndecl, arg0); - - CASE_INT_FN (BUILT_IN_FFS): - CASE_INT_FN (BUILT_IN_CLZ): - CASE_INT_FN (BUILT_IN_CTZ): - CASE_INT_FN (BUILT_IN_CLRSB): - CASE_INT_FN (BUILT_IN_POPCOUNT): - CASE_INT_FN (BUILT_IN_PARITY): - return fold_builtin_bitop (fndecl, arg0); - case BUILT_IN_ISASCII: return fold_builtin_isascii (loc, arg0); @@ -9226,13 +8995,6 @@ fold_builtin_strspn (location_t loc, tree s1, tree s2) { const char *p1 = c_getstr (s1), *p2 = c_getstr (s2); - /* If both arguments are constants, evaluate at compile-time. */ - if (p1 && p2) - { - const size_t r = strspn (p1, p2); - return build_int_cst (size_type_node, r); - } - /* If either argument is "", return NULL_TREE. */ if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')) /* Evaluate and ignore both arguments in case either one has @@ -9269,16 +9031,8 @@ fold_builtin_strcspn (location_t loc, tree s1, tree s2) return NULL_TREE; else { - const char *p1 = c_getstr (s1), *p2 = c_getstr (s2); - - /* If both arguments are constants, evaluate at compile-time. */ - if (p1 && p2) - { - const size_t r = strcspn (p1, p2); - return build_int_cst (size_type_node, r); - } - /* If the first argument is "", return NULL_TREE. */ + const char *p1 = c_getstr (s1); if (p1 && *p1 == '\0') { /* Evaluate and ignore argument s2 in case it has @@ -9288,6 +9042,7 @@ fold_builtin_strcspn (location_t loc, tree s1, tree s2) } /* If the second argument is "", return __builtin_strlen(s1). */ + const char *p2 = c_getstr (s2); if (p2 && *p2 == '\0') { tree fn = builtin_decl_implicit (BUILT_IN_STRLEN); diff --git a/gcc/builtins.def b/gcc/builtins.def index 886b45ccec3..ed850df2d01 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -475,9 +475,9 @@ DEF_C99_BUILTIN (BUILT_IN_REMAINDERL, "remainderl", BT_FN_LONGDOUBLE_LONG DEF_C99_BUILTIN (BUILT_IN_REMQUO, "remquo", BT_FN_DOUBLE_DOUBLE_DOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE) DEF_C99_BUILTIN (BUILT_IN_REMQUOF, "remquof", BT_FN_FLOAT_FLOAT_FLOAT_INTPTR, ATTR_MATHFN_FPROUNDING_STORE) DEF_C99_BUILTIN (BUILT_IN_REMQUOL, "remquol", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE) -DEF_C99_BUILTIN (BUILT_IN_RINT, "rint", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) -DEF_C99_BUILTIN (BUILT_IN_RINTF, "rintf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) -DEF_C99_BUILTIN (BUILT_IN_RINTL, "rintl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_C99_BUILTIN (BUILT_IN_RINT, "rint", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_C99_BUILTIN (BUILT_IN_RINTF, "rintf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING) +DEF_C99_BUILTIN (BUILT_IN_RINTL, "rintl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_ROUND, "round", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN_ROUNDF, "roundf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN_ROUNDL, "roundl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) @@ -945,3 +945,6 @@ DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, ATTR_NOTHROW_LEAF_LIST) /* Pointer Bounds Checker builtins. */ #include "chkp-builtins.def" + +#undef DEF_BUILTIN_CHKP +#undef DEF_BUILTIN diff --git a/gcc/builtins.h b/gcc/builtins.h index cce9e7507a2..b0396322fa0 100644 --- a/gcc/builtins.h +++ b/gcc/builtins.h @@ -87,7 +87,6 @@ extern bool is_simple_builtin (tree); extern bool is_inexpensive_builtin (tree); extern bool readonly_data_expr (tree exp); -extern const char *c_getstr (tree); extern bool init_target_chars (void); extern unsigned HOST_WIDE_INT target_newline; extern unsigned HOST_WIDE_INT target_percent; diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index cc9a6420407..f52b3e354c5 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,33 @@ +2015-11-08 Eric Botcazou + + * c-common.c (c_common_attributes): Add scalar_storage_order. + (handle_scalar_storage_order_attribute): New function. + * c-pragma.c (global_sso): New variable. + (maybe_apply_pragma_scalar_storage_order): New function. + (handle_pragma_scalar_storage_order): Likewise. + (init_pragma): Register scalar_storage_order. + * c-pragma.h (maybe_apply_pragma_scalar_storage_order): Declare. + * c.opt (Wscalar-storage-order): New warning. + (fsso-struct=): New option. + +2015-11-08 Martin Sebor + + * c.opt (Wplacement-new): Add a period to the end of a sentence. + +2015-11-07 Richard Sandiford + + * c-common.c: Don't undef DEF_BUILTIN. + +2015-11-06 David Malcolm + + * c-common.c (c_cpp_error): Convert parameter from location_t to + rich_location *. Eliminate the "column_override" parameter and + the call to diagnostic_override_column. + Update the "done_lexing" clause to set range 0 + on the rich_location, rather than overwriting a location_t. + * c-common.h (c_cpp_error): Convert parameter from location_t to + rich_location *. Eliminate the "column_override" parameter. + 2015-11-05 Cesar Philippidis Thomas Schwinge James Norris diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index de5f8b6cbdf..53c1d81c0c8 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -339,6 +339,8 @@ static tree handle_no_reorder_attribute (tree *, tree, tree, int, static tree handle_const_attribute (tree *, tree, tree, int, bool *); static tree handle_transparent_union_attribute (tree *, tree, tree, int, bool *); +static tree handle_scalar_storage_order_attribute (tree *, tree, tree, + int, bool *); static tree handle_constructor_attribute (tree *, tree, tree, int, bool *); static tree handle_destructor_attribute (tree *, tree, tree, int, bool *); static tree handle_mode_attribute (tree *, tree, tree, int, bool *); @@ -693,6 +695,8 @@ const struct attribute_spec c_common_attribute_table[] = /* The same comments as for noreturn attributes apply to const ones. */ { "const", 0, 0, true, false, false, handle_const_attribute, false }, + { "scalar_storage_order", 1, 1, false, false, false, + handle_scalar_storage_order_attribute, false }, { "transparent_union", 0, 0, false, false, false, handle_transparent_union_attribute, false }, { "constructor", 0, 1, true, false, false, @@ -5735,7 +5739,6 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node) BOTH_P, FALLBACK_P, NONANSI_P, \ built_in_attributes[(int) ATTRS], IMPLICIT); #include "builtins.def" -#undef DEF_BUILTIN targetm.init_builtins (); @@ -7669,6 +7672,62 @@ handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args), return NULL_TREE; } +/* Handle a "scalar_storage_order" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_scalar_storage_order_attribute (tree *node, tree name, tree args, + int flags, bool *no_add_attrs) +{ + tree id = TREE_VALUE (args); + tree type; + + if (TREE_CODE (*node) == TYPE_DECL + && ! (flags & ATTR_FLAG_CXX11)) + node = &TREE_TYPE (*node); + type = *node; + + if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN) + { + error ("scalar_storage_order is not supported because endianness " + "is not uniform"); + return NULL_TREE; + } + + if (RECORD_OR_UNION_TYPE_P (type) && !c_dialect_cxx ()) + { + bool reverse = false; + + if (TREE_CODE (id) == STRING_CST + && strcmp (TREE_STRING_POINTER (id), "big-endian") == 0) + reverse = !BYTES_BIG_ENDIAN; + else if (TREE_CODE (id) == STRING_CST + && strcmp (TREE_STRING_POINTER (id), "little-endian") == 0) + reverse = BYTES_BIG_ENDIAN; + else + { + error ("scalar_storage_order argument must be one of \"big-endian\"" + " or \"little-endian\""); + return NULL_TREE; + } + + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + { + if (reverse) + /* A type variant isn't good enough, since we don't want a cast + to such a type to be removed as a no-op. */ + *node = type = build_duplicate_type (type); + } + + TYPE_REVERSE_STORAGE_ORDER (type) = reverse; + return NULL_TREE; + } + + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + return NULL_TREE; +} + /* Handle a "transparent_union" attribute; arguments as in struct attribute_spec.handler. */ @@ -7681,7 +7740,6 @@ handle_transparent_union_attribute (tree *node, tree name, *no_add_attrs = true; - if (TREE_CODE (*node) == TYPE_DECL && ! (flags & ATTR_FLAG_CXX11)) node = &TREE_TYPE (*node); @@ -7712,8 +7770,8 @@ handle_transparent_union_attribute (tree *node, tree name, if (c_dialect_cxx ()) goto ignored; - /* A type variant isn't good enough, since we don't a cast - to such a type removed as a no-op. */ + /* A type variant isn't good enough, since we don't want a cast + to such a type to be removed as a no-op. */ *node = type = build_duplicate_type (type); } @@ -10543,15 +10601,14 @@ c_option_controlling_cpp_error (int reason) /* Callback from cpp_error for PFILE to print diagnostics from the preprocessor. The diagnostic is of type LEVEL, with REASON set to the reason code if LEVEL is represents a warning, at location - LOCATION unless this is after lexing and the compiler's location - should be used instead, with column number possibly overridden by - COLUMN_OVERRIDE if not zero; MSG is the translated message and AP + RICHLOC unless this is after lexing and the compiler's location + should be used instead; MSG is the translated message and AP the arguments. Returns true if a diagnostic was emitted, false otherwise. */ bool c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason, - location_t location, unsigned int column_override, + rich_location *richloc, const char *msg, va_list *ap) { diagnostic_info diagnostic; @@ -10592,11 +10649,11 @@ c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason, gcc_unreachable (); } if (done_lexing) - location = input_location; + richloc->set_range (0, + source_range::from_location (input_location), + true, true); diagnostic_set_info_translated (&diagnostic, msg, ap, - location, dlevel); - if (column_override) - diagnostic_override_column (&diagnostic, column_override); + richloc, dlevel); diagnostic_override_option_index (&diagnostic, c_option_controlling_cpp_error (reason)); ret = report_diagnostic (&diagnostic); diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index de9768e9214..c82545405e4 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -995,9 +995,9 @@ extern void init_c_lex (void); extern void c_cpp_builtins (cpp_reader *); extern void c_cpp_builtins_optimize_pragma (cpp_reader *, tree, tree); -extern bool c_cpp_error (cpp_reader *, int, int, location_t, unsigned int, +extern bool c_cpp_error (cpp_reader *, int, int, rich_location *, const char *, va_list *) - ATTRIBUTE_GCC_DIAG(6,0); + ATTRIBUTE_GCC_DIAG(5,0); extern int c_common_has_attribute (cpp_reader *); extern bool parse_optimize_options (tree, bool); diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index ac118382816..ffc5b33a4cd 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -388,6 +388,51 @@ handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy)) } } +static enum scalar_storage_order_kind global_sso; + +void +maybe_apply_pragma_scalar_storage_order (tree type) +{ + if (global_sso == SSO_NATIVE) + return; + + gcc_assert (RECORD_OR_UNION_TYPE_P (type)); + + if (lookup_attribute ("scalar_storage_order", TYPE_ATTRIBUTES (type))) + return; + + if (global_sso == SSO_BIG_ENDIAN) + TYPE_REVERSE_STORAGE_ORDER (type) = !BYTES_BIG_ENDIAN; + else if (global_sso == SSO_LITTLE_ENDIAN) + TYPE_REVERSE_STORAGE_ORDER (type) = BYTES_BIG_ENDIAN; + else + gcc_unreachable (); +} + +static void +handle_pragma_scalar_storage_order (cpp_reader *ARG_UNUSED(dummy)) +{ + const char *kind_string; + enum cpp_ttype token; + tree x; + + if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN) + error ("scalar_storage_order is not supported"); + + token = pragma_lex (&x); + if (token != CPP_NAME) + GCC_BAD ("missing [big-endian|little-endian|default] after %<#pragma scalar_storage_order%>"); + kind_string = IDENTIFIER_POINTER (x); + if (strcmp (kind_string, "default") == 0) + global_sso = default_sso; + else if (strcmp (kind_string, "big") == 0) + global_sso = SSO_BIG_ENDIAN; + else if (strcmp (kind_string, "little") == 0) + global_sso = SSO_LITTLE_ENDIAN; + else + GCC_BAD ("expected [big-endian|little-endian|default] after %<#pragma scalar_storage_order%>"); +} + /* GCC supports two #pragma directives for renaming the external symbol associated with a declaration (DECL_ASSEMBLER_NAME), for compatibility with the Solaris and VMS system headers. GCC also @@ -1481,6 +1526,7 @@ init_pragma (void) c_register_pragma (0, "pack", handle_pragma_pack); #endif c_register_pragma (0, "weak", handle_pragma_weak); + c_register_pragma ("GCC", "visibility", handle_pragma_visibility); c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic); @@ -1502,6 +1548,10 @@ init_pragma (void) REGISTER_TARGET_PRAGMAS (); #endif + global_sso = default_sso; + c_register_pragma (0, "scalar_storage_order", + handle_pragma_scalar_storage_order); + /* Allow plugins to register their own pragmas. */ invoke_plugin_callbacks (PLUGIN_PRAGMAS, NULL); } diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 953c4e31d04..59231ce030e 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -227,6 +227,7 @@ extern void c_invoke_pragma_handler (unsigned int); extern void maybe_apply_pragma_weak (tree); extern void maybe_apply_pending_pragma_weaks (void); extern tree maybe_apply_renaming_pragma (tree, tree); +extern void maybe_apply_pragma_scalar_storage_order (tree); extern void add_to_renaming_pragma_list (tree, tree); extern enum cpp_ttype pragma_lex (tree *, location_t *loc = NULL); diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 5f38018d35e..aafd80207b1 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -778,7 +778,7 @@ Warn if inherited methods are unimplemented. Wplacement-new C++ Var(warn_placement_new) Init(1) Warning -Warn for placement new expressions with undefined behavior +Warn for placement new expressions with undefined behavior. Wredundant-decls C ObjC C++ ObjC++ Var(warn_redundant_decls) Warning @@ -792,6 +792,10 @@ Wreturn-type C ObjC C++ ObjC++ Var(warn_return_type) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Warn whenever a function's return type defaults to \"int\" (C), or about inconsistent return types (C++). +Wscalar-storage-order +C ObjC C++ ObjC++ Init(1) Warning +Warn on suspicious constructs involving reverse scalar storage order. + Wselector ObjC ObjC++ Var(warn_selector) Warning Warn if a selector has multiple methods. @@ -1454,6 +1458,19 @@ Enable C++14 sized deallocation support. fsquangle C++ ObjC++ Ignore Warn(switch %qs is no longer supported) +fsso-struct= +C ObjC Joined Enum(sso_struct) Var(default_sso) Init(SSO_NATIVE) +-fsso-struct=[big-endian|little-endian] Set the default scalar storage order. + +Enum +Name(sso_struct) Type(enum scalar_storage_order_kind) UnknownError(unrecognized scalar storage order value %qs) + +EnumValue +Enum(sso_struct) String(big-endian) Value(SSO_BIG_ENDIAN) + +EnumValue +Enum(sso_struct) String(little-endian) Value(SSO_LITTLE_ENDIAN) + fstats C++ ObjC++ Var(flag_detailed_statistics) Display statistics accumulated during compilation. diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index c734a81f45c..6fea3a996e9 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,23 @@ +2015-11-08 Eric Botcazou + + * c-decl.c (finish_struct): If the structure has reverse storage + order, rewrite the type of array fields with scalar component. Call + maybe_apply_pragma_scalar_storage_order on entry. + * c-typeck.c (build_unary_op) : Remove left-overs. Issue + errors on bit-fields and reverse SSO here and not... + (c_mark_addressable): ...here. + (output_init_element): Adjust call to initializer_constant_valid_p. + (c_build_qualified_type): Propagate TYPE_REVERSE_STORAGE_ORDER. + +2015-11-06 David Malcolm + + * c-decl.c (warn_defaults_to): Update for change in signature + of diagnostic_set_info. + * c-errors.c (pedwarn_c99): Likewise. + (pedwarn_c90): Likewise. + * c-objc-common.c (c_tree_printer): Update for new "caret_p" param + for textinfo::set_location. + 2015-11-05 Cesar Philippidis Thomas Schwinge James Norris diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 8e355bae637..a3d8eada928 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -5285,9 +5285,10 @@ warn_defaults_to (location_t location, int opt, const char *gmsgid, ...) { diagnostic_info diagnostic; va_list ap; + rich_location richloc (location); va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, flag_isoc99 ? DK_PEDWARN : DK_WARNING); diagnostic.option_index = opt; report_diagnostic (&diagnostic); @@ -7723,6 +7724,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, TYPE_FIELDS (t) = fieldlist; + maybe_apply_pragma_scalar_storage_order (t); + layout_type (t); if (TYPE_SIZE_UNIT (t) @@ -7731,27 +7734,45 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, && !valid_constant_size_p (TYPE_SIZE_UNIT (t))) error ("type %qT is too large", t); - /* Give bit-fields their proper types. */ - { - tree *fieldlistp = &fieldlist; - while (*fieldlistp) - if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp) - && TREE_TYPE (*fieldlistp) != error_mark_node) + /* Give bit-fields their proper types and rewrite the type of array fields + with scalar component if the enclosing type has reverse storage order. */ + for (tree field = fieldlist; field; field = DECL_CHAIN (field)) + { + if (TREE_CODE (field) == FIELD_DECL + && DECL_INITIAL (field) + && TREE_TYPE (field) != error_mark_node) { unsigned HOST_WIDE_INT width - = tree_to_uhwi (DECL_INITIAL (*fieldlistp)); - tree type = TREE_TYPE (*fieldlistp); + = tree_to_uhwi (DECL_INITIAL (field)); + tree type = TREE_TYPE (field); if (width != TYPE_PRECISION (type)) { - TREE_TYPE (*fieldlistp) + TREE_TYPE (field) = c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type)); - DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp)); + DECL_MODE (field) = TYPE_MODE (TREE_TYPE (field)); } - DECL_INITIAL (*fieldlistp) = 0; + DECL_INITIAL (field) = 0; } - else - fieldlistp = &DECL_CHAIN (*fieldlistp); - } + else if (TYPE_REVERSE_STORAGE_ORDER (t) + && TREE_CODE (field) == FIELD_DECL + && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE) + { + tree ftype = TREE_TYPE (field); + tree ctype = strip_array_types (ftype); + if (!RECORD_OR_UNION_TYPE_P (ctype) && TYPE_MODE (ctype) != QImode) + { + tree fmain_type = TYPE_MAIN_VARIANT (ftype); + tree *typep = &fmain_type; + do { + *typep = build_distinct_type_copy (*typep); + TYPE_REVERSE_STORAGE_ORDER (*typep) = 1; + typep = &TREE_TYPE (*typep); + } while (TREE_CODE (*typep) == ARRAY_TYPE); + TREE_TYPE (field) + = c_build_qualified_type (fmain_type, TYPE_QUALS (ftype)); + } + } + } /* Now we have the truly final field list. Store it in this type and in the variants. */ diff --git a/gcc/c/c-errors.c b/gcc/c/c-errors.c index d9176ec0f11..b458957474d 100644 --- a/gcc/c/c-errors.c +++ b/gcc/c/c-errors.c @@ -41,13 +41,14 @@ pedwarn_c99 (location_t location, int opt, const char *gmsgid, ...) diagnostic_info diagnostic; va_list ap; bool warned = false; + rich_location richloc (location); va_start (ap, gmsgid); /* If desired, issue the C99/C11 compat warning, which is more specific than -pedantic. */ if (warn_c99_c11_compat > 0) { - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, (pedantic && !flag_isoc11) ? DK_PEDWARN : DK_WARNING); diagnostic.option_index = OPT_Wc99_c11_compat; @@ -59,7 +60,7 @@ pedwarn_c99 (location_t location, int opt, const char *gmsgid, ...) /* For -pedantic outside C11, issue a pedwarn. */ else if (pedantic && !flag_isoc11) { - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_PEDWARN); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN); diagnostic.option_index = opt; warned = report_diagnostic (&diagnostic); } @@ -79,6 +80,7 @@ pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...) { diagnostic_info diagnostic; va_list ap; + rich_location richloc (location); va_start (ap, gmsgid); /* Warnings such as -Wvla are the most specific ones. */ @@ -89,7 +91,7 @@ pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...) goto out; else if (opt_var > 0) { - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, (pedantic && !flag_isoc99) ? DK_PEDWARN : DK_WARNING); diagnostic.option_index = opt; @@ -101,7 +103,7 @@ pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...) specific than -pedantic. */ if (warn_c90_c99_compat > 0) { - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, (pedantic && !flag_isoc99) ? DK_PEDWARN : DK_WARNING); diagnostic.option_index = OPT_Wc90_c99_compat; @@ -113,7 +115,7 @@ pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...) /* For -pedantic outside C99, issue a pedwarn. */ else if (pedantic && !flag_isoc99) { - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_PEDWARN); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN); diagnostic.option_index = opt; report_diagnostic (&diagnostic); } diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c index ac61191c511..270b03da5ca 100644 --- a/gcc/c/c-objc-common.c +++ b/gcc/c/c-objc-common.c @@ -100,7 +100,7 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec, { t = va_arg (*text->args_ptr, tree); if (set_locus) - text->set_location (0, DECL_SOURCE_LOCATION (t)); + text->set_location (0, DECL_SOURCE_LOCATION (t), true); } switch (*spec) diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 33f5ead829f..2080db95ebc 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -4169,18 +4169,10 @@ build_unary_op (location_t location, goto return_build_unary_op; } - /* For &x[y], return x+y */ - if (TREE_CODE (arg) == ARRAY_REF) - { - tree op0 = TREE_OPERAND (arg, 0); - if (!c_mark_addressable (op0)) - return error_mark_node; - } - /* Anything not already handled and not a true memory reference or a non-lvalue array is an error. */ - else if (typecode != FUNCTION_TYPE && !flag - && !lvalue_or_else (location, arg, lv_addressof)) + if (typecode != FUNCTION_TYPE && !flag + && !lvalue_or_else (location, arg, lv_addressof)) return error_mark_node; /* Move address operations inside C_MAYBE_CONST_EXPR to simplify @@ -4218,6 +4210,39 @@ build_unary_op (location_t location, argtype = c_build_qualified_type (argtype, quals); } + switch (TREE_CODE (arg)) + { + case COMPONENT_REF: + if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) + { + error ("cannot take address of bit-field %qD", + TREE_OPERAND (arg, 1)); + return error_mark_node; + } + + /* ... fall through ... */ + + case ARRAY_REF: + if (TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (arg, 0)))) + { + if (!AGGREGATE_TYPE_P (TREE_TYPE (arg)) + && !VECTOR_TYPE_P (TREE_TYPE (arg))) + { + error ("cannot take address of scalar with reverse storage " + "order"); + return error_mark_node; + } + + if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE + && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (arg))) + warning (OPT_Wscalar_storage_order, "address of array with " + "reverse scalar storage order requested"); + } + + default: + break; + } + if (!c_mark_addressable (arg)) return error_mark_node; @@ -4360,15 +4385,6 @@ c_mark_addressable (tree exp) switch (TREE_CODE (x)) { case COMPONENT_REF: - if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1))) - { - error - ("cannot take address of bit-field %qD", TREE_OPERAND (x, 1)); - return false; - } - - /* ... fall through ... */ - case ADDR_EXPR: case ARRAY_REF: case REALPART_EXPR: @@ -8444,7 +8460,11 @@ output_init_element (location_t loc, tree value, tree origtype, constructor_erroneous = 1; else if (!TREE_CONSTANT (value)) constructor_constant = 0; - else if (!initializer_constant_valid_p (value, TREE_TYPE (value)) + else if (!initializer_constant_valid_p (value, + TREE_TYPE (value), + AGGREGATE_TYPE_P (constructor_type) + && TYPE_REVERSE_STORAGE_ORDER + (constructor_type)) || ((TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) && DECL_C_BIT_FIELD (field) @@ -13238,6 +13258,12 @@ c_build_qualified_type (tree type, int type_quals) = build_array_type (TYPE_CANONICAL (element_type), domain? TYPE_CANONICAL (domain) : NULL_TREE); + if (TYPE_REVERSE_STORAGE_ORDER (type)) + { + unqualified_canon + = build_distinct_type_copy (unqualified_canon); + TYPE_REVERSE_STORAGE_ORDER (unqualified_canon) = 1; + } TYPE_CANONICAL (t) = c_build_qualified_type (unqualified_canon, type_quals); } diff --git a/gcc/calls.c b/gcc/calls.c index 6db114ad32e..b56556a9d0a 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1065,7 +1065,7 @@ store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals) args[i].aligned_regs[j] = reg; word = extract_bit_field (word, bitsize, 0, 1, NULL_RTX, - word_mode, word_mode); + word_mode, word_mode, false); /* There is no need to restrict this code to loading items in TYPE_ALIGN sized hunks. The bitfield instructions can @@ -1082,7 +1082,7 @@ store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals) bytes -= bitsize / BITS_PER_UNIT; store_bit_field (reg, bitsize, endian_correction, 0, 0, - word_mode, word); + word_mode, word, false); } } } @@ -1363,7 +1363,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, else copy = assign_temp (type, 1, 0); - store_expr (args[i].tree_value, copy, 0, false); + store_expr (args[i].tree_value, copy, 0, false, false); /* Just change the const function to pure and then let the next test clear the pure based on @@ -2084,8 +2084,8 @@ load_register_parameters (struct arg_data *args, int num_actuals, rtx dest = gen_rtx_REG (word_mode, REGNO (reg) + nregs - 1); unsigned int bitoff = (nregs - 1) * BITS_PER_WORD; unsigned int bitsize = size * BITS_PER_UNIT - bitoff; - rtx x = extract_bit_field (mem, bitsize, bitoff, 1, - dest, word_mode, word_mode); + rtx x = extract_bit_field (mem, bitsize, bitoff, 1, dest, + word_mode, word_mode, false); if (BYTES_BIG_ENDIAN) x = expand_shift (LSHIFT_EXPR, word_mode, x, BITS_PER_WORD - bitsize, dest, 1); diff --git a/gcc/cfg-flags.def b/gcc/cfg-flags.def index eedcd692724..e2bfbed5ecf 100644 --- a/gcc/cfg-flags.def +++ b/gcc/cfg-flags.def @@ -78,7 +78,7 @@ DEF_BASIC_BLOCK_FLAG(RTL, 9) DEF_BASIC_BLOCK_FLAG(FORWARDER_BLOCK, 10) /* Set on blocks that cannot be threaded through. - Only used in cfgcleanup.c. */ + Only used for jump threading. */ DEF_BASIC_BLOCK_FLAG(NONTHREADABLE_BLOCK, 11) /* Set on blocks that were modified in some way. This bit is set in @@ -177,6 +177,11 @@ DEF_EDGE_FLAG(TM_UNINSTRUMENTED, 15) /* Abort (over) edge out of a GIMPLE_TRANSACTION statement. */ DEF_EDGE_FLAG(TM_ABORT, 16) +/* An edge we should ignore. It should be entirely local to + passes. ie, it is never set on any edge upon the completion + of any pass. */ +DEF_EDGE_FLAG(IGNORE, 17) + #endif /* diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index bfbc958c020..ae893527a0f 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -4374,9 +4374,10 @@ expand_debug_expr (tree exp) machine_mode mode1; HOST_WIDE_INT bitsize, bitpos; tree offset; - int volatilep = 0; - tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode1, &unsignedp, &volatilep, false); + int reversep, volatilep = 0; + tree tem + = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode1, + &unsignedp, &reversep, &volatilep, false); rtx orig_op0; if (bitsize == 0) @@ -4799,9 +4800,10 @@ expand_debug_expr (tree exp) if (handled_component_p (TREE_OPERAND (exp, 0))) { HOST_WIDE_INT bitoffset, bitsize, maxsize; + bool reverse; tree decl - = get_ref_base_and_extent (TREE_OPERAND (exp, 0), - &bitoffset, &bitsize, &maxsize); + = get_ref_base_and_extent (TREE_OPERAND (exp, 0), &bitoffset, + &bitsize, &maxsize, &reverse); if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL) diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c index 0f8c3e1df04..49899bd6fa6 100644 --- a/gcc/common/config/i386/i386-common.c +++ b/gcc/common/config/i386/i386-common.c @@ -997,6 +997,9 @@ static const struct default_options ix86_option_optimization_table[] = { OPT_LEVELS_2_PLUS, OPT_free, NULL, 1 }, /* Enable function splitting at -O2 and higher. */ { OPT_LEVELS_2_PLUS, OPT_freorder_blocks_and_partition, NULL, 1 }, + /* The STC algorithm produces the smallest code at -Os, for x86. */ + { OPT_LEVELS_2_PLUS, OPT_freorder_blocks_algorithm_, NULL, + REORDER_BLOCKS_ALGORITHM_STC }, /* Turn off -fschedule-insns by default. It tends to make the problem with not enough registers even worse. */ { OPT_LEVELS_ALL, OPT_fschedule_insns, NULL, 0 }, diff --git a/gcc/config.gcc b/gcc/config.gcc index 4a7cbd20503..9cc765e2bc1 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -439,7 +439,7 @@ powerpc*-*-*) cpu_type=rs6000 extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h htmintrin.h htmxlintrin.h" case x$with_cpu in - xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[345678]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|Xe6500) + xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[345678]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|xe6500) cpu_is_64bit=yes ;; esac diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c index a1998ed550a..6b4208ffb4c 100644 --- a/gcc/config/aarch64/aarch64-builtins.c +++ b/gcc/config/aarch64/aarch64-builtins.c @@ -324,6 +324,11 @@ enum aarch64_builtins AARCH64_BUILTIN_GET_FPSR, AARCH64_BUILTIN_SET_FPSR, + AARCH64_BUILTIN_RSQRT_DF, + AARCH64_BUILTIN_RSQRT_SF, + AARCH64_BUILTIN_RSQRT_V2DF, + AARCH64_BUILTIN_RSQRT_V2SF, + AARCH64_BUILTIN_RSQRT_V4SF, AARCH64_SIMD_BUILTIN_BASE, AARCH64_SIMD_BUILTIN_LANE_CHECK, #include "aarch64-simd-builtins.def" @@ -822,6 +827,46 @@ aarch64_init_crc32_builtins () } } +/* Add builtins for reciprocal square root. */ + +void +aarch64_init_builtin_rsqrt (void) +{ + tree fndecl = NULL; + tree ftype = NULL; + + tree V2SF_type_node = build_vector_type (float_type_node, 2); + tree V2DF_type_node = build_vector_type (double_type_node, 2); + tree V4SF_type_node = build_vector_type (float_type_node, 4); + + struct builtin_decls_data + { + tree type_node; + const char *builtin_name; + int function_code; + }; + + builtin_decls_data bdda[] = + { + { double_type_node, "__builtin_aarch64_rsqrt_df", AARCH64_BUILTIN_RSQRT_DF }, + { float_type_node, "__builtin_aarch64_rsqrt_sf", AARCH64_BUILTIN_RSQRT_SF }, + { V2DF_type_node, "__builtin_aarch64_rsqrt_v2df", AARCH64_BUILTIN_RSQRT_V2DF }, + { V2SF_type_node, "__builtin_aarch64_rsqrt_v2sf", AARCH64_BUILTIN_RSQRT_V2SF }, + { V4SF_type_node, "__builtin_aarch64_rsqrt_v4sf", AARCH64_BUILTIN_RSQRT_V4SF } + }; + + builtin_decls_data *bdd = bdda; + builtin_decls_data *bdd_end = bdd + (sizeof (bdda) / sizeof (builtin_decls_data)); + + for (; bdd < bdd_end; bdd++) + { + ftype = build_function_type_list (bdd->type_node, bdd->type_node, NULL_TREE); + fndecl = add_builtin_function (bdd->builtin_name, + ftype, bdd->function_code, BUILT_IN_MD, NULL, NULL_TREE); + aarch64_builtin_decls[bdd->function_code] = fndecl; + } +} + void aarch64_init_builtins (void) { @@ -853,6 +898,7 @@ aarch64_init_builtins (void) aarch64_init_simd_builtins (); aarch64_init_crc32_builtins (); + aarch64_init_builtin_rsqrt (); } tree @@ -1116,6 +1162,44 @@ aarch64_crc32_expand_builtin (int fcode, tree exp, rtx target) return target; } +/* Function to expand reciprocal square root builtins. */ + +static rtx +aarch64_expand_builtin_rsqrt (int fcode, tree exp, rtx target) +{ + tree arg0 = CALL_EXPR_ARG (exp, 0); + rtx op0 = expand_normal (arg0); + + rtx (*gen) (rtx, rtx); + + switch (fcode) + { + case AARCH64_BUILTIN_RSQRT_DF: + gen = gen_aarch64_rsqrt_df2; + break; + case AARCH64_BUILTIN_RSQRT_SF: + gen = gen_aarch64_rsqrt_sf2; + break; + case AARCH64_BUILTIN_RSQRT_V2DF: + gen = gen_aarch64_rsqrt_v2df2; + break; + case AARCH64_BUILTIN_RSQRT_V2SF: + gen = gen_aarch64_rsqrt_v2sf2; + break; + case AARCH64_BUILTIN_RSQRT_V4SF: + gen = gen_aarch64_rsqrt_v4sf2; + break; + default: gcc_unreachable (); + } + + if (!target) + target = gen_reg_rtx (GET_MODE (op0)); + + emit_insn (gen (target, op0)); + + return target; +} + /* Expand an expression EXP that calls a built-in function, with result going to TARGET if that's convenient. */ rtx @@ -1163,6 +1247,13 @@ aarch64_expand_builtin (tree exp, else if (fcode >= AARCH64_CRC32_BUILTIN_BASE && fcode <= AARCH64_CRC32_BUILTIN_MAX) return aarch64_crc32_expand_builtin (fcode, exp, target); + if (fcode == AARCH64_BUILTIN_RSQRT_DF + || fcode == AARCH64_BUILTIN_RSQRT_SF + || fcode == AARCH64_BUILTIN_RSQRT_V2DF + || fcode == AARCH64_BUILTIN_RSQRT_V2SF + || fcode == AARCH64_BUILTIN_RSQRT_V4SF) + return aarch64_expand_builtin_rsqrt (fcode, exp, target); + gcc_unreachable (); } @@ -1320,6 +1411,30 @@ aarch64_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in) return NULL_TREE; } +/* Return builtin for reciprocal square root. */ + +tree +aarch64_builtin_rsqrt (unsigned int fn, bool md_fn) +{ + if (md_fn) + { + if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2df) + return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2DF]; + if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2sf) + return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2SF]; + if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv4sf) + return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V4SF]; + } + else + { + if (fn == BUILT_IN_SQRT) + return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_DF]; + if (fn == BUILT_IN_SQRTF) + return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_SF]; + } + return NULL_TREE; +} + #undef VAR1 #define VAR1(T, N, MAP, A) \ case AARCH64_SIMD_BUILTIN_##T##_##N##A: diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 81792bcb7da..0f20f604481 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -352,6 +352,8 @@ void aarch64_register_pragmas (void); void aarch64_relayout_simd_types (void); void aarch64_reset_previous_fndecl (void); +void aarch64_emit_swrsqrt (rtx, rtx); + /* Initialize builtins for SIMD intrinsics. */ void init_aarch64_simd_builtins (void); @@ -403,6 +405,8 @@ rtx aarch64_expand_builtin (tree exp, int ignore ATTRIBUTE_UNUSED); tree aarch64_builtin_decl (unsigned, bool ATTRIBUTE_UNUSED); +tree aarch64_builtin_rsqrt (unsigned int, bool); + tree aarch64_builtin_vectorized_function (tree fndecl, tree type_out, diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def index 04dac6f84db..aad66b134ef 100644 --- a/gcc/config/aarch64/aarch64-simd-builtins.def +++ b/gcc/config/aarch64/aarch64-simd-builtins.def @@ -408,8 +408,26 @@ VAR1 (BINOPP, crypto_pmull, 0, di) VAR1 (BINOPP, crypto_pmull, 0, v2di) - /* Implemented by aarch64_tbl3v8qi. */ + /* Implemented by aarch64_tbl3. */ VAR1 (BINOP, tbl3, 0, v8qi) + VAR1 (BINOP, tbl3, 0, v16qi) - /* Implemented by aarch64_tbx4v8qi. */ + /* Implemented by aarch64_qtbl3. */ + VAR1 (BINOP, qtbl3, 0, v8qi) + VAR1 (BINOP, qtbl3, 0, v16qi) + + /* Implemented by aarch64_qtbl4. */ + VAR1 (BINOP, qtbl4, 0, v8qi) + VAR1 (BINOP, qtbl4, 0, v16qi) + + /* Implemented by aarch64_tbx4. */ VAR1 (TERNOP, tbx4, 0, v8qi) + VAR1 (TERNOP, tbx4, 0, v16qi) + + /* Implemented by aarch64_qtbx3. */ + VAR1 (TERNOP, qtbx3, 0, v8qi) + VAR1 (TERNOP, qtbx3, 0, v16qi) + + /* Implemented by aarch64_qtbx4. */ + VAR1 (TERNOP, qtbx4, 0, v8qi) + VAR1 (TERNOP, qtbx4, 0, v16qi) diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 269e00237bb..0fb81342128 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -382,6 +382,33 @@ [(set_attr "type" "neon_fp_mul_d_scalar_q")] ) +(define_insn "aarch64_rsqrte_2" + [(set (match_operand:VALLF 0 "register_operand" "=w") + (unspec:VALLF [(match_operand:VALLF 1 "register_operand" "w")] + UNSPEC_RSQRTE))] + "TARGET_SIMD" + "frsqrte\\t%0, %1" + [(set_attr "type" "neon_fp_rsqrte_")]) + +(define_insn "aarch64_rsqrts_3" + [(set (match_operand:VALLF 0 "register_operand" "=w") + (unspec:VALLF [(match_operand:VALLF 1 "register_operand" "w") + (match_operand:VALLF 2 "register_operand" "w")] + UNSPEC_RSQRTS))] + "TARGET_SIMD" + "frsqrts\\t%0, %1, %2" + [(set_attr "type" "neon_fp_rsqrts_")]) + +(define_expand "aarch64_rsqrt_2" + [(set (match_operand:VALLF 0 "register_operand" "=w") + (unspec:VALLF [(match_operand:VALLF 1 "register_operand" "w")] + UNSPEC_RSQRT))] + "TARGET_SIMD" +{ + aarch64_emit_swrsqrt (operands[0], operands[1]); + DONE; +}) + (define_insn "*aarch64_mul3_elt_to_64v2df" [(set (match_operand:DF 0 "register_operand" "=w") (mult:DF @@ -4789,24 +4816,70 @@ [(set_attr "type" "neon_tbl2_q")] ) -(define_insn "aarch64_tbl3v8qi" - [(set (match_operand:V8QI 0 "register_operand" "=w") - (unspec:V8QI [(match_operand:OI 1 "register_operand" "w") - (match_operand:V8QI 2 "register_operand" "w")] +(define_insn "aarch64_tbl3" + [(set (match_operand:VB 0 "register_operand" "=w") + (unspec:VB [(match_operand:OI 1 "register_operand" "w") + (match_operand:VB 2 "register_operand" "w")] UNSPEC_TBL))] "TARGET_SIMD" - "tbl\\t%S0.8b, {%S1.16b - %T1.16b}, %S2.8b" + "tbl\\t%S0., {%S1.16b - %T1.16b}, %S2." [(set_attr "type" "neon_tbl3")] ) -(define_insn "aarch64_tbx4v8qi" - [(set (match_operand:V8QI 0 "register_operand" "=w") - (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "0") +(define_insn "aarch64_tbx4" + [(set (match_operand:VB 0 "register_operand" "=w") + (unspec:VB [(match_operand:VB 1 "register_operand" "0") (match_operand:OI 2 "register_operand" "w") - (match_operand:V8QI 3 "register_operand" "w")] + (match_operand:VB 3 "register_operand" "w")] + UNSPEC_TBX))] + "TARGET_SIMD" + "tbx\\t%S0., {%S2.16b - %T2.16b}, %S3." + [(set_attr "type" "neon_tbl4")] +) + +;; Three source registers. + +(define_insn "aarch64_qtbl3" + [(set (match_operand:VB 0 "register_operand" "=w") + (unspec:VB [(match_operand:CI 1 "register_operand" "w") + (match_operand:VB 2 "register_operand" "w")] + UNSPEC_TBL))] + "TARGET_SIMD" + "tbl\\t%S0., {%S1.16b - %U1.16b}, %S2." + [(set_attr "type" "neon_tbl3")] +) + +(define_insn "aarch64_qtbx3" + [(set (match_operand:VB 0 "register_operand" "=w") + (unspec:VB [(match_operand:VB 1 "register_operand" "0") + (match_operand:CI 2 "register_operand" "w") + (match_operand:VB 3 "register_operand" "w")] + UNSPEC_TBX))] + "TARGET_SIMD" + "tbx\\t%S0., {%S2.16b - %U2.16b}, %S3." + [(set_attr "type" "neon_tbl3")] +) + +;; Four source registers. + +(define_insn "aarch64_qtbl4" + [(set (match_operand:VB 0 "register_operand" "=w") + (unspec:VB [(match_operand:XI 1 "register_operand" "w") + (match_operand:VB 2 "register_operand" "w")] + UNSPEC_TBL))] + "TARGET_SIMD" + "tbl\\t%S0., {%S1.16b - %V1.16b}, %S2." + [(set_attr "type" "neon_tbl4")] +) + +(define_insn "aarch64_qtbx4" + [(set (match_operand:VB 0 "register_operand" "=w") + (unspec:VB [(match_operand:VB 1 "register_operand" "0") + (match_operand:XI 2 "register_operand" "w") + (match_operand:VB 3 "register_operand" "w")] UNSPEC_TBX))] "TARGET_SIMD" - "tbx\\t%S0.8b, {%S2.16b - %T2.16b}, %S3.8b" + "tbx\\t%S0., {%S2.16b - %V2.16b}, %S3." [(set_attr "type" "neon_tbl4")] ) diff --git a/gcc/config/aarch64/aarch64-tuning-flags.def b/gcc/config/aarch64/aarch64-tuning-flags.def index 628386b5a1d..6f7dbcec03d 100644 --- a/gcc/config/aarch64/aarch64-tuning-flags.def +++ b/gcc/config/aarch64/aarch64-tuning-flags.def @@ -29,4 +29,5 @@ AARCH64_TUNE_ to give an enum name. */ AARCH64_EXTRA_TUNING_OPTION ("rename_fma_regs", RENAME_FMA_REGS) +AARCH64_EXTRA_TUNING_OPTION ("recip_sqrt", RECIP_SQRT) diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 5c8604ffa72..1b7be838c73 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -52,6 +52,7 @@ #include "params.h" #include "gimplify.h" #include "dwarf2.h" +#include "gimple-iterator.h" #include "tree-vectorizer.h" #include "aarch64-cost-tables.h" #include "dumpfile.h" @@ -402,7 +403,8 @@ static const struct tune_params cortexa57_tunings = 2, /* min_div_recip_mul_sf. */ 2, /* min_div_recip_mul_df. */ tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_RENAME_FMA_REGS) /* tune_flags. */ + (AARCH64_EXTRA_TUNE_RENAME_FMA_REGS + | AARCH64_EXTRA_TUNE_RECIP_SQRT) /* tune_flags. */ }; static const struct tune_params cortexa72_tunings = @@ -469,7 +471,7 @@ static const struct tune_params xgene1_tunings = 2, /* min_div_recip_mul_sf. */ 2, /* min_div_recip_mul_df. */ tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE) /* tune_flags. */ + (AARCH64_EXTRA_TUNE_RECIP_SQRT) /* tune_flags. */ }; /* Support for fine-grained override of the tuning structures. */ @@ -5235,24 +5237,38 @@ aarch64_uxt_size (int shift, HOST_WIDE_INT mask) return 0; } +/* Constant pools are per function only when PC relative + literal loads are true or we are in the large memory + model. */ + +static inline bool +aarch64_can_use_per_function_literal_pools_p (void) +{ + return (!aarch64_nopcrelative_literal_loads + || aarch64_cmodel == AARCH64_CMODEL_LARGE); +} + static bool -aarch64_use_blocks_for_constant_p (machine_mode mode ATTRIBUTE_UNUSED, - const_rtx x ATTRIBUTE_UNUSED) +aarch64_use_blocks_for_constant_p (machine_mode, const_rtx) { /* We can't use blocks for constants when we're using a per-function constant pool. */ - return false; + return !aarch64_can_use_per_function_literal_pools_p (); } +/* Select appropriate section for constants depending + on where we place literal pools. */ + static section * -aarch64_select_rtx_section (machine_mode mode ATTRIBUTE_UNUSED, - rtx x ATTRIBUTE_UNUSED, - unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) +aarch64_select_rtx_section (machine_mode mode, + rtx x, + unsigned HOST_WIDE_INT align) { - /* Force all constant pool entries into the current function section. */ - return function_section (current_function_decl); -} + if (aarch64_can_use_per_function_literal_pools_p ()) + return function_section (current_function_decl); + return default_elf_select_rtx_section (mode, x, align); +} /* Costs. */ @@ -7030,6 +7046,105 @@ aarch64_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED, return aarch64_tune_params.memmov_cost; } +/* Function to decide when to use + reciprocal square root builtins. */ + +static tree +aarch64_builtin_reciprocal (unsigned int fn, + bool md_fn, + bool) +{ + if (flag_trapping_math + || !flag_unsafe_math_optimizations + || optimize_size + || ! (aarch64_tune_params.extra_tuning_flags + & AARCH64_EXTRA_TUNE_RECIP_SQRT)) + { + return NULL_TREE; + } + + return aarch64_builtin_rsqrt (fn, md_fn); +} + +typedef rtx (*rsqrte_type) (rtx, rtx); + +/* Select reciprocal square root initial estimate + insn depending on machine mode. */ + +rsqrte_type +get_rsqrte_type (machine_mode mode) +{ + switch (mode) + { + case DFmode: return gen_aarch64_rsqrte_df2; + case SFmode: return gen_aarch64_rsqrte_sf2; + case V2DFmode: return gen_aarch64_rsqrte_v2df2; + case V2SFmode: return gen_aarch64_rsqrte_v2sf2; + case V4SFmode: return gen_aarch64_rsqrte_v4sf2; + default: gcc_unreachable (); + } +} + +typedef rtx (*rsqrts_type) (rtx, rtx, rtx); + +/* Select reciprocal square root Newton-Raphson step + insn depending on machine mode. */ + +rsqrts_type +get_rsqrts_type (machine_mode mode) +{ + switch (mode) + { + case DFmode: return gen_aarch64_rsqrts_df3; + case SFmode: return gen_aarch64_rsqrts_sf3; + case V2DFmode: return gen_aarch64_rsqrts_v2df3; + case V2SFmode: return gen_aarch64_rsqrts_v2sf3; + case V4SFmode: return gen_aarch64_rsqrts_v4sf3; + default: gcc_unreachable (); + } +} + +/* Emit instruction sequence to compute + reciprocal square root. Use two Newton-Raphson steps + for single precision and three for double precision. */ + +void +aarch64_emit_swrsqrt (rtx dst, rtx src) +{ + machine_mode mode = GET_MODE (src); + gcc_assert ( + mode == SFmode || mode == V2SFmode || mode == V4SFmode + || mode == DFmode || mode == V2DFmode); + + rtx xsrc = gen_reg_rtx (mode); + emit_move_insn (xsrc, src); + rtx x0 = gen_reg_rtx (mode); + + emit_insn ((*get_rsqrte_type (mode)) (x0, xsrc)); + + bool double_mode = (mode == DFmode || mode == V2DFmode); + + int iterations = double_mode ? 3 : 2; + + if (flag_mrecip_low_precision_sqrt) + iterations--; + + for (int i = 0; i < iterations; ++i) + { + rtx x1 = gen_reg_rtx (mode); + rtx x2 = gen_reg_rtx (mode); + rtx x3 = gen_reg_rtx (mode); + emit_set_insn (x2, gen_rtx_MULT (mode, x0, x0)); + + emit_insn ((*get_rsqrts_type (mode)) (x3, xsrc, x2)); + + emit_set_insn (x1, gen_rtx_MULT (mode, x0, x3)); + x0 = x1; + } + + emit_move_insn (dst, x0); +} + /* Return the number of instructions that can be issued per cycle. */ static int aarch64_sched_issue_rate (void) @@ -13454,6 +13569,9 @@ aarch64_promoted_type (const_tree t) #undef TARGET_BUILTIN_DECL #define TARGET_BUILTIN_DECL aarch64_builtin_decl +#undef TARGET_BUILTIN_RECIPROCAL +#define TARGET_BUILTIN_RECIPROCAL aarch64_builtin_reciprocal + #undef TARGET_EXPAND_BUILTIN #define TARGET_EXPAND_BUILTIN aarch64_expand_builtin diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 6cdddf49102..6b08850e9d0 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -126,6 +126,9 @@ UNSPEC_VSTRUCTDUMMY UNSPEC_SP_SET UNSPEC_SP_TEST + UNSPEC_RSQRT + UNSPEC_RSQRTE + UNSPEC_RSQRTS ]) (define_c_enum "unspecv" [ diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt index c031bcc7be6..a0fbfd42c09 100644 --- a/gcc/config/aarch64/aarch64.opt +++ b/gcc/config/aarch64/aarch64.opt @@ -148,3 +148,8 @@ Enum(aarch64_abi) String(lp64) Value(AARCH64_ABI_LP64) mpc-relative-literal-loads Target Report Save Var(nopcrelative_literal_loads) Init(2) Save PC relative literal loads. + +mlow-precision-recip-sqrt +Common Var(flag_mrecip_low_precision_sqrt) Optimization +When calculating a sqrt approximation, run fewer steps. +This reduces precision, but can result in faster computation. diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h index 265c2667908..7f69043d8a7 100644 --- a/gcc/config/aarch64/arm_neon.h +++ b/gcc/config/aarch64/arm_neon.h @@ -10622,224 +10622,6 @@ vqtbl1q_u8 (uint8x16_t a, uint8x16_t b) return result; } -__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) -vqtbl2_s8 (int8x16x2_t tab, uint8x8_t idx) -{ - int8x8_t result; - __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t" - "tbl %0.8b, {v16.16b, v17.16b}, %2.8b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17"); - return result; -} - -__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -vqtbl2_u8 (uint8x16x2_t tab, uint8x8_t idx) -{ - uint8x8_t result; - __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t" - "tbl %0.8b, {v16.16b, v17.16b}, %2.8b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17"); - return result; -} - -__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) -vqtbl2_p8 (poly8x16x2_t tab, uint8x8_t idx) -{ - poly8x8_t result; - __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t" - "tbl %0.8b, {v16.16b, v17.16b}, %2.8b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17"); - return result; -} - -__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) -vqtbl2q_s8 (int8x16x2_t tab, uint8x16_t idx) -{ - int8x16_t result; - __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t" - "tbl %0.16b, {v16.16b, v17.16b}, %2.16b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17"); - return result; -} - -__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -vqtbl2q_u8 (uint8x16x2_t tab, uint8x16_t idx) -{ - uint8x16_t result; - __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t" - "tbl %0.16b, {v16.16b, v17.16b}, %2.16b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17"); - return result; -} - -__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) -vqtbl2q_p8 (poly8x16x2_t tab, uint8x16_t idx) -{ - poly8x16_t result; - __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t" - "tbl %0.16b, {v16.16b, v17.16b}, %2.16b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17"); - return result; -} - -__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) -vqtbl3_s8 (int8x16x3_t tab, uint8x8_t idx) -{ - int8x8_t result; - __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t" - "tbl %0.8b, {v16.16b - v18.16b}, %2.8b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18"); - return result; -} - -__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -vqtbl3_u8 (uint8x16x3_t tab, uint8x8_t idx) -{ - uint8x8_t result; - __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t" - "tbl %0.8b, {v16.16b - v18.16b}, %2.8b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18"); - return result; -} - -__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) -vqtbl3_p8 (poly8x16x3_t tab, uint8x8_t idx) -{ - poly8x8_t result; - __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t" - "tbl %0.8b, {v16.16b - v18.16b}, %2.8b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18"); - return result; -} - -__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) -vqtbl3q_s8 (int8x16x3_t tab, uint8x16_t idx) -{ - int8x16_t result; - __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t" - "tbl %0.16b, {v16.16b - v18.16b}, %2.16b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18"); - return result; -} - -__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -vqtbl3q_u8 (uint8x16x3_t tab, uint8x16_t idx) -{ - uint8x16_t result; - __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t" - "tbl %0.16b, {v16.16b - v18.16b}, %2.16b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18"); - return result; -} - -__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) -vqtbl3q_p8 (poly8x16x3_t tab, uint8x16_t idx) -{ - poly8x16_t result; - __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t" - "tbl %0.16b, {v16.16b - v18.16b}, %2.16b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18"); - return result; -} - -__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) -vqtbl4_s8 (int8x16x4_t tab, uint8x8_t idx) -{ - int8x8_t result; - __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t" - "tbl %0.8b, {v16.16b - v19.16b}, %2.8b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18", "v19"); - return result; -} - -__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -vqtbl4_u8 (uint8x16x4_t tab, uint8x8_t idx) -{ - uint8x8_t result; - __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t" - "tbl %0.8b, {v16.16b - v19.16b}, %2.8b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18", "v19"); - return result; -} - -__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) -vqtbl4_p8 (poly8x16x4_t tab, uint8x8_t idx) -{ - poly8x8_t result; - __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t" - "tbl %0.8b, {v16.16b - v19.16b}, %2.8b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18", "v19"); - return result; -} - - -__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) -vqtbl4q_s8 (int8x16x4_t tab, uint8x16_t idx) -{ - int8x16_t result; - __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t" - "tbl %0.16b, {v16.16b - v19.16b}, %2.16b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18", "v19"); - return result; -} - -__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -vqtbl4q_u8 (uint8x16x4_t tab, uint8x16_t idx) -{ - uint8x16_t result; - __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t" - "tbl %0.16b, {v16.16b - v19.16b}, %2.16b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18", "v19"); - return result; -} - -__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) -vqtbl4q_p8 (poly8x16x4_t tab, uint8x16_t idx) -{ - poly8x16_t result; - __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t" - "tbl %0.16b, {v16.16b - v19.16b}, %2.16b\n\t" - :"=w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18", "v19"); - return result; -} - - __extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) vqtbx1_s8 (int8x8_t r, int8x16_t tab, uint8x8_t idx) { @@ -10906,227 +10688,6 @@ vqtbx1q_p8 (poly8x16_t r, poly8x16_t tab, uint8x16_t idx) return result; } -__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) -vqtbx2_s8 (int8x8_t r, int8x16x2_t tab, uint8x8_t idx) -{ - int8x8_t result = r; - __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t" - "tbx %0.8b, {v16.16b, v17.16b}, %2.8b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17"); - return result; -} - -__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -vqtbx2_u8 (uint8x8_t r, uint8x16x2_t tab, uint8x8_t idx) -{ - uint8x8_t result = r; - __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t" - "tbx %0.8b, {v16.16b, v17.16b}, %2.8b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17"); - return result; -} - -__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) -vqtbx2_p8 (poly8x8_t r, poly8x16x2_t tab, uint8x8_t idx) -{ - poly8x8_t result = r; - __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t" - "tbx %0.8b, {v16.16b, v17.16b}, %2.8b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17"); - return result; -} - - -__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) -vqtbx2q_s8 (int8x16_t r, int8x16x2_t tab, uint8x16_t idx) -{ - int8x16_t result = r; - __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t" - "tbx %0.16b, {v16.16b, v17.16b}, %2.16b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17"); - return result; -} - -__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -vqtbx2q_u8 (uint8x16_t r, uint8x16x2_t tab, uint8x16_t idx) -{ - uint8x16_t result = r; - __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t" - "tbx %0.16b, {v16.16b, v17.16b}, %2.16b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17"); - return result; -} - -__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) -vqtbx2q_p8 (poly8x16_t r, poly8x16x2_t tab, uint8x16_t idx) -{ - poly8x16_t result = r; - __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t" - "tbx %0.16b, {v16.16b, v17.16b}, %2.16b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17"); - return result; -} - - -__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) -vqtbx3_s8 (int8x8_t r, int8x16x3_t tab, uint8x8_t idx) -{ - int8x8_t result = r; - __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t" - "tbx %0.8b, {v16.16b - v18.16b}, %2.8b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18"); - return result; -} - -__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -vqtbx3_u8 (uint8x8_t r, uint8x16x3_t tab, uint8x8_t idx) -{ - uint8x8_t result = r; - __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t" - "tbx %0.8b, {v16.16b - v18.16b}, %2.8b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18"); - return result; -} - -__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) -vqtbx3_p8 (poly8x8_t r, poly8x16x3_t tab, uint8x8_t idx) -{ - poly8x8_t result = r; - __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t" - "tbx %0.8b, {v16.16b - v18.16b}, %2.8b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18"); - return result; -} - - -__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) -vqtbx3q_s8 (int8x16_t r, int8x16x3_t tab, uint8x16_t idx) -{ - int8x16_t result = r; - __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t" - "tbx %0.16b, {v16.16b - v18.16b}, %2.16b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18"); - return result; -} - -__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -vqtbx3q_u8 (uint8x16_t r, uint8x16x3_t tab, uint8x16_t idx) -{ - uint8x16_t result = r; - __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t" - "tbx %0.16b, {v16.16b - v18.16b}, %2.16b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18"); - return result; -} - -__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) -vqtbx3q_p8 (poly8x16_t r, poly8x16x3_t tab, uint8x16_t idx) -{ - poly8x16_t result = r; - __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t" - "tbx %0.16b, {v16.16b - v18.16b}, %2.16b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18"); - return result; -} - - -__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) -vqtbx4_s8 (int8x8_t r, int8x16x4_t tab, uint8x8_t idx) -{ - int8x8_t result = r; - __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t" - "tbx %0.8b, {v16.16b - v19.16b}, %2.8b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18", "v19"); - return result; -} - -__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -vqtbx4_u8 (uint8x8_t r, uint8x16x4_t tab, uint8x8_t idx) -{ - uint8x8_t result = r; - __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t" - "tbx %0.8b, {v16.16b - v19.16b}, %2.8b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18", "v19"); - return result; -} - -__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) -vqtbx4_p8 (poly8x8_t r, poly8x16x4_t tab, uint8x8_t idx) -{ - poly8x8_t result = r; - __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t" - "tbx %0.8b, {v16.16b - v19.16b}, %2.8b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18", "v19"); - return result; -} - - -__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) -vqtbx4q_s8 (int8x16_t r, int8x16x4_t tab, uint8x16_t idx) -{ - int8x16_t result = r; - __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t" - "tbx %0.16b, {v16.16b - v19.16b}, %2.16b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18", "v19"); - return result; -} - -__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -vqtbx4q_u8 (uint8x16_t r, uint8x16x4_t tab, uint8x16_t idx) -{ - uint8x16_t result = r; - __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t" - "tbx %0.16b, {v16.16b - v19.16b}, %2.16b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18", "v19"); - return result; -} - -__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) -vqtbx4q_p8 (poly8x16_t r, poly8x16x4_t tab, uint8x16_t idx) -{ - poly8x16_t result = r; - __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t" - "tbx %0.16b, {v16.16b - v19.16b}, %2.16b\n\t" - :"+w"(result) - :"Q"(tab),"w"(idx) - :"memory", "v16", "v17", "v18", "v19"); - return result; -} - /* V7 legacy table intrinsics. */ __extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) @@ -20714,6 +20275,389 @@ vqsubd_u64 (uint64_t __a, uint64_t __b) return __builtin_aarch64_uqsubdi_uuu (__a, __b); } +/* vqtbl2 */ + +__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) +vqtbl2_s8 (int8x16x2_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[1], 1); + return __builtin_aarch64_tbl3v8qi (__o, (int8x8_t)idx); +} + +__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) +vqtbl2_u8 (uint8x16x2_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (uint8x8_t)__builtin_aarch64_tbl3v8qi (__o, (int8x8_t)idx); +} + +__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) +vqtbl2_p8 (poly8x16x2_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (poly8x8_t)__builtin_aarch64_tbl3v8qi (__o, (int8x8_t)idx); +} + +__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) +vqtbl2q_s8 (int8x16x2_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return __builtin_aarch64_tbl3v16qi (__o, (int8x16_t)idx); +} + +__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) +vqtbl2q_u8 (uint8x16x2_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (uint8x16_t)__builtin_aarch64_tbl3v16qi (__o, (int8x16_t)idx); +} + +__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) +vqtbl2q_p8 (poly8x16x2_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (poly8x16_t)__builtin_aarch64_tbl3v16qi (__o, (int8x16_t)idx); +} + +/* vqtbl3 */ + +__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) +vqtbl3_s8 (int8x16x3_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return __builtin_aarch64_qtbl3v8qi (__o, (int8x8_t)idx); +} + +__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) +vqtbl3_u8 (uint8x16x3_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (uint8x8_t)__builtin_aarch64_qtbl3v8qi (__o, (int8x8_t)idx); +} + +__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) +vqtbl3_p8 (poly8x16x3_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (poly8x8_t)__builtin_aarch64_qtbl3v8qi (__o, (int8x8_t)idx); +} + +__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) +vqtbl3q_s8 (int8x16x3_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return __builtin_aarch64_qtbl3v16qi (__o, (int8x16_t)idx); +} + +__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) +vqtbl3q_u8 (uint8x16x3_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (uint8x16_t)__builtin_aarch64_qtbl3v16qi (__o, (int8x16_t)idx); +} + +__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) +vqtbl3q_p8 (poly8x16x3_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (poly8x16_t)__builtin_aarch64_qtbl3v16qi (__o, (int8x16_t)idx); +} + +/* vqtbl4 */ + +__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) +vqtbl4_s8 (int8x16x4_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return __builtin_aarch64_qtbl4v8qi (__o, (int8x8_t)idx); +} + +__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) +vqtbl4_u8 (uint8x16x4_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (uint8x8_t)__builtin_aarch64_qtbl4v8qi (__o, (int8x8_t)idx); +} + +__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) +vqtbl4_p8 (poly8x16x4_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (poly8x8_t)__builtin_aarch64_qtbl4v8qi (__o, (int8x8_t)idx); +} + +__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) +vqtbl4q_s8 (int8x16x4_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return __builtin_aarch64_qtbl4v16qi (__o, (int8x16_t)idx); +} + +__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) +vqtbl4q_u8 (uint8x16x4_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (uint8x16_t)__builtin_aarch64_qtbl4v16qi (__o, (int8x16_t)idx); +} + +__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) +vqtbl4q_p8 (poly8x16x4_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (poly8x16_t)__builtin_aarch64_qtbl4v16qi (__o, (int8x16_t)idx); +} + + +/* vqtbx2 */ +__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) +vqtbx2_s8 (int8x8_t r, int8x16x2_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[1], 1); + return __builtin_aarch64_tbx4v8qi (r, __o, (int8x8_t)idx); +} + +__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) +vqtbx2_u8 (uint8x8_t r, uint8x16x2_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (uint8x8_t)__builtin_aarch64_tbx4v8qi ((int8x8_t)r, __o, + (int8x8_t)idx); +} + +__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) +vqtbx2_p8 (poly8x8_t r, poly8x16x2_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (poly8x8_t)__builtin_aarch64_tbx4v8qi ((int8x8_t)r, __o, + (int8x8_t)idx); +} + +__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) +vqtbx2q_s8 (int8x16_t r, int8x16x2_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[1], 1); + return __builtin_aarch64_tbx4v16qi (r, __o, (int8x16_t)idx); +} + +__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) +vqtbx2q_u8 (uint8x16_t r, uint8x16x2_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (uint8x16_t)__builtin_aarch64_tbx4v16qi ((int8x16_t)r, __o, + (int8x16_t)idx); +} + +__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) +vqtbx2q_p8 (poly8x16_t r, poly8x16x2_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_oi __o; + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1); + return (poly8x16_t)__builtin_aarch64_tbx4v16qi ((int8x16_t)r, __o, + (int8x16_t)idx); +} + +/* vqtbx3 */ +__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) +vqtbx3_s8 (int8x8_t r, int8x16x3_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[2], 2); + return __builtin_aarch64_qtbx3v8qi (r, __o, (int8x8_t)idx); +} + +__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) +vqtbx3_u8 (uint8x8_t r, uint8x16x3_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (uint8x8_t)__builtin_aarch64_qtbx3v8qi ((int8x8_t)r, __o, + (int8x8_t)idx); +} + +__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) +vqtbx3_p8 (poly8x8_t r, poly8x16x3_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (poly8x8_t)__builtin_aarch64_qtbx3v8qi ((int8x8_t)r, __o, + (int8x8_t)idx); +} + +__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) +vqtbx3q_s8 (int8x16_t r, int8x16x3_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[2], 2); + return __builtin_aarch64_qtbx3v16qi (r, __o, (int8x16_t)idx); +} + +__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) +vqtbx3q_u8 (uint8x16_t r, uint8x16x3_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (uint8x16_t)__builtin_aarch64_qtbx3v16qi ((int8x16_t)r, __o, + (int8x16_t)idx); +} + +__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) +vqtbx3q_p8 (poly8x16_t r, poly8x16x3_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_ci __o; + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2); + return (poly8x16_t)__builtin_aarch64_qtbx3v16qi ((int8x16_t)r, __o, + (int8x16_t)idx); +} + +/* vqtbx4 */ + +__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) +vqtbx4_s8 (int8x8_t r, int8x16x4_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[3], 3); + return __builtin_aarch64_qtbx4v8qi (r, __o, (int8x8_t)idx); +} + +__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) +vqtbx4_u8 (uint8x8_t r, uint8x16x4_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (uint8x8_t)__builtin_aarch64_qtbx4v8qi ((int8x8_t)r, __o, + (int8x8_t)idx); +} + +__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) +vqtbx4_p8 (poly8x8_t r, poly8x16x4_t tab, uint8x8_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (poly8x8_t)__builtin_aarch64_qtbx4v8qi ((int8x8_t)r, __o, + (int8x8_t)idx); +} + +__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) +vqtbx4q_s8 (int8x16_t r, int8x16x4_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[3], 3); + return __builtin_aarch64_qtbx4v16qi (r, __o, (int8x16_t)idx); +} + +__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) +vqtbx4q_u8 (uint8x16_t r, uint8x16x4_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (uint8x16_t)__builtin_aarch64_qtbx4v16qi ((int8x16_t)r, __o, + (int8x16_t)idx); +} + +__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) +vqtbx4q_p8 (poly8x16_t r, poly8x16x4_t tab, uint8x16_t idx) +{ + __builtin_aarch64_simd_xi __o; + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2); + __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3); + return (poly8x16_t)__builtin_aarch64_qtbx4v16qi ((int8x16_t)r, __o, + (int8x16_t)idx); +} + /* vrbit */ __extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) diff --git a/gcc/config/arm/aarch-common.c b/gcc/config/arm/aarch-common.c index a940a0232f8..e6668d5742c 100644 --- a/gcc/config/arm/aarch-common.c +++ b/gcc/config/arm/aarch-common.c @@ -460,6 +460,12 @@ aarch_accumulator_forwarding (rtx_insn *producer, rtx_insn *consumer) return 0; } + if (GET_CODE (accumulator) == SUBREG) + accumulator = SUBREG_REG (accumulator); + + if (!REG_P (accumulator)) + return 0; + return (REGNO (dest) == REGNO (accumulator)); } diff --git a/gcc/config/arm/arm-ldmstm.ml b/gcc/config/arm/arm-ldmstm.ml index bb901922e83..62982df594d 100644 --- a/gcc/config/arm/arm-ldmstm.ml +++ b/gcc/config/arm/arm-ldmstm.ml @@ -33,9 +33,20 @@ type amode = IA | IB | DA | DB type optype = IN | OUT | INOUT -let rec string_of_addrmode addrmode = +let rec string_of_addrmode addrmode thumb update = + if thumb || update +then match addrmode with - IA -> "ia" | IB -> "ib" | DA -> "da" | DB -> "db" + IA -> "ia" + | IB -> "ib" + | DA -> "da" + | DB -> "db" +else + match addrmode with + IA -> "" + | IB -> "ib" + | DA -> "da" + | DB -> "db" let rec initial_offset addrmode nregs = match addrmode with @@ -160,7 +171,7 @@ let target addrmode thumb = | _, _ -> raise (InvalidAddrMode "ERROR: Invalid Addressing mode for Thumb1.") let write_pattern_1 name ls addrmode nregs write_set_fn update thumb = - let astr = string_of_addrmode addrmode in + let astr = string_of_addrmode addrmode thumb update in Printf.printf "(define_insn \"*%s%s%d_%s%s\"\n" (if thumb then "thumb_" else "") name nregs astr (if update then "_update" else ""); @@ -180,8 +191,10 @@ let write_pattern_1 name ls addrmode nregs write_set_fn update thumb = Printf.printf ")]\n \"%s && XVECLEN (operands[0], 0) == %d\"\n" (target addrmode thumb) (if update then nregs + 1 else nregs); - Printf.printf " \"%s%%(%s%%)\\t%%%d%s, {" - name astr (nregs + 1) (if update then "!" else ""); + if thumb then + Printf.printf " \"%s%s\\t%%%d%s, {" name astr (nregs + 1) (if update then "!" else "") + else + Printf.printf " \"%s%s%%?\\t%%%d%s, {" name astr (nregs + 1) (if update then "!" else ""); for n = 1 to nregs; do Printf.printf "%%%d%s" n (if n < nregs then ", " else "") done; diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 43106387c1a..61e2aa23006 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -913,7 +913,7 @@ int arm_regs_in_sequence[] = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; -#define ARM_LSL_NAME (TARGET_UNIFIED_ASM ? "lsl" : "asl") +#define ARM_LSL_NAME "lsl" #define streq(string1, string2) (strcmp (string1, string2) == 0) #define THUMB2_WORK_REGS (0xff & ~( (1 << THUMB_HARD_FRAME_POINTER_REGNUM) \ @@ -3566,10 +3566,7 @@ arm_warn_func_return (tree decl) static void arm_asm_trampoline_template (FILE *f) { - if (TARGET_UNIFIED_ASM) - fprintf (f, "\t.syntax unified\n"); - else - fprintf (f, "\t.syntax divided\n"); + fprintf (f, "\t.syntax unified\n"); if (TARGET_ARM) { @@ -17637,10 +17634,8 @@ arm_output_multireg_pop (rtx *operands, bool return_pc, rtx cond, bool reverse, } conditional = reverse ? "%?%D0" : "%?%d0"; - if ((regno_base == SP_REGNUM) && TARGET_THUMB) + if ((regno_base == SP_REGNUM) && update) { - /* Output pop (not stmfd) because it has a shorter encoding. */ - gcc_assert (update); sprintf (pattern, "pop%s\t{", conditional); } else @@ -17648,11 +17643,14 @@ 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) - sprintf (pattern, "ldm%sfd\t", conditional); - else if (TARGET_UNIFIED_ASM) - sprintf (pattern, "ldmia%s\t", conditional); + /* update is never true here, hence there is no need to handle + pop here. */ + sprintf (pattern, "ldmfd%s", conditional); + + if (update) + sprintf (pattern, "ldmia%s\t", conditional); else - sprintf (pattern, "ldm%sia\t", conditional); + sprintf (pattern, "ldm%s\t", conditional); strcat (pattern, reg_names[regno_base]); if (update) @@ -17992,25 +17990,25 @@ output_move_double (rtx *operands, bool emit, int *count) { if (TARGET_LDRD && !(fix_cm3_ldrd && reg0 == REGNO(XEXP (operands[1], 0)))) - output_asm_insn ("ldr%(d%)\t%0, [%m1]", operands); + output_asm_insn ("ldrd%?\t%0, [%m1]", operands); else - output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands); + output_asm_insn ("ldmia%?\t%m1, %M0", operands); } break; case PRE_INC: gcc_assert (TARGET_LDRD); if (emit) - output_asm_insn ("ldr%(d%)\t%0, [%m1, #8]!", operands); + output_asm_insn ("ldrd%?\t%0, [%m1, #8]!", operands); break; case PRE_DEC: if (emit) { if (TARGET_LDRD) - output_asm_insn ("ldr%(d%)\t%0, [%m1, #-8]!", operands); + output_asm_insn ("ldrd%?\t%0, [%m1, #-8]!", operands); else - output_asm_insn ("ldm%(db%)\t%m1!, %M0", operands); + output_asm_insn ("ldmdb%?\t%m1!, %M0", operands); } break; @@ -18018,16 +18016,16 @@ output_move_double (rtx *operands, bool emit, int *count) if (emit) { if (TARGET_LDRD) - output_asm_insn ("ldr%(d%)\t%0, [%m1], #8", operands); + output_asm_insn ("ldrd%?\t%0, [%m1], #8", operands); else - output_asm_insn ("ldm%(ia%)\t%m1!, %M0", operands); + output_asm_insn ("ldmia%?\t%m1!, %M0", operands); } break; case POST_DEC: gcc_assert (TARGET_LDRD); if (emit) - output_asm_insn ("ldr%(d%)\t%0, [%m1], #-8", operands); + output_asm_insn ("ldrd%?\t%0, [%m1], #-8", operands); break; case PRE_MODIFY: @@ -18048,7 +18046,7 @@ output_move_double (rtx *operands, bool emit, int *count) if (emit) { output_asm_insn ("add%?\t%1, %1, %2", otherops); - output_asm_insn ("ldr%(d%)\t%0, [%1] @split", otherops); + output_asm_insn ("ldrd%?\t%0, [%1] @split", otherops); } if (count) *count = 2; @@ -18064,7 +18062,7 @@ output_move_double (rtx *operands, bool emit, int *count) && INTVAL (otherops[2]) < 256)) { if (emit) - output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops); + output_asm_insn ("ldrd%?\t%0, [%1, %2]!", otherops); } else { @@ -18090,7 +18088,7 @@ output_move_double (rtx *operands, bool emit, int *count) && INTVAL (otherops[2]) < 256)) { if (emit) - output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops); + output_asm_insn ("ldrd%?\t%0, [%1], %2", otherops); } else { @@ -18119,9 +18117,9 @@ output_move_double (rtx *operands, bool emit, int *count) if (emit) { if (TARGET_LDRD) - output_asm_insn ("ldr%(d%)\t%0, [%1]", operands); + output_asm_insn ("ldrd%?\t%0, [%1]", operands); else - output_asm_insn ("ldm%(ia%)\t%1, %M0", operands); + output_asm_insn ("ldmia%?\t%1, %M0", operands); } if (count) @@ -18145,19 +18143,19 @@ output_move_double (rtx *operands, bool emit, int *count) { case -8: if (emit) - output_asm_insn ("ldm%(db%)\t%1, %M0", otherops); + output_asm_insn ("ldmdb%?\t%1, %M0", otherops); return ""; case -4: if (TARGET_THUMB2) break; if (emit) - output_asm_insn ("ldm%(da%)\t%1, %M0", otherops); + output_asm_insn ("ldmda%?\t%1, %M0", otherops); return ""; case 4: if (TARGET_THUMB2) break; if (emit) - output_asm_insn ("ldm%(ib%)\t%1, %M0", otherops); + output_asm_insn ("ldmib%?\t%1, %M0", otherops); return ""; } } @@ -18185,7 +18183,7 @@ output_move_double (rtx *operands, bool emit, int *count) if (emit) { output_asm_insn ("add%?\t%0, %1, %2", otherops); - output_asm_insn ("ldr%(d%)\t%0, [%1]", operands); + output_asm_insn ("ldrd%?\t%0, [%1]", operands); } if (count) *count = 2; @@ -18194,7 +18192,7 @@ output_move_double (rtx *operands, bool emit, int *count) { otherops[0] = operands[0]; if (emit) - output_asm_insn ("ldr%(d%)\t%0, [%1, %2]", otherops); + output_asm_insn ("ldrd%?\t%0, [%1, %2]", otherops); } return ""; } @@ -18225,9 +18223,9 @@ output_move_double (rtx *operands, bool emit, int *count) *count = 2; if (TARGET_LDRD) - return "ldr%(d%)\t%0, [%1]"; + return "ldrd%?\t%0, [%1]"; - return "ldm%(ia%)\t%1, %M0"; + return "ldmia%?\t%1, %M0"; } else { @@ -18270,25 +18268,25 @@ output_move_double (rtx *operands, bool emit, int *count) if (emit) { if (TARGET_LDRD) - output_asm_insn ("str%(d%)\t%1, [%m0]", operands); + output_asm_insn ("strd%?\t%1, [%m0]", operands); else - output_asm_insn ("stm%(ia%)\t%m0, %M1", operands); + output_asm_insn ("stm%?\t%m0, %M1", operands); } break; case PRE_INC: gcc_assert (TARGET_LDRD); if (emit) - output_asm_insn ("str%(d%)\t%1, [%m0, #8]!", operands); + output_asm_insn ("strd%?\t%1, [%m0, #8]!", operands); break; case PRE_DEC: if (emit) { if (TARGET_LDRD) - output_asm_insn ("str%(d%)\t%1, [%m0, #-8]!", operands); + output_asm_insn ("strd%?\t%1, [%m0, #-8]!", operands); else - output_asm_insn ("stm%(db%)\t%m0!, %M1", operands); + output_asm_insn ("stmdb%?\t%m0!, %M1", operands); } break; @@ -18296,16 +18294,16 @@ output_move_double (rtx *operands, bool emit, int *count) if (emit) { if (TARGET_LDRD) - output_asm_insn ("str%(d%)\t%1, [%m0], #8", operands); + output_asm_insn ("strd%?\t%1, [%m0], #8", operands); else - output_asm_insn ("stm%(ia%)\t%m0!, %M1", operands); + output_asm_insn ("stm%?\t%m0!, %M1", operands); } break; case POST_DEC: gcc_assert (TARGET_LDRD); if (emit) - output_asm_insn ("str%(d%)\t%1, [%m0], #-8", operands); + output_asm_insn ("strd%?\t%1, [%m0], #-8", operands); break; case PRE_MODIFY: @@ -18345,12 +18343,12 @@ output_move_double (rtx *operands, bool emit, int *count) else if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY) { if (emit) - output_asm_insn ("str%(d%)\t%0, [%1, %2]!", otherops); + output_asm_insn ("strd%?\t%0, [%1, %2]!", otherops); } else { if (emit) - output_asm_insn ("str%(d%)\t%0, [%1], %2", otherops); + output_asm_insn ("strd%?\t%0, [%1], %2", otherops); } break; @@ -18362,21 +18360,21 @@ output_move_double (rtx *operands, bool emit, int *count) { case -8: if (emit) - output_asm_insn ("stm%(db%)\t%m0, %M1", operands); + output_asm_insn ("stmdb%?\t%m0, %M1", operands); return ""; case -4: if (TARGET_THUMB2) break; if (emit) - output_asm_insn ("stm%(da%)\t%m0, %M1", operands); + output_asm_insn ("stmda%?\t%m0, %M1", operands); return ""; case 4: if (TARGET_THUMB2) break; if (emit) - output_asm_insn ("stm%(ib%)\t%m0, %M1", operands); + output_asm_insn ("stmib%?\t%m0, %M1", operands); return ""; } } @@ -18390,7 +18388,7 @@ output_move_double (rtx *operands, bool emit, int *count) otherops[0] = operands[1]; otherops[1] = XEXP (XEXP (operands[0], 0), 0); if (emit) - output_asm_insn ("str%(d%)\t%0, [%1, %2]", otherops); + output_asm_insn ("strd%?\t%0, [%1, %2]", otherops); return ""; } /* Fall through */ @@ -18426,13 +18424,13 @@ output_move_quad (rtx *operands) switch (GET_CODE (XEXP (operands[1], 0))) { case REG: - output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands); + output_asm_insn ("ldmia%?\t%m1, %M0", operands); break; case LABEL_REF: case CONST: output_asm_insn ("adr%?\t%0, %1", operands); - output_asm_insn ("ldm%(ia%)\t%0, %M0", operands); + output_asm_insn ("ldmia%?\t%0, %M0", operands); break; default: @@ -18476,7 +18474,7 @@ output_move_quad (rtx *operands) switch (GET_CODE (XEXP (operands[0], 0))) { case REG: - output_asm_insn ("stm%(ia%)\t%m0, %M1", operands); + output_asm_insn ("stm%?\t%m0, %M1", operands); break; default: @@ -19510,10 +19508,7 @@ output_return_instruction (rtx operand, bool really_return, bool reverse, gcc_assert (stack_adjust == 0 || stack_adjust == 4); if (stack_adjust && arm_arch5 && TARGET_ARM) - if (TARGET_UNIFIED_ASM) sprintf (instr, "ldmib%s\t%%|sp, {", conditional); - else - sprintf (instr, "ldm%sib\t%%|sp, {", conditional); else { /* If we can't use ldmib (SA110 bug), @@ -19521,17 +19516,11 @@ output_return_instruction (rtx operand, bool really_return, bool reverse, if (stack_adjust) live_regs_mask |= 1 << 3; - if (TARGET_UNIFIED_ASM) - sprintf (instr, "ldmfd%s\t%%|sp, {", conditional); - else - sprintf (instr, "ldm%sfd\t%%|sp, {", conditional); + sprintf (instr, "ldmfd%s\t%%|sp, {", conditional); } } else - if (TARGET_UNIFIED_ASM) sprintf (instr, "pop%s\t{", conditional); - else - sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional); p = instr + strlen (instr); @@ -21804,37 +21793,17 @@ arm_print_operand (FILE *stream, rtx x, int code) arm_print_condition (stream); return; - case '(': - /* Nothing in unified syntax, otherwise the current condition code. */ - if (!TARGET_UNIFIED_ASM) - arm_print_condition (stream); - break; - - case ')': - /* The current condition code in unified syntax, otherwise nothing. */ - if (TARGET_UNIFIED_ASM) - arm_print_condition (stream); - break; - case '.': /* The current condition code for a condition code setting instruction. Preceded by 's' in unified syntax, otherwise followed by 's'. */ - if (TARGET_UNIFIED_ASM) - { - fputc('s', stream); - arm_print_condition (stream); - } - else - { - arm_print_condition (stream); - fputc('s', stream); - } + fputc('s', stream); + arm_print_condition (stream); return; case '!': /* If the instruction is conditionally executed then print the current condition code, otherwise print 's'. */ - gcc_assert (TARGET_THUMB2 && TARGET_UNIFIED_ASM); + gcc_assert (TARGET_THUMB2); if (current_insn_predicate) arm_print_condition (stream); else @@ -27243,20 +27212,16 @@ arm_output_shift(rtx * operands, int set_flags) char c; c = flag_chars[set_flags]; - if (TARGET_UNIFIED_ASM) + shift = shift_op(operands[3], &val); + if (shift) { - shift = shift_op(operands[3], &val); - if (shift) - { - if (val != -1) - operands[2] = GEN_INT(val); - sprintf (pattern, "%s%%%c\t%%0, %%1, %%2", shift, c); - } - else - sprintf (pattern, "mov%%%c\t%%0, %%1", c); + if (val != -1) + operands[2] = GEN_INT(val); + sprintf (pattern, "%s%%%c\t%%0, %%1, %%2", shift, c); } else - sprintf (pattern, "mov%%%c\t%%0, %%1%%S3", c); + sprintf (pattern, "mov%%%c\t%%0, %%1", c); + output_asm_insn (pattern, operands); return ""; } @@ -30005,10 +29970,8 @@ arm_valid_target_attribute_p (tree fndecl, tree ARG_UNUSED (name), void arm_declare_function_name (FILE *stream, const char *name, tree decl) { - if (TARGET_UNIFIED_ASM) - fprintf (stream, "\t.syntax unified\n"); - else - fprintf (stream, "\t.syntax divided\n"); + + fprintf (stream, "\t.syntax unified\n"); if (TARGET_THUMB) { diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 585bd1d95f3..a1a04a94ef2 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -237,10 +237,6 @@ extern void (*arm_lang_output_object_attributes_hook)(void); && (arm_disable_literal_pool \ || (!optimize_size && !current_tune->prefer_constant_pool))) -/* We could use unified syntax for arm mode, but for now we just use it - for thumb mode. */ -#define TARGET_UNIFIED_ASM (TARGET_THUMB) - /* Nonzero if this chip provides the DMB instruction. */ #define TARGET_HAVE_DMB (arm_arch6m || arm_arch7) @@ -2023,8 +2019,7 @@ extern int making_const_table; "\t.syntax divided\n") #undef ASM_APP_OFF -#define ASM_APP_OFF (TARGET_ARM ? "\t.arm\n\t.syntax divided\n" : \ - "\t.thumb\n\t.syntax unified\n") +#define ASM_APP_OFF "\t.syntax unified\n" /* Output a push or a pop instruction (only used when profiling). We can't push STATIC_CHAIN_REGNUM (r12) directly with Thumb-1. We know @@ -2035,10 +2030,7 @@ extern int making_const_table; #define ASM_OUTPUT_REG_PUSH(STREAM, REGNO) \ do \ { \ - if (TARGET_ARM) \ - asm_fprintf (STREAM,"\tstmfd\t%r!,{%r}\n", \ - STACK_POINTER_REGNUM, REGNO); \ - else if (TARGET_THUMB1 \ + if (TARGET_THUMB1 \ && (REGNO) == STATIC_CHAIN_REGNUM) \ { \ asm_fprintf (STREAM, "\tpush\t{r7}\n"); \ @@ -2054,11 +2046,8 @@ extern int making_const_table; #define ASM_OUTPUT_REG_POP(STREAM, REGNO) \ do \ { \ - if (TARGET_ARM) \ - asm_fprintf (STREAM, "\tldmfd\t%r!,{%r}\n", \ - STACK_POINTER_REGNUM, REGNO); \ - else if (TARGET_THUMB1 \ - && (REGNO) == STATIC_CHAIN_REGNUM) \ + if (TARGET_THUMB1 \ + && (REGNO) == STATIC_CHAIN_REGNUM) \ { \ asm_fprintf (STREAM, "\tpop\t{r7}\n"); \ asm_fprintf (STREAM, "\tmov\t%r, r7\n", REGNO);\ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 02e147ec4a4..8ebb1bfd221 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -622,9 +622,9 @@ (plus:SI (match_dup 1) (match_dup 2)))] "TARGET_ARM" "@ - add%.\\t%0, %1, %2 - sub%.\\t%0, %1, #%n2 - add%.\\t%0, %1, %2" + adds%?\\t%0, %1, %2 + subs%?\\t%0, %1, #%n2 + adds%?\\t%0, %1, %2" [(set_attr "conds" "set") (set_attr "type" "alus_imm,alus_imm,alus_sreg")] ) @@ -672,8 +672,8 @@ (match_operand:SI 3 "arm_addimm_operand" "I,L")))] "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])" "@ - add%.\\t%0, %1, %3 - sub%.\\t%0, %1, #%n3" + adds%?\\t%0, %1, %3 + subs%?\\t%0, %1, #%n3" [(set_attr "conds" "set") (set_attr "type" "alus_sreg")] ) @@ -729,9 +729,9 @@ (plus:SI (match_dup 1) (match_dup 2)))] "TARGET_32BIT" "@ - add%.\\t%0, %1, %2 - sub%.\\t%0, %1, #%n2 - add%.\\t%0, %1, %2" + adds%?\\t%0, %1, %2 + subs%?\\t%0, %1, #%n2 + adds%?\\t%0, %1, %2" [(set_attr "conds" "set") (set_attr "type" "alus_imm,alus_imm,alus_sreg")] ) @@ -746,9 +746,9 @@ (plus:SI (match_dup 1) (match_dup 2)))] "TARGET_32BIT" "@ - add%.\\t%0, %1, %2 - add%.\\t%0, %1, %2 - sub%.\\t%0, %1, #%n2" + adds%?\\t%0, %1, %2 + adds%?\\t%0, %1, %2 + subs%?\\t%0, %1, #%n2" [(set_attr "conds" "set") (set_attr "type" "alus_imm,alus_imm,alus_sreg")] ) @@ -856,7 +856,7 @@ (LTUGEU:SI (reg: CC_REGNUM) (const_int 0)))) (clobber (reg:CC CC_REGNUM))] "TARGET_32BIT" - "adc%.\\t%0, %1, %2" + "adcs%?\\t%0, %1, %2" [(set_attr "conds" "set") (set_attr "type" "adcs_reg")] ) @@ -1239,9 +1239,9 @@ (minus:SI (match_dup 1) (match_dup 2)))] "TARGET_32BIT" "@ - sub%.\\t%0, %1, %2 - sub%.\\t%0, %1, %2 - rsb%.\\t%0, %2, %1" + subs%?\\t%0, %1, %2 + subs%?\\t%0, %1, %2 + rsbs%?\\t%0, %2, %1" [(set_attr "conds" "set") (set_attr "type" "alus_imm,alus_sreg,alus_sreg")] ) @@ -1254,9 +1254,9 @@ (minus:SI (match_dup 1) (match_dup 2)))] "TARGET_32BIT" "@ - sub%.\\t%0, %1, %2 - sub%.\\t%0, %1, %2 - rsb%.\\t%0, %2, %1" + subs%?\\t%0, %1, %2 + subs%?\\t%0, %1, %2 + rsbs%?\\t%0, %2, %1" [(set_attr "conds" "set") (set_attr "type" "alus_imm,alus_sreg,alus_sreg")] ) @@ -1335,7 +1335,7 @@ (set (match_operand:SI 0 "s_register_operand" "=&r,&r") (mult:SI (match_dup 2) (match_dup 1)))] "TARGET_ARM && !arm_arch6" - "mul%.\\t%0, %2, %1" + "muls%?\\t%0, %2, %1" [(set_attr "conds" "set") (set_attr "type" "muls")] ) @@ -1349,7 +1349,7 @@ (set (match_operand:SI 0 "s_register_operand" "=r") (mult:SI (match_dup 2) (match_dup 1)))] "TARGET_ARM && arm_arch6 && optimize_size" - "mul%.\\t%0, %2, %1" + "muls%?\\t%0, %2, %1" [(set_attr "conds" "set") (set_attr "type" "muls")] ) @@ -1362,7 +1362,7 @@ (const_int 0))) (clobber (match_scratch:SI 0 "=&r,&r"))] "TARGET_ARM && !arm_arch6" - "mul%.\\t%0, %2, %1" + "muls%?\\t%0, %2, %1" [(set_attr "conds" "set") (set_attr "type" "muls")] ) @@ -1375,7 +1375,7 @@ (const_int 0))) (clobber (match_scratch:SI 0 "=r"))] "TARGET_ARM && arm_arch6 && optimize_size" - "mul%.\\t%0, %2, %1" + "muls%?\\t%0, %2, %1" [(set_attr "conds" "set") (set_attr "type" "muls")] ) @@ -1419,7 +1419,7 @@ (plus:SI (mult:SI (match_dup 2) (match_dup 1)) (match_dup 3)))] "TARGET_ARM && arm_arch6" - "mla%.\\t%0, %2, %1, %3" + "mlas%?\\t%0, %2, %1, %3" [(set_attr "conds" "set") (set_attr "type" "mlas")] ) @@ -1436,7 +1436,7 @@ (plus:SI (mult:SI (match_dup 2) (match_dup 1)) (match_dup 3)))] "TARGET_ARM && arm_arch6 && optimize_size" - "mla%.\\t%0, %2, %1, %3" + "mlas%?\\t%0, %2, %1, %3" [(set_attr "conds" "set") (set_attr "type" "mlas")] ) @@ -1451,7 +1451,7 @@ (const_int 0))) (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))] "TARGET_ARM && !arm_arch6" - "mla%.\\t%0, %2, %1, %3" + "mlas%?\\t%0, %2, %1, %3" [(set_attr "conds" "set") (set_attr "type" "mlas")] ) @@ -1466,7 +1466,7 @@ (const_int 0))) (clobber (match_scratch:SI 0 "=r"))] "TARGET_ARM && arm_arch6 && optimize_size" - "mla%.\\t%0, %2, %1, %3" + "mlas%?\\t%0, %2, %1, %3" [(set_attr "conds" "set") (set_attr "type" "mlas")] ) @@ -2195,9 +2195,9 @@ (and:SI (match_dup 1) (match_dup 2)))] "TARGET_32BIT" "@ - and%.\\t%0, %1, %2 - bic%.\\t%0, %1, #%B2 - and%.\\t%0, %1, %2" + ands%?\\t%0, %1, %2 + bics%?\\t%0, %1, #%B2 + ands%?\\t%0, %1, %2" [(set_attr "conds" "set") (set_attr "type" "logics_imm,logics_imm,logics_reg")] ) @@ -2212,7 +2212,7 @@ "TARGET_32BIT" "@ tst%?\\t%0, %1 - bic%.\\t%2, %0, #%B1 + bics%?\\t%2, %0, #%B1 tst%?\\t%0, %1" [(set_attr "conds" "set") (set_attr "type" "logics_imm,logics_imm,logics_reg")] @@ -2796,7 +2796,7 @@ (const_int 0))) (clobber (match_scratch:SI 4 "=r"))] "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))" - "bic%.%?\\t%4, %3, %1%S0" + "bics%?\\t%4, %3, %1%S0" [(set_attr "predicable" "yes") (set_attr "predicable_short_it" "no") (set_attr "conds" "set") @@ -2822,7 +2822,7 @@ (match_dup 2)])) (match_dup 3)))])] "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))" - "bic%.%?\\t%4, %3, %1%S0" + "bics%?\\t%4, %3, %1%S0" [(set_attr "predicable" "yes") (set_attr "predicable_short_it" "no") (set_attr "conds" "set") @@ -2841,7 +2841,7 @@ (set (match_operand:SI 0 "s_register_operand" "=r") (and:SI (not:SI (match_dup 2)) (match_dup 1)))] "TARGET_32BIT" - "bic%.\\t%0, %1, %2" + "bics\\t%0, %1, %2" [(set_attr "conds" "set") (set_attr "type" "logics_shift_reg")] ) @@ -2854,7 +2854,7 @@ (const_int 0))) (clobber (match_scratch:SI 0 "=r"))] "TARGET_32BIT" - "bic%.\\t%0, %1, %2" + "bics\\t%0, %1, %2" [(set_attr "conds" "set") (set_attr "type" "logics_shift_reg")] ) @@ -3023,7 +3023,7 @@ (set (match_operand:SI 0 "s_register_operand" "=r,r") (ior:SI (match_dup 1) (match_dup 2)))] "TARGET_32BIT" - "orr%.\\t%0, %1, %2" + "orrs%?\\t%0, %1, %2" [(set_attr "conds" "set") (set_attr "type" "logics_imm,logics_reg")] ) @@ -3035,7 +3035,7 @@ (const_int 0))) (clobber (match_scratch:SI 0 "=r,r"))] "TARGET_32BIT" - "orr%.\\t%0, %1, %2" + "orrs%?\\t%0, %1, %2" [(set_attr "conds" "set") (set_attr "type" "logics_imm,logics_reg")] ) @@ -3182,7 +3182,7 @@ (set (match_operand:SI 0 "s_register_operand" "=r,r") (xor:SI (match_dup 1) (match_dup 2)))] "TARGET_32BIT" - "eor%.\\t%0, %1, %2" + "eors%?\\t%0, %1, %2" [(set_attr "conds" "set") (set_attr "type" "logics_imm,logics_reg")] ) @@ -3455,44 +3455,6 @@ (set_attr "type" "multiple,multiple")] ) -;; t = (s/u)min (x, y) -;; cc = cmp (t, z) -;; is the same as -;; cmp x, z -;; cmpge(u) y, z - -(define_insn_and_split "*arm_smin_cmp" - [(set (reg:CC CC_REGNUM) - (compare:CC - (smin:SI (match_operand:SI 0 "s_register_operand" "r") - (match_operand:SI 1 "s_register_operand" "r")) - (match_operand:SI 2 "s_register_operand" "r")))] - "TARGET_32BIT" - "#" - "&& reload_completed" - [(set (reg:CC CC_REGNUM) - (compare:CC (match_dup 0) (match_dup 2))) - (cond_exec (ge:CC (reg:CC CC_REGNUM) (const_int 0)) - (set (reg:CC CC_REGNUM) - (compare:CC (match_dup 1) (match_dup 2))))] -) - -(define_insn_and_split "*arm_umin_cmp" - [(set (reg:CC CC_REGNUM) - (compare:CC - (umin:SI (match_operand:SI 0 "s_register_operand" "r") - (match_operand:SI 1 "s_register_operand" "r")) - (match_operand:SI 2 "s_register_operand" "r")))] - "TARGET_32BIT" - "#" - "&& reload_completed" - [(set (reg:CC CC_REGNUM) - (compare:CC (match_dup 0) (match_dup 2))) - (cond_exec (geu:CC (reg:CC CC_REGNUM) (const_int 0)) - (set (reg:CC CC_REGNUM) - (compare:CC (match_dup 1) (match_dup 2))))] -) - (define_expand "umaxsi3" [(parallel [ (set (match_operand:SI 0 "s_register_operand" "") @@ -4066,7 +4028,7 @@ (set (match_operand:SI 0 "s_register_operand" "=r,r") (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))] "TARGET_32BIT" - "mvn%.\\t%0, %1%S3" + "mvns%?\\t%0, %1%S3" [(set_attr "conds" "set") (set_attr "shift" "1") (set_attr "arch" "32,a") @@ -4081,7 +4043,7 @@ (const_int 0))) (clobber (match_scratch:SI 0 "=r,r"))] "TARGET_32BIT" - "mvn%.\\t%0, %1%S3" + "mvns%?\\t%0, %1%S3" [(set_attr "conds" "set") (set_attr "shift" "1") (set_attr "arch" "32,a") @@ -4271,7 +4233,7 @@ (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")] UNSPEC_UNALIGNED_LOAD)))] "unaligned_access && TARGET_32BIT" - "ldr%(sh%)\t%0, %1\t@ unaligned" + "ldrsh%?\t%0, %1\t@ unaligned" [(set_attr "arch" "t2,any") (set_attr "length" "2,4") (set_attr "predicable" "yes") @@ -4284,7 +4246,7 @@ (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")] UNSPEC_UNALIGNED_LOAD)))] "unaligned_access && TARGET_32BIT" - "ldr%(h%)\t%0, %1\t@ unaligned" + "ldrh%?\t%0, %1\t@ unaligned" [(set_attr "arch" "t2,any") (set_attr "length" "2,4") (set_attr "predicable" "yes") @@ -4308,7 +4270,7 @@ (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")] UNSPEC_UNALIGNED_STORE))] "unaligned_access && TARGET_32BIT" - "str%(h%)\t%1, %0\t@ unaligned" + "strh%?\t%1, %0\t@ unaligned" [(set_attr "arch" "t2,any") (set_attr "length" "2,4") (set_attr "predicable" "yes") @@ -4818,7 +4780,7 @@ (set (match_operand:SI 0 "s_register_operand" "=r") (not:SI (match_dup 1)))] "TARGET_32BIT" - "mvn%.\\t%0, %1" + "mvns%?\\t%0, %1" [(set_attr "conds" "set") (set_attr "type" "mvn_reg")] ) @@ -4829,7 +4791,7 @@ (const_int 0))) (clobber (match_scratch:SI 0 "=r"))] "TARGET_32BIT" - "mvn%.\\t%0, %1" + "mvns%?\\t%0, %1" [(set_attr "conds" "set") (set_attr "type" "mvn_reg")] ) @@ -5060,7 +5022,7 @@ "TARGET_ARM && arm_arch4 && !arm_arch6" "@ # - ldr%(h%)\\t%0, %1" + ldrh%?\\t%0, %1" [(set_attr "type" "alu_shift_reg,load_byte") (set_attr "predicable" "yes")] ) @@ -5071,7 +5033,7 @@ "TARGET_ARM && arm_arch6" "@ uxth%?\\t%0, %1 - ldr%(h%)\\t%0, %1" + ldrh%?\\t%0, %1" [(set_attr "predicable" "yes") (set_attr "type" "extend,load_byte")] ) @@ -5130,7 +5092,7 @@ "TARGET_ARM && !arm_arch6" "@ # - ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2" + ldrb%?\\t%0, %1\\t%@ zero_extendqisi2" [(set_attr "length" "8,4") (set_attr "type" "alu_shift_reg,load_byte") (set_attr "predicable" "yes")] @@ -5141,8 +5103,8 @@ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))] "TARGET_ARM && arm_arch6" "@ - uxtb%(%)\\t%0, %1 - ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2" + uxtb%?\\t%0, %1 + ldrb%?\\t%0, %1\\t%@ zero_extendqisi2" [(set_attr "type" "extend,load_byte") (set_attr "predicable" "yes")] ) @@ -5302,7 +5264,7 @@ "TARGET_ARM && arm_arch4 && !arm_arch6" "@ # - ldr%(sh%)\\t%0, %1" + ldrsh%?\\t%0, %1" [(set_attr "length" "8,4") (set_attr "type" "alu_shift_reg,load_byte") (set_attr "predicable" "yes")] @@ -5315,7 +5277,7 @@ "TARGET_32BIT && arm_arch6" "@ sxth%?\\t%0, %1 - ldr%(sh%)\\t%0, %1" + ldrsh%?\\t%0, %1" [(set_attr "type" "extend,load_byte") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")] @@ -5358,7 +5320,7 @@ [(set (match_operand:HI 0 "s_register_operand" "=r") (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))] "TARGET_ARM && arm_arch4" - "ldr%(sb%)\\t%0, %1" + "ldrsb%?\\t%0, %1" [(set_attr "type" "load_byte") (set_attr "predicable" "yes")] ) @@ -5397,7 +5359,7 @@ "TARGET_ARM && arm_arch4 && !arm_arch6" "@ # - ldr%(sb%)\\t%0, %1" + ldrsb%?\\t%0, %1" [(set_attr "length" "8,4") (set_attr "type" "alu_shift_reg,load_byte") (set_attr "predicable" "yes")] @@ -5410,7 +5372,7 @@ "TARGET_ARM && arm_arch6" "@ sxtb%?\\t%0, %1 - ldr%(sb%)\\t%0, %1" + ldrsb%?\\t%0, %1" [(set_attr "type" "extend,load_byte") (set_attr "predicable" "yes")] ) @@ -6065,7 +6027,7 @@ "TARGET_32BIT" "@ cmp%?\\t%0, #0 - sub%.\\t%0, %1, #0" + subs%?\\t%0, %1, #0" [(set_attr "conds" "set") (set_attr "type" "alus_imm,alus_imm")] ) @@ -6441,8 +6403,8 @@ mov%?\\t%0, %1\\t%@ movhi mvn%?\\t%0, #%B1\\t%@ movhi movw%?\\t%0, %L1\\t%@ movhi - str%(h%)\\t%1, %0\\t%@ movhi - ldr%(h%)\\t%0, %1\\t%@ movhi" + strh%?\\t%1, %0\\t%@ movhi + ldrh%?\\t%0, %1\\t%@ movhi" [(set_attr "predicable" "yes") (set_attr "pool_range" "*,*,*,*,256") (set_attr "neg_pool_range" "*,*,*,*,244") @@ -6584,10 +6546,10 @@ mov%?\\t%0, %1 mov%?\\t%0, %1 mvn%?\\t%0, #%B1 - ldr%(b%)\\t%0, %1 - str%(b%)\\t%1, %0 - ldr%(b%)\\t%0, %1 - str%(b%)\\t%1, %0" + ldrb%?\\t%0, %1 + strb%?\\t%1, %0 + ldrb%?\\t%0, %1 + strb%?\\t%1, %0" [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "yes,yes,yes,no,no,no,no,no,no") @@ -6627,9 +6589,9 @@ switch (which_alternative) { case 0: /* ARM register from memory */ - return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\"; + return \"ldrh%?\\t%0, %1\\t%@ __fp16\"; case 1: /* memory from ARM register */ - return \"str%(h%)\\t%1, %0\\t%@ __fp16\"; + return \"strh%?\\t%1, %0\\t%@ __fp16\"; case 2: /* ARM register from ARM register */ return \"mov%?\\t%0, %1\\t%@ __fp16\"; case 3: /* ARM register from constant */ @@ -7141,7 +7103,7 @@ (const_int 0))) (clobber (match_scratch:SI 1 "=r"))] "TARGET_32BIT" - "orr%.\\t%1, %Q0, %R0" + "orrs%?\\t%1, %Q0, %R0" [(set_attr "conds" "set") (set_attr "type" "logics_reg")] ) @@ -8385,13 +8347,7 @@ (define_insn "nop" [(const_int 0)] "TARGET_EITHER" - "* - if (TARGET_UNIFIED_ASM) - return \"nop\"; - if (TARGET_ARM) - return \"mov%?\\t%|r0, %|r0\\t%@ nop\"; - return \"mov\\tr8, r8\"; - " + "nop" [(set (attr "length") (if_then_else (eq_attr "is_thumb" "yes") (const_int 2) @@ -8479,7 +8435,7 @@ (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) (match_dup 2)]))] "TARGET_32BIT" - "%i1%.\\t%0, %2, %4%S3" + "%i1s%?\\t%0, %2, %4%S3" [(set_attr "conds" "set") (set_attr "shift" "4") (set_attr "arch" "32,a") @@ -8496,7 +8452,7 @@ (const_int 0))) (clobber (match_scratch:SI 0 "=r,r"))] "TARGET_32BIT" - "%i1%.\\t%0, %2, %4%S3" + "%i1s%?\\t%0, %2, %4%S3" [(set_attr "conds" "set") (set_attr "shift" "4") (set_attr "arch" "32,a") @@ -8527,7 +8483,7 @@ (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) (match_dup 4)])))] "TARGET_32BIT" - "sub%.\\t%0, %1, %3%S2" + "subs%?\\t%0, %1, %3%S2" [(set_attr "conds" "set") (set_attr "shift" "3") (set_attr "arch" "32,a,a") @@ -8543,7 +8499,7 @@ (const_int 0))) (clobber (match_scratch:SI 0 "=r,r,r"))] "TARGET_32BIT" - "sub%.\\t%0, %1, %3%S2" + "subs%?\\t%0, %1, %3%S2" [(set_attr "conds" "set") (set_attr "shift" "3") (set_attr "arch" "32,a,a") @@ -10247,7 +10203,7 @@ if (val1 == 4 || val2 == 4) /* Other val must be 8, since we know they are adjacent and neither is zero. */ - output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm); + output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm); else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1)) { ldm[0] = ops[0] = operands[4]; @@ -10255,9 +10211,9 @@ ops[2] = GEN_INT (val1); output_add_immediate (ops); if (val1 < val2) - output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm); + output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm); else - output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm); + output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm); } else { @@ -10274,16 +10230,16 @@ else if (val1 != 0) { if (val1 < val2) - output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm); + output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm); else - output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm); + output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm); } else { if (val1 < val2) - output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm); + output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm); else - output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm); + output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm); } output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith); return \"\"; @@ -10619,9 +10575,7 @@ int i; char pattern[100]; - if (TARGET_ARM) - strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\"); - else if (TARGET_THUMB2) + if (TARGET_32BIT) strcpy (pattern, \"push%?\\t{%1\"); else strcpy (pattern, \"push\\t{%1\"); diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt index 666ff732264..c12f2b13a03 100644 --- a/gcc/config/arm/arm.opt +++ b/gcc/config/arm/arm.opt @@ -280,4 +280,4 @@ Assume loading data from flash is slower than fetching instructions. masm-syntax-unified Target Report Var(inline_asm_unified) Init(0) Save -Assume unified syntax for Thumb inline assembly code. +Assume unified syntax for inline assembly code. diff --git a/gcc/config/arm/ldmstm.md b/gcc/config/arm/ldmstm.md index 20d6b4c364a..ebb09ab86e7 100644 --- a/gcc/config/arm/ldmstm.md +++ b/gcc/config/arm/ldmstm.md @@ -21,7 +21,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ -(define_insn "*ldm4_ia" +(define_insn "*ldm4_" [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (match_operand:SI 5 "s_register_operand" "rk"))) @@ -35,7 +35,7 @@ (mem:SI (plus:SI (match_dup 5) (const_int 12))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" - "ldm%(ia%)\t%5, {%1, %2, %3, %4}" + "ldm%?\t%5, {%1, %2, %3, %4}" [(set_attr "type" "load4") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -54,7 +54,7 @@ (mem:SI (plus:SI (match_dup 5) (const_int 12))))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4" - "ldm%(ia%)\t%5, {%1, %2, %3, %4}" + "ldmia\t%5, {%1, %2, %3, %4}" [(set_attr "type" "load4")]) (define_insn "*ldm4_ia_update" @@ -73,7 +73,7 @@ (mem:SI (plus:SI (match_dup 5) (const_int 12))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 5" - "ldm%(ia%)\t%5!, {%1, %2, %3, %4}" + "ldmia%?\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "load4") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -94,10 +94,10 @@ (mem:SI (plus:SI (match_dup 5) (const_int 12))))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5" - "ldm%(ia%)\t%5!, {%1, %2, %3, %4}" + "ldmia\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "load4")]) -(define_insn "*stm4_ia" +(define_insn "*stm4_" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (match_operand:SI 5 "s_register_operand" "rk")) (match_operand:SI 1 "arm_hard_general_register_operand" "")) @@ -108,7 +108,7 @@ (set (mem:SI (plus:SI (match_dup 5) (const_int 12))) (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" - "stm%(ia%)\t%5, {%1, %2, %3, %4}" + "stm%?\t%5, {%1, %2, %3, %4}" [(set_attr "type" "store4") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -126,7 +126,7 @@ (set (mem:SI (plus:SI (match_dup 5) (const_int 12))) (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 5" - "stm%(ia%)\t%5!, {%1, %2, %3, %4}" + "stmia%?\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "store4") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -144,7 +144,7 @@ (set (mem:SI (plus:SI (match_dup 5) (const_int 12))) (match_operand:SI 4 "low_register_operand" ""))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5" - "stm%(ia%)\t%5!, {%1, %2, %3, %4}" + "stmia\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "store4")]) (define_insn "*ldm4_ib" @@ -162,7 +162,7 @@ (mem:SI (plus:SI (match_dup 5) (const_int 16))))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" - "ldm%(ib%)\t%5, {%1, %2, %3, %4}" + "ldmib%?\t%5, {%1, %2, %3, %4}" [(set_attr "type" "load4") (set_attr "predicable" "yes")]) @@ -183,7 +183,7 @@ (mem:SI (plus:SI (match_dup 5) (const_int 16))))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 5" - "ldm%(ib%)\t%5!, {%1, %2, %3, %4}" + "ldmib%?\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "load4") (set_attr "predicable" "yes")]) @@ -198,7 +198,7 @@ (set (mem:SI (plus:SI (match_dup 5) (const_int 16))) (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" - "stm%(ib%)\t%5, {%1, %2, %3, %4}" + "stmib%?\t%5, {%1, %2, %3, %4}" [(set_attr "type" "store4") (set_attr "predicable" "yes")]) @@ -215,7 +215,7 @@ (set (mem:SI (plus:SI (match_dup 5) (const_int 16))) (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 5" - "stm%(ib%)\t%5!, {%1, %2, %3, %4}" + "stmib%?\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "store4") (set_attr "predicable" "yes")]) @@ -233,7 +233,7 @@ (set (match_operand:SI 4 "arm_hard_general_register_operand" "") (mem:SI (match_dup 5)))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" - "ldm%(da%)\t%5, {%1, %2, %3, %4}" + "ldmda%?\t%5, {%1, %2, %3, %4}" [(set_attr "type" "load4") (set_attr "predicable" "yes")]) @@ -253,7 +253,7 @@ (set (match_operand:SI 4 "arm_hard_general_register_operand" "") (mem:SI (match_dup 5)))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 5" - "ldm%(da%)\t%5!, {%1, %2, %3, %4}" + "ldmda%?\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "load4") (set_attr "predicable" "yes")]) @@ -268,7 +268,7 @@ (set (mem:SI (match_dup 5)) (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" - "stm%(da%)\t%5, {%1, %2, %3, %4}" + "stmda%?\t%5, {%1, %2, %3, %4}" [(set_attr "type" "store4") (set_attr "predicable" "yes")]) @@ -285,7 +285,7 @@ (set (mem:SI (match_dup 5)) (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 5" - "stm%(da%)\t%5!, {%1, %2, %3, %4}" + "stmda%?\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "store4") (set_attr "predicable" "yes")]) @@ -304,7 +304,7 @@ (mem:SI (plus:SI (match_dup 5) (const_int -4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" - "ldm%(db%)\t%5, {%1, %2, %3, %4}" + "ldmdb%?\t%5, {%1, %2, %3, %4}" [(set_attr "type" "load4") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -326,7 +326,7 @@ (mem:SI (plus:SI (match_dup 5) (const_int -4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 5" - "ldm%(db%)\t%5!, {%1, %2, %3, %4}" + "ldmdb%?\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "load4") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -342,7 +342,7 @@ (set (mem:SI (plus:SI (match_dup 5) (const_int -4))) (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" - "stm%(db%)\t%5, {%1, %2, %3, %4}" + "stmdb%?\t%5, {%1, %2, %3, %4}" [(set_attr "type" "store4") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -360,7 +360,7 @@ (set (mem:SI (plus:SI (match_dup 5) (const_int -4))) (match_operand:SI 4 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 5" - "stm%(db%)\t%5!, {%1, %2, %3, %4}" + "stmdb%?\t%5!, {%1, %2, %3, %4}" [(set_attr "type" "store4") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -472,7 +472,7 @@ FAIL; }) -(define_insn "*ldm3_ia" +(define_insn "*ldm3_" [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (match_operand:SI 4 "s_register_operand" "rk"))) @@ -483,7 +483,7 @@ (mem:SI (plus:SI (match_dup 4) (const_int 8))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" - "ldm%(ia%)\t%4, {%1, %2, %3}" + "ldm%?\t%4, {%1, %2, %3}" [(set_attr "type" "load3") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -499,7 +499,7 @@ (mem:SI (plus:SI (match_dup 4) (const_int 8))))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3" - "ldm%(ia%)\t%4, {%1, %2, %3}" + "ldmia\t%4, {%1, %2, %3}" [(set_attr "type" "load3")]) (define_insn "*ldm3_ia_update" @@ -515,7 +515,7 @@ (mem:SI (plus:SI (match_dup 4) (const_int 8))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" - "ldm%(ia%)\t%4!, {%1, %2, %3}" + "ldmia%?\t%4!, {%1, %2, %3}" [(set_attr "type" "load3") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -533,10 +533,10 @@ (mem:SI (plus:SI (match_dup 4) (const_int 8))))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4" - "ldm%(ia%)\t%4!, {%1, %2, %3}" + "ldmia\t%4!, {%1, %2, %3}" [(set_attr "type" "load3")]) -(define_insn "*stm3_ia" +(define_insn "*stm3_" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (match_operand:SI 4 "s_register_operand" "rk")) (match_operand:SI 1 "arm_hard_general_register_operand" "")) @@ -545,7 +545,7 @@ (set (mem:SI (plus:SI (match_dup 4) (const_int 8))) (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" - "stm%(ia%)\t%4, {%1, %2, %3}" + "stm%?\t%4, {%1, %2, %3}" [(set_attr "type" "store3") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -561,7 +561,7 @@ (set (mem:SI (plus:SI (match_dup 4) (const_int 8))) (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" - "stm%(ia%)\t%4!, {%1, %2, %3}" + "stmia%?\t%4!, {%1, %2, %3}" [(set_attr "type" "store3") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -577,7 +577,7 @@ (set (mem:SI (plus:SI (match_dup 4) (const_int 8))) (match_operand:SI 3 "low_register_operand" ""))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4" - "stm%(ia%)\t%4!, {%1, %2, %3}" + "stmia\t%4!, {%1, %2, %3}" [(set_attr "type" "store3")]) (define_insn "*ldm3_ib" @@ -592,7 +592,7 @@ (mem:SI (plus:SI (match_dup 4) (const_int 12))))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" - "ldm%(ib%)\t%4, {%1, %2, %3}" + "ldmib%?\t%4, {%1, %2, %3}" [(set_attr "type" "load3") (set_attr "predicable" "yes")]) @@ -610,7 +610,7 @@ (mem:SI (plus:SI (match_dup 4) (const_int 12))))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" - "ldm%(ib%)\t%4!, {%1, %2, %3}" + "ldmib%?\t%4!, {%1, %2, %3}" [(set_attr "type" "load3") (set_attr "predicable" "yes")]) @@ -623,7 +623,7 @@ (set (mem:SI (plus:SI (match_dup 4) (const_int 12))) (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" - "stm%(ib%)\t%4, {%1, %2, %3}" + "stmib%?\t%4, {%1, %2, %3}" [(set_attr "type" "store3") (set_attr "predicable" "yes")]) @@ -638,7 +638,7 @@ (set (mem:SI (plus:SI (match_dup 4) (const_int 12))) (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" - "stm%(ib%)\t%4!, {%1, %2, %3}" + "stmib%?\t%4!, {%1, %2, %3}" [(set_attr "type" "store3") (set_attr "predicable" "yes")]) @@ -653,7 +653,7 @@ (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (match_dup 4)))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" - "ldm%(da%)\t%4, {%1, %2, %3}" + "ldmda%?\t%4, {%1, %2, %3}" [(set_attr "type" "load3") (set_attr "predicable" "yes")]) @@ -670,7 +670,7 @@ (set (match_operand:SI 3 "arm_hard_general_register_operand" "") (mem:SI (match_dup 4)))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" - "ldm%(da%)\t%4!, {%1, %2, %3}" + "ldmda%?\t%4!, {%1, %2, %3}" [(set_attr "type" "load3") (set_attr "predicable" "yes")]) @@ -683,7 +683,7 @@ (set (mem:SI (match_dup 4)) (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" - "stm%(da%)\t%4, {%1, %2, %3}" + "stmda%?\t%4, {%1, %2, %3}" [(set_attr "type" "store3") (set_attr "predicable" "yes")]) @@ -698,7 +698,7 @@ (set (mem:SI (match_dup 4)) (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 4" - "stm%(da%)\t%4!, {%1, %2, %3}" + "stmda%?\t%4!, {%1, %2, %3}" [(set_attr "type" "store3") (set_attr "predicable" "yes")]) @@ -714,7 +714,7 @@ (mem:SI (plus:SI (match_dup 4) (const_int -4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" - "ldm%(db%)\t%4, {%1, %2, %3}" + "ldmdb%?\t%4, {%1, %2, %3}" [(set_attr "type" "load3") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -733,7 +733,7 @@ (mem:SI (plus:SI (match_dup 4) (const_int -4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" - "ldm%(db%)\t%4!, {%1, %2, %3}" + "ldmdb%?\t%4!, {%1, %2, %3}" [(set_attr "type" "load3") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -747,7 +747,7 @@ (set (mem:SI (plus:SI (match_dup 4) (const_int -4))) (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" - "stm%(db%)\t%4, {%1, %2, %3}" + "stmdb%?\t%4, {%1, %2, %3}" [(set_attr "type" "store3") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -763,7 +763,7 @@ (set (mem:SI (plus:SI (match_dup 4) (const_int -4))) (match_operand:SI 3 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 4" - "stm%(db%)\t%4!, {%1, %2, %3}" + "stmdb%?\t%4!, {%1, %2, %3}" [(set_attr "type" "store3") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -861,7 +861,7 @@ FAIL; }) -(define_insn "*ldm2_ia" +(define_insn "*ldm2_" [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 1 "arm_hard_general_register_operand" "") (mem:SI (match_operand:SI 3 "s_register_operand" "rk"))) @@ -869,7 +869,7 @@ (mem:SI (plus:SI (match_dup 3) (const_int 4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 2" - "ldm%(ia%)\t%3, {%1, %2}" + "ldm%?\t%3, {%1, %2}" [(set_attr "type" "load2") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -882,7 +882,7 @@ (mem:SI (plus:SI (match_dup 3) (const_int 4))))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 2" - "ldm%(ia%)\t%3, {%1, %2}" + "ldmia\t%3, {%1, %2}" [(set_attr "type" "load2")]) (define_insn "*ldm2_ia_update" @@ -895,7 +895,7 @@ (mem:SI (plus:SI (match_dup 3) (const_int 4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" - "ldm%(ia%)\t%3!, {%1, %2}" + "ldmia%?\t%3!, {%1, %2}" [(set_attr "type" "load2") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -910,17 +910,17 @@ (mem:SI (plus:SI (match_dup 3) (const_int 4))))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3" - "ldm%(ia%)\t%3!, {%1, %2}" + "ldmia\t%3!, {%1, %2}" [(set_attr "type" "load2")]) -(define_insn "*stm2_ia" +(define_insn "*stm2_" [(match_parallel 0 "store_multiple_operation" [(set (mem:SI (match_operand:SI 3 "s_register_operand" "rk")) (match_operand:SI 1 "arm_hard_general_register_operand" "")) (set (mem:SI (plus:SI (match_dup 3) (const_int 4))) (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 2" - "stm%(ia%)\t%3, {%1, %2}" + "stm%?\t%3, {%1, %2}" [(set_attr "type" "store2") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -934,7 +934,7 @@ (set (mem:SI (plus:SI (match_dup 3) (const_int 4))) (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" - "stm%(ia%)\t%3!, {%1, %2}" + "stmia%?\t%3!, {%1, %2}" [(set_attr "type" "store2") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -948,7 +948,7 @@ (set (mem:SI (plus:SI (match_dup 3) (const_int 4))) (match_operand:SI 2 "low_register_operand" ""))])] "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3" - "stm%(ia%)\t%3!, {%1, %2}" + "stmia\t%3!, {%1, %2}" [(set_attr "type" "store2")]) (define_insn "*ldm2_ib" @@ -960,7 +960,7 @@ (mem:SI (plus:SI (match_dup 3) (const_int 8))))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 2" - "ldm%(ib%)\t%3, {%1, %2}" + "ldmib%?\t%3, {%1, %2}" [(set_attr "type" "load2") (set_attr "predicable" "yes")]) @@ -975,7 +975,7 @@ (mem:SI (plus:SI (match_dup 3) (const_int 8))))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" - "ldm%(ib%)\t%3!, {%1, %2}" + "ldmib%?\t%3!, {%1, %2}" [(set_attr "type" "load2") (set_attr "predicable" "yes")]) @@ -986,7 +986,7 @@ (set (mem:SI (plus:SI (match_dup 3) (const_int 8))) (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 2" - "stm%(ib%)\t%3, {%1, %2}" + "stmib%?\t%3, {%1, %2}" [(set_attr "type" "store2") (set_attr "predicable" "yes")]) @@ -999,7 +999,7 @@ (set (mem:SI (plus:SI (match_dup 3) (const_int 8))) (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" - "stm%(ib%)\t%3!, {%1, %2}" + "stmib%?\t%3!, {%1, %2}" [(set_attr "type" "store2") (set_attr "predicable" "yes")]) @@ -1011,7 +1011,7 @@ (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (match_dup 3)))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 2" - "ldm%(da%)\t%3, {%1, %2}" + "ldmda%?\t%3, {%1, %2}" [(set_attr "type" "load2") (set_attr "predicable" "yes")]) @@ -1025,7 +1025,7 @@ (set (match_operand:SI 2 "arm_hard_general_register_operand" "") (mem:SI (match_dup 3)))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" - "ldm%(da%)\t%3!, {%1, %2}" + "ldmda%?\t%3!, {%1, %2}" [(set_attr "type" "load2") (set_attr "predicable" "yes")]) @@ -1036,7 +1036,7 @@ (set (mem:SI (match_dup 3)) (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 2" - "stm%(da%)\t%3, {%1, %2}" + "stmda%?\t%3, {%1, %2}" [(set_attr "type" "store2") (set_attr "predicable" "yes")]) @@ -1049,7 +1049,7 @@ (set (mem:SI (match_dup 3)) (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_ARM && XVECLEN (operands[0], 0) == 3" - "stm%(da%)\t%3!, {%1, %2}" + "stmda%?\t%3!, {%1, %2}" [(set_attr "type" "store2") (set_attr "predicable" "yes")]) @@ -1062,7 +1062,7 @@ (mem:SI (plus:SI (match_dup 3) (const_int -4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 2" - "ldm%(db%)\t%3, {%1, %2}" + "ldmdb%?\t%3, {%1, %2}" [(set_attr "type" "load2") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -1078,7 +1078,7 @@ (mem:SI (plus:SI (match_dup 3) (const_int -4))))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" - "ldm%(db%)\t%3!, {%1, %2}" + "ldmdb%?\t%3!, {%1, %2}" [(set_attr "type" "load2") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -1090,7 +1090,7 @@ (set (mem:SI (plus:SI (match_dup 3) (const_int -4))) (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 2" - "stm%(db%)\t%3, {%1, %2}" + "stmdb%?\t%3, {%1, %2}" [(set_attr "type" "store2") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) @@ -1104,7 +1104,7 @@ (set (mem:SI (plus:SI (match_dup 3) (const_int -4))) (match_operand:SI 2 "arm_hard_general_register_operand" ""))])] "TARGET_32BIT && XVECLEN (operands[0], 0) == 3" - "stm%(db%)\t%3!, {%1, %2}" + "stmdb%?\t%3!, {%1, %2}" [(set_attr "type" "store2") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no")]) diff --git a/gcc/config/arm/sync.md b/gcc/config/arm/sync.md index 9ee715cd6de..fc7836fea7c 100644 --- a/gcc/config/arm/sync.md +++ b/gcc/config/arm/sync.md @@ -72,7 +72,7 @@ { enum memmodel model = memmodel_from_int (INTVAL (operands[2])); if (is_mm_relaxed (model) || is_mm_consume (model) || is_mm_release (model)) - return \"ldr%(%)\\t%0, %1\"; + return \"ldr%?\\t%0, %1\"; else return \"lda%?\\t%0, %1\"; } @@ -89,7 +89,7 @@ { enum memmodel model = memmodel_from_int (INTVAL (operands[2])); if (is_mm_relaxed (model) || is_mm_consume (model) || is_mm_acquire (model)) - return \"str%(%)\t%1, %0\"; + return \"str%?\t%1, %0\"; else return \"stl%?\t%1, %0\"; } diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md index 8c754d90d58..a724752a39c 100644 --- a/gcc/config/arm/thumb2.md +++ b/gcc/config/arm/thumb2.md @@ -330,8 +330,8 @@ mov%?\\t%0, %1\\t%@ movhi mov%?\\t%0, %1\\t%@ movhi movw%?\\t%0, %L1\\t%@ movhi - str%(h%)\\t%1, %0\\t%@ movhi - ldr%(h%)\\t%0, %1\\t%@ movhi" + strh%?\\t%1, %0\\t%@ movhi + ldrh%?\\t%0, %1\\t%@ movhi" [(set_attr "type" "mov_reg,mov_imm,mov_imm,mov_imm,store1,load1") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "yes,no,yes,no,no,no") @@ -1028,7 +1028,7 @@ "TARGET_THUMB2 && arm_arch6" "@ sxtb%?\\t%0, %1 - ldr%(sb%)\\t%0, %1" + ldrsb%?\\t%0, %1" [(set_attr "type" "extend,load_byte") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no") @@ -1042,7 +1042,7 @@ "TARGET_THUMB2 && arm_arch6" "@ uxth%?\\t%0, %1 - ldr%(h%)\\t%0, %1" + ldrh%?\\t%0, %1" [(set_attr "type" "extend,load_byte") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no") @@ -1055,8 +1055,8 @@ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] "TARGET_THUMB2 && arm_arch6" "@ - uxtb%(%)\\t%0, %1 - ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2" + uxtb%?\\t%0, %1 + ldrb%?\\t%0, %1\\t%@ zero_extendqisi2" [(set_attr "type" "extend,load_byte") (set_attr "predicable" "yes") (set_attr "predicable_short_it" "no") diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c index a3c0342950d..e3a301205e6 100644 --- a/gcc/config/i386/i386-c.c +++ b/gcc/config/i386/i386-c.c @@ -586,6 +586,10 @@ ix86_target_macros (void) ix86_tune, ix86_fpmath, cpp_define); + + cpp_define (parse_in, "__SEG_FS"); + cpp_define (parse_in, "__SEG_GS"); + cpp_define (parse_in, "__SEG_TLS"); } @@ -600,6 +604,10 @@ ix86_register_pragmas (void) /* Update pragma hook to allow parsing #pragma GCC target. */ targetm.target_option.pragma_parse = ix86_pragma_target_parse; + c_register_addr_space ("__seg_fs", ADDR_SPACE_SEG_FS); + c_register_addr_space ("__seg_gs", ADDR_SPACE_SEG_GS); + c_register_addr_space ("__seg_tls", ADDR_SPACE_SEG_TLS); + #ifdef REGISTER_SUBTARGET_PRAGMAS REGISTER_SUBTARGET_PRAGMAS (); #endif diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 6a17ef40a2e..026b778f4e3 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -141,6 +141,7 @@ extern void ix86_split_ashr (rtx *, rtx, machine_mode); extern void ix86_split_lshr (rtx *, rtx, machine_mode); extern rtx ix86_find_base_term (rtx); extern bool ix86_check_movabs (rtx, int); +extern bool ix86_check_no_addr_space (rtx); extern void ix86_split_idivmod (machine_mode, rtx[], bool); extern rtx assign_386_stack_local (machine_mode, enum ix86_stack_slot); @@ -278,12 +279,11 @@ extern rtx maybe_get_pool_constant (rtx); extern char internal_label_prefix[16]; extern int internal_label_prefix_len; -enum ix86_address_seg { SEG_DEFAULT, SEG_FS, SEG_GS }; struct ix86_address { rtx base, index, disp; HOST_WIDE_INT scale; - enum ix86_address_seg seg; + addr_space_t seg; }; extern int ix86_decompose_address (rtx, struct ix86_address *); @@ -325,3 +325,7 @@ struct ix86_first_cycle_multipass_data_ # define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T \ struct ix86_first_cycle_multipass_data_ #endif /* RTX_CODE */ + +const addr_space_t ADDR_SPACE_SEG_FS = 1; +const addr_space_t ADDR_SPACE_SEG_GS = 2; +const addr_space_t ADDR_SPACE_SEG_TLS = 3; diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 2a965f678a0..0d84cde9cbe 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see #include "context.h" #include "pass_manager.h" #include "target-globals.h" +#include "gimple-iterator.h" #include "tree-vectorizer.h" #include "shrink-wrap.h" #include "builtins.h" @@ -79,6 +80,7 @@ along with GCC; see the file COPYING3. If not see static rtx legitimize_dllimport_symbol (rtx, bool); static rtx legitimize_pe_coff_extern_decl (rtx, bool); static rtx legitimize_pe_coff_symbol (rtx, bool); +static void ix86_print_operand_address_as (FILE *file, rtx addr, addr_space_t); #ifndef CHECK_STACK_LIMIT #define CHECK_STACK_LIMIT (-1) @@ -10537,6 +10539,20 @@ ix86_check_movabs (rtx insn, int opnum) gcc_assert (MEM_P (mem)); return volatile_ok || !MEM_VOLATILE_P (mem); } + +/* Return false if INSN contains a MEM with a non-default address space. */ +bool +ix86_check_no_addr_space (rtx insn) +{ + subrtx_var_iterator::array_type array; + FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (insn), ALL) + { + rtx x = *iter; + if (MEM_P (x) && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x))) + return false; + } + return true; +} /* Initialize the table of extra 80387 mathematical constants. */ @@ -13973,7 +13989,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) rtx scale_rtx = NULL_RTX; rtx tmp; int retval = 1; - enum ix86_address_seg seg = SEG_DEFAULT; + addr_space_t seg = ADDR_SPACE_GENERIC; /* Allow zero-extended SImode addresses, they will be emitted with addr32 prefix. */ @@ -14072,7 +14088,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) case UNSPEC: if (XINT (op, 1) == UNSPEC_TP && TARGET_TLS_DIRECT_SEG_REFS - && seg == SEG_DEFAULT) + && seg == ADDR_SPACE_GENERIC) seg = DEFAULT_TLS_SEG_REG; else return 0; @@ -14660,7 +14676,7 @@ ix86_legitimate_address_p (machine_mode, rtx addr, bool strict) struct ix86_address parts; rtx base, index, disp; HOST_WIDE_INT scale; - enum ix86_address_seg seg; + addr_space_t seg; if (ix86_decompose_address (addr, &parts) <= 0) /* Decomposition failed. */ @@ -14706,7 +14722,7 @@ ix86_legitimate_address_p (machine_mode, rtx addr, bool strict) return false; /* Address override works only on the (%reg) part of %fs:(%reg). */ - if (seg != SEG_DEFAULT + if (seg != ADDR_SPACE_GENERIC && ((base && GET_MODE (base) != word_mode) || (index && GET_MODE (index) != word_mode))) return false; @@ -17113,32 +17129,22 @@ ix86_print_operand (FILE *file, rtx x, int code) else if (MEM_P (x)) { - /* No `byte ptr' prefix for call instructions or BLKmode operands. */ - if (ASSEMBLER_DIALECT == ASM_INTEL && code != 'X' && code != 'P' - && GET_MODE (x) != BLKmode) + rtx addr = XEXP (x, 0); + + /* Avoid (%rip) for call operands. */ + if (code == 'P' && CONSTANT_ADDRESS_P (x) && !CONST_INT_P (x)) { - const char * size; - switch (GET_MODE_SIZE (GET_MODE (x))) - { - case 1: size = "BYTE"; break; - case 2: size = "WORD"; break; - case 4: size = "DWORD"; break; - case 8: size = "QWORD"; break; - case 12: size = "TBYTE"; break; - case 16: - if (GET_MODE (x) == XFmode) - size = "TBYTE"; - else - size = "XMMWORD"; - break; - case 32: size = "YMMWORD"; break; - case 64: size = "ZMMWORD"; break; - default: - gcc_unreachable (); - } + output_addr_const (file, addr); + return; + } + + /* No `byte ptr' prefix for call instructions ... */ + if (ASSEMBLER_DIALECT == ASM_INTEL && code != 'X' && code != 'P') + { + machine_mode mode = GET_MODE (x); + const char *size; - /* Check for explicit size override (codes 'b', 'w', 'k', - 'q' and 'x') */ + /* Check for explicit size override codes. */ if (code == 'b') size = "BYTE"; else if (code == 'w') @@ -17149,20 +17155,39 @@ ix86_print_operand (FILE *file, rtx x, int code) size = "QWORD"; else if (code == 'x') size = "XMMWORD"; - - fputs (size, file); - fputs (" PTR ", file); + else if (mode == BLKmode) + /* ... or BLKmode operands, when not overridden. */ + size = NULL; + else + switch (GET_MODE_SIZE (mode)) + { + case 1: size = "BYTE"; break; + case 2: size = "WORD"; break; + case 4: size = "DWORD"; break; + case 8: size = "QWORD"; break; + case 12: size = "TBYTE"; break; + case 16: + if (mode == XFmode) + size = "TBYTE"; + else + size = "XMMWORD"; + break; + case 32: size = "YMMWORD"; break; + case 64: size = "ZMMWORD"; break; + default: + gcc_unreachable (); + } + if (size) + { + fputs (size, file); + fputs (" PTR ", file); + } } - x = XEXP (x, 0); - /* Avoid (%rip) for call operands. */ - if (CONSTANT_ADDRESS_P (x) && code == 'P' - && !CONST_INT_P (x)) - output_addr_const (file, x); - else if (this_is_asm_operands && ! address_operand (x, VOIDmode)) + if (this_is_asm_operands && ! address_operand (addr, VOIDmode)) output_operand_lossage ("invalid constraints for operand"); else - output_address (x); + ix86_print_operand_address_as (file, addr, MEM_ADDR_SPACE (x)); } else if (CONST_DOUBLE_P (x) && GET_MODE (x) == SFmode) @@ -17247,7 +17272,7 @@ ix86_print_operand_punct_valid_p (unsigned char code) /* Print a memory operand whose address is ADDR. */ static void -ix86_print_operand_address (FILE *file, rtx addr) +ix86_print_operand_address_as (FILE *file, rtx addr, addr_space_t as) { struct ix86_address parts; rtx base, index, disp; @@ -17300,18 +17325,24 @@ ix86_print_operand_address (FILE *file, rtx addr) disp = parts.disp; scale = parts.scale; - switch (parts.seg) + if (ADDR_SPACE_GENERIC_P (as)) + as = parts.seg; + else + gcc_assert (ADDR_SPACE_GENERIC_P (parts.seg)); + + if (!ADDR_SPACE_GENERIC_P (as)) { - case SEG_DEFAULT: - break; - case SEG_FS: - case SEG_GS: - if (ASSEMBLER_DIALECT == ASM_ATT) - putc ('%', file); - fputs ((parts.seg == SEG_FS ? "fs:" : "gs:"), file); - break; - default: - gcc_unreachable (); + const char *string; + + if (as == ADDR_SPACE_SEG_TLS) + as = DEFAULT_TLS_SEG_REG; + if (as == ADDR_SPACE_SEG_FS) + string = (ASSEMBLER_DIALECT == ASM_ATT ? "%fs:" : "fs:"); + else if (as == ADDR_SPACE_SEG_GS) + string = (ASSEMBLER_DIALECT == ASM_ATT ? "%gs:" : "gs:"); + else + gcc_unreachable (); + fputs (string, file); } /* Use one byte shorter RIP relative addressing for 64bit mode. */ @@ -17335,7 +17366,7 @@ ix86_print_operand_address (FILE *file, rtx addr) if (CONST_INT_P (disp)) { - if (ASSEMBLER_DIALECT == ASM_INTEL && parts.seg == SEG_DEFAULT) + if (ASSEMBLER_DIALECT == ASM_INTEL && parts.seg == ADDR_SPACE_GENERIC) fputs ("ds:", file); fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (disp)); } @@ -17471,6 +17502,12 @@ ix86_print_operand_address (FILE *file, rtx addr) } } +static void +ix86_print_operand_address (FILE *file, rtx addr) +{ + ix86_print_operand_address_as (file, addr, ADDR_SPACE_GENERIC); +} + /* Implementation of TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */ static bool @@ -25664,7 +25701,7 @@ expand_set_or_movmem_constant_prologue (rtx dst, rtx *srcp, rtx destreg, /* Return true if ALG can be used in current context. Assume we expand memset if MEMSET is true. */ static bool -alg_usable_p (enum stringop_alg alg, bool memset) +alg_usable_p (enum stringop_alg alg, bool memset, bool have_as) { if (alg == no_stringop) return false; @@ -25673,12 +25710,19 @@ alg_usable_p (enum stringop_alg alg, bool memset) /* Algorithms using the rep prefix want at least edi and ecx; additionally, memset wants eax and memcpy wants esi. Don't consider such algorithms if the user has appropriated those - registers for their own purposes. */ + registers for their own purposes, or if we have a non-default + address space, since some string insns cannot override the segment. */ if (alg == rep_prefix_1_byte || alg == rep_prefix_4_byte || alg == rep_prefix_8_byte) - return !(fixed_regs[CX_REG] || fixed_regs[DI_REG] - || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG])); + { + if (have_as) + return false; + if (fixed_regs[CX_REG] + || fixed_regs[DI_REG] + || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG])) + return false; + } return true; } @@ -25686,7 +25730,8 @@ alg_usable_p (enum stringop_alg alg, bool memset) static enum stringop_alg decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, unsigned HOST_WIDE_INT min_size, unsigned HOST_WIDE_INT max_size, - bool memset, bool zero_memset, int *dynamic_check, bool *noalign) + bool memset, bool zero_memset, bool have_as, + int *dynamic_check, bool *noalign) { const struct stringop_algs * algs; bool optimize_for_speed; @@ -25718,7 +25763,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, for (i = 0; i < MAX_STRINGOP_ALGS; i++) { enum stringop_alg candidate = algs->size[i].alg; - bool usable = alg_usable_p (candidate, memset); + bool usable = alg_usable_p (candidate, memset, have_as); any_alg_usable_p |= usable; if (candidate != libcall && candidate && usable) @@ -25734,17 +25779,17 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, /* If user specified the algorithm, honnor it if possible. */ if (ix86_stringop_alg != no_stringop - && alg_usable_p (ix86_stringop_alg, memset)) + && alg_usable_p (ix86_stringop_alg, memset, have_as)) return ix86_stringop_alg; /* rep; movq or rep; movl is the smallest variant. */ else if (!optimize_for_speed) { *noalign = true; if (!count || (count & 3) || (memset && !zero_memset)) - return alg_usable_p (rep_prefix_1_byte, memset) + return alg_usable_p (rep_prefix_1_byte, memset, have_as) ? rep_prefix_1_byte : loop_1_byte; else - return alg_usable_p (rep_prefix_4_byte, memset) + return alg_usable_p (rep_prefix_4_byte, memset, have_as) ? rep_prefix_4_byte : loop; } /* Very tiny blocks are best handled via the loop, REP is expensive to @@ -25767,7 +25812,8 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, { enum stringop_alg candidate = algs->size[i].alg; - if (candidate != libcall && alg_usable_p (candidate, memset)) + if (candidate != libcall + && alg_usable_p (candidate, memset, have_as)) { alg = candidate; alg_noalign = algs->size[i].noalign; @@ -25787,7 +25833,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, else if (!any_alg_usable_p) break; } - else if (alg_usable_p (candidate, memset)) + else if (alg_usable_p (candidate, memset, have_as)) { *noalign = algs->size[i].noalign; return candidate; @@ -25804,7 +25850,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, choice in ix86_costs. */ if ((TARGET_INLINE_ALL_STRINGOPS || TARGET_INLINE_STRINGOPS_DYNAMICALLY) && (algs->unknown_size == libcall - || !alg_usable_p (algs->unknown_size, memset))) + || !alg_usable_p (algs->unknown_size, memset, have_as))) { enum stringop_alg alg; @@ -25821,7 +25867,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, if (max <= 0) max = 4096; alg = decide_alg (count, max / 2, min_size, max_size, memset, - zero_memset, dynamic_check, noalign); + zero_memset, have_as, dynamic_check, noalign); gcc_assert (*dynamic_check == -1); if (TARGET_INLINE_STRINGOPS_DYNAMICALLY) *dynamic_check = max; @@ -25829,7 +25875,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, gcc_assert (alg != libcall); return alg; } - return (alg_usable_p (algs->unknown_size, memset) + return (alg_usable_p (algs->unknown_size, memset, have_as) ? algs->unknown_size : libcall); } @@ -26035,6 +26081,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp, unsigned HOST_WIDE_INT max_size = -1; unsigned HOST_WIDE_INT probable_max_size = -1; bool misaligned_prologue_used = false; + bool have_as; if (CONST_INT_P (align_exp)) align = INTVAL (align_exp); @@ -26072,11 +26119,15 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp, if (count > (HOST_WIDE_INT_1U << 30)) return false; + have_as = !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (dst)); + if (!issetmem) + have_as |= !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (src)); + /* Step 0: Decide on preferred algorithm, desired alignment and size of chunks to be copied by main loop. */ alg = decide_alg (count, expected_size, min_size, probable_max_size, issetmem, - issetmem && val_exp == const0_rtx, + issetmem && val_exp == const0_rtx, have_as, &dynamic_check, &noalign); if (alg == libcall) return false; @@ -26690,6 +26741,9 @@ ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align) /* Can't use this if the user has appropriated eax, ecx, or edi. */ if (fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG]) return false; + /* Can't use this for non-default address spaces. */ + if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (src))) + return false; scratch2 = gen_reg_rtx (Pmode); scratch3 = gen_reg_rtx (Pmode); @@ -27104,7 +27158,7 @@ memory_address_length (rtx addr, bool lea) ok = ix86_decompose_address (addr, &parts); gcc_assert (ok); - len = (parts.seg == SEG_DEFAULT) ? 0 : 1; + len = (parts.seg == ADDR_SPACE_GENERIC) ? 0 : 1; /* If this is not LEA instruction, add the length of addr32 prefix. */ if (TARGET_64BIT && !lea @@ -27265,25 +27319,35 @@ ix86_attr_length_address_default (rtx_insn *insn) extract_insn_cached (insn); for (i = recog_data.n_operands - 1; i >= 0; --i) - if (MEM_P (recog_data.operand[i])) - { - constrain_operands_cached (insn, reload_completed); - if (which_alternative != -1) - { - const char *constraints = recog_data.constraints[i]; - int alt = which_alternative; - - while (*constraints == '=' || *constraints == '+') - constraints++; - while (alt-- > 0) - while (*constraints++ != ',') - ; - /* Skip ignored operands. */ - if (*constraints == 'X') - continue; - } - return memory_address_length (XEXP (recog_data.operand[i], 0), false); - } + { + rtx op = recog_data.operand[i]; + if (MEM_P (op)) + { + constrain_operands_cached (insn, reload_completed); + if (which_alternative != -1) + { + const char *constraints = recog_data.constraints[i]; + int alt = which_alternative; + + while (*constraints == '=' || *constraints == '+') + constraints++; + while (alt-- > 0) + while (*constraints++ != ',') + ; + /* Skip ignored operands. */ + if (*constraints == 'X') + continue; + } + + int len = memory_address_length (XEXP (op, 0), false); + + /* Account for segment prefix for non-default addr spaces. */ + if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (op))) + len++; + + return len; + } + } return 0; } @@ -53637,6 +53701,78 @@ ix86_operands_ok_for_move_multiple (rtx *operands, bool load, return true; } +/* Address space support. + + This is not "far pointers" in the 16-bit sense, but an easy way + to use %fs and %gs segment prefixes. Therefore: + + (a) All address spaces have the same modes, + (b) All address spaces have the same addresss forms, + (c) While %fs and %gs are technically subsets of the generic + address space, they are probably not subsets of each other. + (d) Since we have no access to the segment base register values + without resorting to a system call, we cannot convert a + non-default address space to a default address space. + Therefore we do not claim %fs or %gs are subsets of generic. + (e) However, __seg_tls uses UNSPEC_TP as the base (which itself is + stored at __seg_tls:0) so we can map between tls and generic. */ + +static bool +ix86_addr_space_subset_p (addr_space_t subset, addr_space_t superset) +{ + return (subset == superset + || (superset == ADDR_SPACE_GENERIC + && subset == ADDR_SPACE_SEG_TLS)); +} +#undef TARGET_ADDR_SPACE_SUBSET_P +#define TARGET_ADDR_SPACE_SUBSET_P ix86_addr_space_subset_p + +static rtx +ix86_addr_space_convert (rtx op, tree from_type, tree to_type) +{ + addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type)); + addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type)); + + /* Conversion between SEG_TLS and GENERIC is handled by adding or + subtracting the thread pointer. */ + if ((from_as == ADDR_SPACE_GENERIC && to_as == ADDR_SPACE_SEG_TLS) + || (from_as == ADDR_SPACE_SEG_TLS && to_as == ADDR_SPACE_GENERIC)) + { + machine_mode mode = GET_MODE (op); + if (mode == VOIDmode) + mode = ptr_mode; + rtx tp = get_thread_pointer (mode, optimize || mode != ptr_mode); + return expand_binop (mode, (to_as == ADDR_SPACE_GENERIC + ? add_optab : sub_optab), + op, tp, NULL, 1, OPTAB_WIDEN); + } + + return op; +} +#undef TARGET_ADDR_SPACE_CONVERT +#define TARGET_ADDR_SPACE_CONVERT ix86_addr_space_convert + +static int +ix86_addr_space_debug (addr_space_t as) +{ + /* Fold __seg_tls to __seg_fs or __seg_gs for debugging. */ + if (as == ADDR_SPACE_SEG_TLS) + as = DEFAULT_TLS_SEG_REG; + return as; +} +#undef TARGET_ADDR_SPACE_DEBUG +#define TARGET_ADDR_SPACE_DEBUG ix86_addr_space_debug + +/* All use of segmentation is assumed to make address 0 valid. */ + +static bool +ix86_addr_space_zero_address_valid (addr_space_t as) +{ + return as != ADDR_SPACE_GENERIC; +} +#undef TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID +#define TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID ix86_addr_space_zero_address_valid + /* Initialize the GCC target structure. */ #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY ix86_return_in_memory diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index be96c75df77..3d5b2b25ced 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -602,7 +602,8 @@ extern tree x86_mfence; #define DEFAULT_ABI SYSV_ABI /* The default TLS segment register used by target. */ -#define DEFAULT_TLS_SEG_REG (TARGET_64BIT ? SEG_FS : SEG_GS) +#define DEFAULT_TLS_SEG_REG \ + (TARGET_64BIT ? ADDR_SPACE_SEG_FS : ADDR_SPACE_SEG_GS) /* Subtargets may reset this to 1 in order to enable 96-bit long double with the rounding mode forced to 53 bits. */ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index d0c0d23df28..2cb94fec34e 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -2595,9 +2595,19 @@ [(set (mem:SWI1248x (match_operand:DI 0 "x86_64_movabs_operand" "i,r")) (match_operand:SWI1248x 1 "nonmemory_operand" "a,r"))] "TARGET_LP64 && ix86_check_movabs (insn, 0)" - "@ - movabs{}\t{%1, %P0|[%P0], %1} - mov{}\t{%1, %a0| PTR %a0, %1}" +{ + /* Recover the full memory rtx. */ + operands[0] = SET_DEST (PATTERN (insn)); + switch (which_alternative) + { + case 0: + return "movabs{}\t{%1, %0|%0, %1}"; + case 1: + return "mov{}\t{%1, %0|%0, %1}"; + default: + gcc_unreachable (); + } +} [(set_attr "type" "imov") (set_attr "modrm" "0,*") (set_attr "length_address" "8,0") @@ -2609,9 +2619,19 @@ [(set (match_operand:SWI1248x 0 "register_operand" "=a,r") (mem:SWI1248x (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))] "TARGET_LP64 && ix86_check_movabs (insn, 1)" - "@ - movabs{}\t{%P1, %0|%0, [%P1]} - mov{}\t{%a1, %0|%0, PTR %a1}" +{ + /* Recover the full memory rtx. */ + operands[1] = SET_SRC (PATTERN (insn)); + switch (which_alternative) + { + case 0: + return "movabs{}\t{%1, %0|%0, %1}"; + case 1: + return "mov{}\t{%1, %0|%0, %1}"; + default: + gcc_unreachable (); + } +} [(set_attr "type" "imov") (set_attr "modrm" "0,*") (set_attr "length_address" "8,0") @@ -16139,6 +16159,10 @@ (clobber (reg:CC FLAGS_REG))])] "" { + /* Can't use this for non-default address spaces. */ + if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (operands[3]))) + FAIL; + rtx adjust = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1]))); /* If .md ever supports :P for Pmode, these can be directly @@ -16179,7 +16203,8 @@ (plus:P (match_dup 3) (const_int 8)))] "TARGET_64BIT - && !(fixed_regs[SI_REG] || fixed_regs[DI_REG])" + && !(fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^movsq" [(set_attr "type" "str") (set_attr "memory" "both") @@ -16194,7 +16219,8 @@ (set (match_operand:P 1 "register_operand" "=S") (plus:P (match_dup 3) (const_int 4)))] - "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^movs{l|d}" [(set_attr "type" "str") (set_attr "memory" "both") @@ -16209,7 +16235,8 @@ (set (match_operand:P 1 "register_operand" "=S") (plus:P (match_dup 3) (const_int 2)))] - "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^movsw" [(set_attr "type" "str") (set_attr "memory" "both") @@ -16225,7 +16252,8 @@ (plus:P (match_dup 3) (const_int 1)))] "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])" - "%^movsb" + "%^movsb + && ix86_check_no_addr_space (insn)" [(set_attr "type" "str") (set_attr "memory" "both") (set (attr "prefix_rex") @@ -16260,7 +16288,8 @@ (mem:BLK (match_dup 4))) (use (match_dup 5))] "TARGET_64BIT - && !(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])" + && !(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^rep{%;} movsq" [(set_attr "type" "str") (set_attr "prefix_rep" "1") @@ -16279,7 +16308,8 @@ (set (mem:BLK (match_dup 3)) (mem:BLK (match_dup 4))) (use (match_dup 5))] - "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^rep{%;} movs{l|d}" [(set_attr "type" "str") (set_attr "prefix_rep" "1") @@ -16296,7 +16326,8 @@ (set (mem:BLK (match_dup 3)) (mem:BLK (match_dup 4))) (use (match_dup 5))] - "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^rep{%;} movsb" [(set_attr "type" "str") (set_attr "prefix_rep" "1") @@ -16336,6 +16367,10 @@ (clobber (reg:CC FLAGS_REG))])] "" { + /* Can't use this for non-default address spaces. */ + if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (operands[1]))) + FAIL; + if (GET_MODE (operands[1]) != GET_MODE (operands[2])) operands[1] = adjust_address_nv (operands[1], GET_MODE (operands[2]), 0); @@ -16371,7 +16406,8 @@ (const_int 8))) (unspec [(const_int 0)] UNSPEC_STOS)] "TARGET_64BIT - && !(fixed_regs[AX_REG] || fixed_regs[DI_REG])" + && !(fixed_regs[AX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^stosq" [(set_attr "type" "str") (set_attr "memory" "store") @@ -16384,7 +16420,8 @@ (plus:P (match_dup 1) (const_int 4))) (unspec [(const_int 0)] UNSPEC_STOS)] - "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[AX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^stos{l|d}" [(set_attr "type" "str") (set_attr "memory" "store") @@ -16397,7 +16434,8 @@ (plus:P (match_dup 1) (const_int 2))) (unspec [(const_int 0)] UNSPEC_STOS)] - "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[AX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^stosw" [(set_attr "type" "str") (set_attr "memory" "store") @@ -16410,7 +16448,8 @@ (plus:P (match_dup 1) (const_int 1))) (unspec [(const_int 0)] UNSPEC_STOS)] - "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[AX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^stosb" [(set_attr "type" "str") (set_attr "memory" "store") @@ -16442,7 +16481,8 @@ (use (match_operand:DI 2 "register_operand" "a")) (use (match_dup 4))] "TARGET_64BIT - && !(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])" + && !(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^rep{%;} stosq" [(set_attr "type" "str") (set_attr "prefix_rep" "1") @@ -16459,7 +16499,8 @@ (const_int 0)) (use (match_operand:SI 2 "register_operand" "a")) (use (match_dup 4))] - "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^rep{%;} stos{l|d}" [(set_attr "type" "str") (set_attr "prefix_rep" "1") @@ -16475,7 +16516,8 @@ (const_int 0)) (use (match_operand:QI 2 "register_operand" "a")) (use (match_dup 4))] - "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^rep{%;} stosb" [(set_attr "type" "str") (set_attr "prefix_rep" "1") @@ -16596,7 +16638,8 @@ (clobber (match_operand:P 0 "register_operand" "=S")) (clobber (match_operand:P 1 "register_operand" "=D")) (clobber (match_operand:P 2 "register_operand" "=c"))] - "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^repz{%;} cmpsb" [(set_attr "type" "str") (set_attr "mode" "QI") @@ -16636,7 +16679,8 @@ (clobber (match_operand:P 0 "register_operand" "=S")) (clobber (match_operand:P 1 "register_operand" "=D")) (clobber (match_operand:P 2 "register_operand" "=c"))] - "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^repz{%;} cmpsb" [(set_attr "type" "str") (set_attr "mode" "QI") @@ -16677,7 +16721,8 @@ (match_operand:P 4 "register_operand" "0")] UNSPEC_SCAS)) (clobber (match_operand:P 1 "register_operand" "=D")) (clobber (reg:CC FLAGS_REG))] - "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^repnz{%;} scasb" [(set_attr "type" "str") (set_attr "mode" "QI") diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 1595142255d..c11f2d7d228 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -974,7 +974,7 @@ ok = ix86_decompose_address (op, &parts); gcc_assert (ok); - return parts.seg == SEG_DEFAULT; + return parts.seg == ADDR_SPACE_GENERIC; }) ;; Return true if op if a valid base register, displacement or @@ -988,7 +988,7 @@ ok = ix86_decompose_address (op, &parts); gcc_assert (ok); - if (parts.index || parts.seg != SEG_DEFAULT) + if (parts.index || parts.seg != ADDR_SPACE_GENERIC) return false; /* VSIB addressing doesn't support (%rip). */ @@ -1032,7 +1032,7 @@ if (parts.index && parts.base) return false; - if (parts.seg != SEG_DEFAULT) + if (parts.seg != ADDR_SPACE_GENERIC) return false; /* Do not support (%rip). */ @@ -1064,7 +1064,7 @@ if (parts.index) return false; - if (parts.seg != SEG_DEFAULT) + if (parts.seg != ADDR_SPACE_GENERIC) return false; /* Do not support (%rip). */ diff --git a/gcc/config/i386/rdos.h b/gcc/config/i386/rdos.h index f9bfe6d02e4..ccf6b78824a 100644 --- a/gcc/config/i386/rdos.h +++ b/gcc/config/i386/rdos.h @@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see #define TARGET_TLS_DIRECT_SEG_REFS_DEFAULT MASK_TLS_DIRECT_SEG_REFS #undef DEFAULT_TLS_SEG_REG -#define DEFAULT_TLS_SEG_REG SEG_GS +#define DEFAULT_TLS_SEG_REG ADDR_SPACE_SEG_GS #undef TARGET_RDOS #define TARGET_RDOS 1 diff --git a/gcc/config/mips/loongson.md b/gcc/config/mips/loongson.md index 0b19bd7baf8..b8489ab5ab9 100644 --- a/gcc/config/mips/loongson.md +++ b/gcc/config/mips/loongson.md @@ -852,58 +852,66 @@ "dsrl\t%0,%1,%2" [(set_attr "type" "fcvt")]) -(define_expand "reduc_uplus_" - [(match_operand:VWH 0 "register_operand" "") - (match_operand:VWH 1 "register_operand" "")] +(define_insn "vec_loongson_extract_lo_" + [(set (match_operand: 0 "register_operand" "=r") + (vec_select: + (match_operand:VWHB 1 "register_operand" "f") + (parallel [(const_int 0)])))] "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" -{ - mips_expand_vec_reduc (operands[0], operands[1], gen_add3); - DONE; -}) + "mfc1\t%0,%1" + [(set_attr "type" "mfc")]) -; ??? Given that we're not describing a widening reduction, we should -; not have separate optabs for signed and unsigned. -(define_expand "reduc_splus_" - [(match_operand:VWHB 0 "register_operand" "") +(define_expand "reduc_plus_scal_" + [(match_operand: 0 "register_operand" "") (match_operand:VWHB 1 "register_operand" "")] "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" { - emit_insn (gen_reduc_uplus_(operands[0], operands[1])); + rtx tmp = gen_reg_rtx (GET_MODE (operands[1])); + mips_expand_vec_reduc (tmp, operands[1], gen_add3); + emit_insn (gen_vec_loongson_extract_lo_ (operands[0], tmp)); DONE; }) -(define_expand "reduc_smax_" - [(match_operand:VWHB 0 "register_operand" "") +(define_expand "reduc_smax_scal_" + [(match_operand: 0 "register_operand" "") (match_operand:VWHB 1 "register_operand" "")] "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" { - mips_expand_vec_reduc (operands[0], operands[1], gen_smax3); + rtx tmp = gen_reg_rtx (GET_MODE (operands[1])); + mips_expand_vec_reduc (tmp, operands[1], gen_smax3); + emit_insn (gen_vec_loongson_extract_lo_ (operands[0], tmp)); DONE; }) -(define_expand "reduc_smin_" - [(match_operand:VWHB 0 "register_operand" "") +(define_expand "reduc_smin_scal_" + [(match_operand: 0 "register_operand" "") (match_operand:VWHB 1 "register_operand" "")] "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" { - mips_expand_vec_reduc (operands[0], operands[1], gen_smin3); + rtx tmp = gen_reg_rtx (GET_MODE (operands[1])); + mips_expand_vec_reduc (tmp, operands[1], gen_smin3); + emit_insn (gen_vec_loongson_extract_lo_ (operands[0], tmp)); DONE; }) -(define_expand "reduc_umax_" - [(match_operand:VB 0 "register_operand" "") +(define_expand "reduc_umax_scal_" + [(match_operand: 0 "register_operand" "") (match_operand:VB 1 "register_operand" "")] "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" { - mips_expand_vec_reduc (operands[0], operands[1], gen_umax3); + rtx tmp = gen_reg_rtx (GET_MODE (operands[1])); + mips_expand_vec_reduc (tmp, operands[1], gen_umax3); + emit_insn (gen_vec_loongson_extract_lo_ (operands[0], tmp)); DONE; }) -(define_expand "reduc_umin_" - [(match_operand:VB 0 "register_operand" "") +(define_expand "reduc_umin_scal_" + [(match_operand: 0 "register_operand" "") (match_operand:VB 1 "register_operand" "")] "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" { - mips_expand_vec_reduc (operands[0], operands[1], gen_umin3); + rtx tmp = gen_reg_rtx (GET_MODE (operands[1])); + mips_expand_vec_reduc (tmp, operands[1], gen_umin3); + emit_insn (gen_vec_loongson_extract_lo_ (operands[0], tmp)); DONE; }) diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 95d5ca34bef..9d6283fe116 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -15705,10 +15705,10 @@ r10k_safe_mem_expr_p (tree expr, unsigned HOST_WIDE_INT offset) HOST_WIDE_INT bitoffset, bitsize; tree inner, var_offset; machine_mode mode; - int unsigned_p, volatile_p; + int unsigned_p, reverse_p, volatile_p; inner = get_inner_reference (expr, &bitsize, &bitoffset, &var_offset, &mode, - &unsigned_p, &volatile_p, false); + &unsigned_p, &reverse_p, &volatile_p, false); if (!DECL_P (inner) || !DECL_SIZE_UNIT (inner) || var_offset) return false; diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 12563a089e1..5e3513a6b89 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -6426,7 +6426,7 @@ s390_expand_atomic (machine_mode mode, enum rtx_code code, case SET: if (ac.aligned && MEM_P (val)) store_bit_field (new_rtx, GET_MODE_BITSIZE (mode), 0, - 0, 0, SImode, val); + 0, 0, SImode, val, false); else { new_rtx = expand_simple_binop (SImode, AND, new_rtx, ac.modemaski, diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt index 249d33bc209..16583c38545 100644 --- a/gcc/config/sparc/sparc.opt +++ b/gcc/config/sparc/sparc.opt @@ -209,7 +209,7 @@ Enable strict 32-bit psABI struct return checking. mfix-at697f Target Report RejectNegative Var(sparc_fix_at697f) Enable workaround for single erratum of AT697F processor -(corresponding to erratum #13 of AT697E processor) +(corresponding to erratum #13 of AT697E processor). mfix-ut699 Target Report RejectNegative Var(sparc_fix_ut699) diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c index 6f83dccd90c..4ef2ca9375e 100644 --- a/gcc/config/tilegx/tilegx.c +++ b/gcc/config/tilegx/tilegx.c @@ -1962,7 +1962,7 @@ tilegx_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize, extract_bit_field (gen_lowpart (DImode, wide_result), bitsize, bit_offset % BITS_PER_UNIT, !sign, gen_lowpart (DImode, dest_reg), - DImode, DImode); + DImode, DImode, false); if (extracted != dest_reg) emit_move_insn (dest_reg, gen_lowpart (DImode, extracted)); diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c index ef8e24dbad1..4f95f6cb3b8 100644 --- a/gcc/config/tilepro/tilepro.c +++ b/gcc/config/tilepro/tilepro.c @@ -1692,7 +1692,7 @@ tilepro_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize, extract_bit_field (gen_lowpart (SImode, wide_result), bitsize, bit_offset % BITS_PER_UNIT, !sign, gen_lowpart (SImode, dest_reg), - SImode, SImode); + SImode, SImode, false); if (extracted != dest_reg) emit_move_insn (dest_reg, gen_lowpart (SImode, extracted)); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e780c868b62..11ca9ab584a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,46 @@ +2015-11-08 Martin Sebor + + PR c++/67942 + * cp/init.c (warn_placement_new_too_small): Convert integer + operand of POINTER_PLUS_EXPR to ssize_t to determine its signed + value. + +2015-11-06 David Malcolm + + * error.c (cp_printer): Update for new "caret_p" param for + textinfo::set_location. + (pedwarn_cxx98): Update for change in signature of + diagnostic_set_info. + +2015-11-06 Jason Merrill + + Support non-type constrained-type-specifiers. + * parser.c (check_type_concept): Remove. + (cp_parser_maybe_constrained_type_specifier): Don't call it. + (synthesize_implicit_template_parm): Handle non-type and template + template parameters. Also compare extra args. Return the decl. + (cp_parser_template_argument): Handle constrained-type-specifiers for + non-type template parameters. + (finish_constrained_template_template_parm): Split out from + cp_parser_constrained_template_template_parm. + (cp_parser_nonclass_name): Move some logic into + cp_parser_maybe_concept_name. + (cp_parser_init_declarator): Fix error recovery. + (get_concept_from_constraint): Remove. + (cp_parser_simple_type_specifier): Adjust for + synthesize_implicit_template_parm returning the decl. + * constraint.cc (placeholder_extract_concept_and_args) + (equivalent_placeholder_constraints): Also handle TYPE_DECL + constrained parms. + + * pt.c (push_inline_template_parms_recursive): Don't recreate the + CONST_DECL. + +2015-11-06 Kyrylo Tkachov + + * init.c (warn_placement_new_too_small): Use %wu format + rather than %lu when printing bytes_avail. + 2015-11-05 Cesar Philippidis Thomas Schwinge James Norris diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index a1fbf174ee8..c6eaf754606 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -1379,12 +1379,21 @@ make_constrained_auto (tree con, tree args) return decl; } -/* Given the predicate constraint T from a placeholder type, extract its - TMPL and ARGS. */ +/* Given the predicate constraint T from a constrained-type-specifier, extract + its TMPL and ARGS. FIXME why do we need two different forms of + constrained-type-specifier? */ void placeholder_extract_concept_and_args (tree t, tree &tmpl, tree &args) { + if (TREE_CODE (t) == TYPE_DECL) + { + /* A constrained parameter. */ + tmpl = DECL_TI_TEMPLATE (CONSTRAINED_PARM_CONCEPT (t)); + args = CONSTRAINED_PARM_EXTRA_ARGS (t); + return; + } + gcc_assert (TREE_CODE (t) == PRED_CONSTR); t = PRED_CONSTR_EXPR (t); gcc_assert (TREE_CODE (t) == CALL_EXPR @@ -1418,9 +1427,10 @@ placeholder_extract_concept_and_args (tree t, tree &tmpl, tree &args) bool equivalent_placeholder_constraints (tree c1, tree c2) { - if (TREE_CODE (c1) == TEMPLATE_TYPE_PARM) + if (c1 && TREE_CODE (c1) == TEMPLATE_TYPE_PARM) + /* A constrained auto. */ c1 = PLACEHOLDER_TYPE_CONSTRAINTS (c1); - if (TREE_CODE (c2) == TEMPLATE_TYPE_PARM) + if (c2 && TREE_CODE (c2) == TEMPLATE_TYPE_PARM) c2 = PLACEHOLDER_TYPE_CONSTRAINTS (c2); if (c1 == c2) @@ -1434,14 +1444,21 @@ equivalent_placeholder_constraints (tree c1, tree c2) if (t1 != t2) return false; - int len = TREE_VEC_LENGTH (a1); - if (len != TREE_VEC_LENGTH (a2)) - return false; + /* Skip the first argument to avoid infinite recursion on the placeholder auto itself. */ - for (int i = len-1; i > 0; --i) - if (!cp_tree_equal (TREE_VEC_ELT (a1, i), - TREE_VEC_ELT (a2, i))) + bool skip1 = (TREE_CODE (c1) == PRED_CONSTR); + bool skip2 = (TREE_CODE (c2) == PRED_CONSTR); + + int len1 = (a1 ? TREE_VEC_LENGTH (a1) : 0) - skip1; + int len2 = (a2 ? TREE_VEC_LENGTH (a2) : 0) - skip2; + + if (len1 != len2) + return false; + + for (int i = 0; i < len1; ++i) + if (!cp_tree_equal (TREE_VEC_ELT (a1, i + skip1), + TREE_VEC_ELT (a2, i + skip2))) return false; return true; } diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 75f6abb415f..286389c8aea 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -3563,7 +3563,7 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec, pp_string (pp, result); if (set_locus && t != NULL) - text->set_location (0, location_of (t)); + text->set_location (0, location_of (t), true); return true; #undef next_tree #undef next_tcode @@ -3677,9 +3677,10 @@ pedwarn_cxx98 (location_t location, int opt, const char *gmsgid, ...) diagnostic_info diagnostic; va_list ap; bool ret; + rich_location richloc (location); va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, (cxx_dialect == cxx98) ? DK_PEDWARN : DK_WARNING); diagnostic.option_index = opt; ret = report_diagnostic (&diagnostic); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 7386499d570..b45281f517d 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2321,12 +2321,14 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper) if (TREE_CODE (oper) == POINTER_PLUS_EXPR) { /* If the offset is comple-time constant, use it to compute a more - accurate estimate of the size of the buffer. Otherwise, use - the size of the entire array as an optimistic estimate (this - may lead to false negatives). */ - const_tree adj = TREE_OPERAND (oper, 1); + accurate estimate of the size of the buffer. Since the operand + of POINTER_PLUS_EXPR is represented as an unsigned type, convert + it to signed first. + Otherwise, use the size of the entire array as an optimistic + estimate (this may lead to false negatives). */ + tree adj = TREE_OPERAND (oper, 1); if (CONSTANT_CLASS_P (adj)) - adjust += tree_to_uhwi (adj); + adjust += tree_to_shwi (convert (ssizetype, adj)); else use_obj_size = true; @@ -2447,7 +2449,7 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper) "%<%T [%wu]%> and size %qwu in a region of type %qT " "and size %qwi" : "placement new constructing an object of type " - "%<%T [%lu]%> and size %qwu in a region of type %qT " + "%<%T [%wu]%> and size %qwu in a region of type %qT " "and size at most %qwu", type, tree_to_uhwi (nelts), bytes_need, TREE_TYPE (oper), diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c6f57297e72..d1f4970f1eb 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -13871,18 +13871,9 @@ cp_parser_constrained_type_template_parm (cp_parser *parser, return error_mark_node; } -/* Finish parsing/processing a template template parameter by borrowing - the template parameter list from the prototype parameter. */ - static tree -cp_parser_constrained_template_template_parm (cp_parser *parser, - tree proto, - tree id, - cp_parameter_declarator *parmdecl) +finish_constrained_template_template_parm (tree proto, tree id) { - if (!cp_parser_check_constrained_type_parm (parser, parmdecl)) - return error_mark_node; - /* FIXME: This should probably be copied, and we may need to adjust the template parameter depths. */ tree saved_parms = current_template_parms; @@ -13896,6 +13887,20 @@ cp_parser_constrained_template_template_parm (cp_parser *parser, return parm; } +/* Finish parsing/processing a template template parameter by borrowing + the template parameter list from the prototype parameter. */ + +static tree +cp_parser_constrained_template_template_parm (cp_parser *parser, + tree proto, + tree id, + cp_parameter_declarator *parmdecl) +{ + if (!cp_parser_check_constrained_type_parm (parser, parmdecl)) + return error_mark_node; + return finish_constrained_template_template_parm (proto, id); +} + /* Create a new non-type template parameter from the given PARM declarator. */ @@ -14950,8 +14955,12 @@ cp_parser_template_argument (cp_parser* parser) /*check_dependency=*/true, /*ambiguous_decls=*/NULL, argument_start_token->location); - if (TREE_CODE (argument) != TEMPLATE_DECL - && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE) + /* Handle a constrained-type-specifier for a non-type template + parameter. */ + if (tree decl = cp_parser_maybe_concept_name (parser, argument)) + argument = decl; + else if (TREE_CODE (argument) != TEMPLATE_DECL + && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE) cp_parser_error (parser, "expected template-name"); } if (cp_parser_parse_definitely (parser)) @@ -15630,7 +15639,10 @@ cp_parser_simple_type_specifier (cp_parser* parser, } if (cxx_dialect >= cxx14) - type = synthesize_implicit_template_parm (parser, NULL_TREE); + { + type = synthesize_implicit_template_parm (parser, NULL_TREE); + type = TREE_TYPE (type); + } else type = error_mark_node; @@ -15949,19 +15961,6 @@ cp_parser_type_name (cp_parser* parser, bool typename_keyword_p) return type_decl; } -/* Returns true if proto is a type parameter, but not a template - template parameter. */ -static bool -check_type_concept (tree fn, tree proto) -{ - if (TREE_CODE (proto) != TYPE_DECL) - { - error ("invalid use of non-type concept %qD", fn); - return false; - } - return true; -} - /* Check if DECL and ARGS can form a constrained-type-specifier. If ARGS is non-null, we try to form a concept check of the form DECL where ? is a wildcard that matches any @@ -16009,13 +16008,6 @@ cp_parser_maybe_constrained_type_specifier (cp_parser *parser, if (processing_template_parmlist) return build_constrained_parameter (conc, proto, args); - /* In any other context, a concept must be a type concept. - - FIXME: A constrained-type-specifier can be a placeholder - of any kind. */ - if (!check_type_concept (conc, proto)) - return error_mark_node; - /* In a parameter-declaration-clause, constrained-type specifiers result in invented template parameters. */ if (parser->auto_is_implicit_function_template_parm_p) @@ -16046,7 +16038,13 @@ cp_parser_maybe_constrained_type_specifier (cp_parser *parser, static tree cp_parser_maybe_concept_name (cp_parser* parser, tree decl) { - return cp_parser_maybe_constrained_type_specifier (parser, decl, NULL_TREE); + if (flag_concepts + && (TREE_CODE (decl) == OVERLOAD + || BASELINK_P (decl) + || variable_concept_p (decl))) + return cp_parser_maybe_constrained_type_specifier (parser, decl, NULL_TREE); + else + return NULL_TREE; } /* Check if DECL and ARGS form a partial-concept-id. If so, @@ -16093,15 +16091,8 @@ cp_parser_nonclass_name (cp_parser* parser) type_decl = strip_using_decl (type_decl); /* If we found an overload set, then it may refer to a concept-name. */ - if (flag_concepts - && (TREE_CODE (type_decl) == OVERLOAD - || BASELINK_P (type_decl) - || variable_concept_p (type_decl))) - { - /* Determine whether the overload refers to a concept. */ - if (tree decl = cp_parser_maybe_concept_name (parser, type_decl)) - return decl; - } + if (tree decl = cp_parser_maybe_concept_name (parser, type_decl)) + type_decl = decl; if (TREE_CODE (type_decl) != TYPE_DECL && (objc_is_id (identifier) || objc_is_class_name (identifier))) @@ -18183,7 +18174,7 @@ cp_parser_init_declarator (cp_parser* parser, "attributes after parenthesized initializer ignored"); /* And now complain about a non-function implicit template. */ - if (bogus_implicit_tmpl) + if (bogus_implicit_tmpl && decl != error_mark_node) error_at (DECL_SOURCE_LOCATION (decl), "non-function %qD declared as implicit template", decl); @@ -36681,17 +36672,6 @@ tree_type_is_auto_or_concept (const_tree t) return TREE_TYPE (t) && is_auto_or_concept (TREE_TYPE (t)); } -/* Returns the template declaration being called or evaluated as - part of the constraint check. Note that T must be a predicate - constraint (it can't be any other kind of constraint). */ -static tree -get_concept_from_constraint (tree t) -{ - tree tmpl, args; - placeholder_extract_concept_and_args (t, tmpl, args); - return DECL_TEMPLATE_RESULT (tmpl); -} - /* Add an implicit template type parameter to the CURRENT_TEMPLATE_PARMS (creating a new template parameter list if necessary). Returns the newly created template type parm. */ @@ -36711,9 +36691,14 @@ synthesize_implicit_template_parm (cp_parser *parser, tree constr) tree t = parser->implicit_template_parms; while (t) { - tree c = get_concept_from_constraint (TREE_TYPE (t)); - if (c == CONSTRAINED_PARM_CONCEPT (constr)) - return TREE_VALUE (t); + if (equivalent_placeholder_constraints (TREE_TYPE (t), constr)) + { + tree d = TREE_VALUE (t); + if (TREE_CODE (d) == PARM_DECL) + /* Return the TEMPLATE_PARM_INDEX. */ + d = DECL_INITIAL (d); + return d; + } t = TREE_CHAIN (t); } } @@ -36823,9 +36808,23 @@ synthesize_implicit_template_parm (cp_parser *parser, tree constr) /* Synthesize a new template parameter and track the current template parameter chain with implicit_template_parms. */ + tree proto = constr ? DECL_INITIAL (constr) : NULL_TREE; tree synth_id = make_generic_type_name (); - tree synth_tmpl_parm = finish_template_type_parm (class_type_node, - synth_id); + tree synth_tmpl_parm; + bool non_type = false; + + if (proto == NULL_TREE || TREE_CODE (proto) == TYPE_DECL) + synth_tmpl_parm + = finish_template_type_parm (class_type_node, synth_id); + else if (TREE_CODE (proto) == TEMPLATE_DECL) + synth_tmpl_parm + = finish_constrained_template_template_parm (proto, synth_id); + else + { + synth_tmpl_parm = copy_decl (proto); + DECL_NAME (synth_tmpl_parm) = synth_id; + non_type = true; + } // Attach the constraint to the parm before processing. tree node = build_tree_list (NULL_TREE, synth_tmpl_parm); @@ -36834,7 +36833,7 @@ synthesize_implicit_template_parm (cp_parser *parser, tree constr) = process_template_parm (parser->implicit_template_parms, input_location, node, - /*non_type=*/false, + /*non_type=*/non_type, /*param_pack=*/false); // Chain the new parameter to the list of implicit parameters. @@ -36844,7 +36843,10 @@ synthesize_implicit_template_parm (cp_parser *parser, tree constr) else parser->implicit_template_parms = new_parm; - tree new_type = TREE_TYPE (getdecls ()); + tree new_decl = getdecls (); + if (non_type) + /* Return the TEMPLATE_PARM_INDEX, not the PARM_DECL. */ + new_decl = DECL_INITIAL (new_decl); /* If creating a fully implicit function template, start the new implicit template parameter list with this synthesized type, otherwise grow the @@ -36878,7 +36880,7 @@ synthesize_implicit_template_parm (cp_parser *parser, tree constr) current_binding_level = entry_scope; - return new_type; + return new_decl; } /* Finish the declaration of a fully implicit function template. Such a diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 45eda3a6d72..bfea8e20257 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -441,21 +441,8 @@ push_inline_template_parms_recursive (tree parmlist, int levels) break; case PARM_DECL: - { - /* Make a CONST_DECL as is done in process_template_parm. - It is ugly that we recreate this here; the original - version built in process_template_parm is no longer - available. */ - tree decl = build_decl (DECL_SOURCE_LOCATION (parm), - CONST_DECL, DECL_NAME (parm), - TREE_TYPE (parm)); - DECL_ARTIFICIAL (decl) = 1; - TREE_CONSTANT (decl) = 1; - TREE_READONLY (decl) = 1; - DECL_INITIAL (decl) = DECL_INITIAL (parm); - SET_DECL_TEMPLATE_PARM_P (decl); - pushdecl (decl); - } + /* Push the CONST_DECL. */ + pushdecl (TEMPLATE_PARM_DECL (DECL_INITIAL (parm))); break; default: diff --git a/gcc/cselib.c b/gcc/cselib.c index 4fc70971881..8d73f15aa11 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -1329,15 +1329,15 @@ new_cselib_val (unsigned int hash, machine_mode mode, rtx x) static void add_mem_for_addr (cselib_val *addr_elt, cselib_val *mem_elt, rtx x) { - struct elt_loc_list *l; - addr_elt = canonical_cselib_val (addr_elt); mem_elt = canonical_cselib_val (mem_elt); /* Avoid duplicates. */ - for (l = mem_elt->locs; l; l = l->next) + addr_space_t as = MEM_ADDR_SPACE (x); + for (elt_loc_list *l = mem_elt->locs; l; l = l->next) if (MEM_P (l->loc) - && CSELIB_VAL_PTR (XEXP (l->loc, 0)) == addr_elt) + && CSELIB_VAL_PTR (XEXP (l->loc, 0)) == addr_elt + && MEM_ADDR_SPACE (l->loc) == as) { promote_debug_loc (l); return; @@ -1364,7 +1364,6 @@ cselib_lookup_mem (rtx x, int create) cselib_val **slot; cselib_val *addr; cselib_val *mem_elt; - struct elt_list *l; if (MEM_VOLATILE_P (x) || mode == BLKmode || !cselib_record_memory @@ -1379,14 +1378,19 @@ cselib_lookup_mem (rtx x, int create) addr = cselib_lookup (XEXP (x, 0), addr_mode, create, mode); if (! addr) return 0; - addr = canonical_cselib_val (addr); + /* Find a value that describes a value of our mode at that address. */ - for (l = addr->addr_list; l; l = l->next) + addr_space_t as = MEM_ADDR_SPACE (x); + for (elt_list *l = addr->addr_list; l; l = l->next) if (GET_MODE (l->elt->val_rtx) == mode) { - promote_debug_loc (l->elt->locs); - return l->elt; + for (elt_loc_list *l2 = l->elt->locs; l2; l2 = l2->next) + if (MEM_P (l2->loc) && MEM_ADDR_SPACE (l2->loc) == as) + { + promote_debug_loc (l->elt->locs); + return l->elt; + } } if (! create) diff --git a/gcc/dbxout.c b/gcc/dbxout.c index c13c68a4eb8..1b4a5eaeb6d 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -2479,11 +2479,11 @@ dbxout_expand_expr (tree expr) machine_mode mode; HOST_WIDE_INT bitsize, bitpos; tree offset, tem; - int volatilep = 0, unsignedp = 0; + int unsignedp, reversep, volatilep = 0; rtx x; - tem = get_inner_reference (expr, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, true); + tem = get_inner_reference (expr, &bitsize, &bitpos, &offset, &mode, + &unsignedp, &reversep, &volatilep, true); x = dbxout_expand_expr (tem); if (x == NULL || !MEM_P (x)) diff --git a/gcc/diagnostic-color.c b/gcc/diagnostic-color.c index 3fe49b2be47..d848dfca52e 100644 --- a/gcc/diagnostic-color.c +++ b/gcc/diagnostic-color.c @@ -164,7 +164,8 @@ static struct color_cap color_dict[] = { "warning", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_MAGENTA), 7, false }, { "note", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN), 4, false }, - { "caret", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN), 5, false }, + { "range1", SGR_SEQ (COLOR_FG_GREEN), 6, false }, + { "range2", SGR_SEQ (COLOR_FG_BLUE), 6, false }, { "locus", SGR_SEQ (COLOR_BOLD), 5, false }, { "quote", SGR_SEQ (COLOR_BOLD), 5, false }, { NULL, NULL, 0, false } @@ -195,7 +196,7 @@ colorize_stop (bool show_color) } /* Parse GCC_COLORS. The default would look like: - GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01' + GCC_COLORS='error=01;31:warning=01;35:note=01;36:range1=32:range2=34;locus=01:quote=01' No character escaping is needed or supported. */ static bool parse_gcc_colors (void) diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h index 6cc1e6b3ee5..749c847c9ce 100644 --- a/gcc/diagnostic-core.h +++ b/gcc/diagnostic-core.h @@ -63,18 +63,26 @@ extern bool warning_n (location_t, int, int, const char *, const char *, ...) ATTRIBUTE_GCC_DIAG(4,6) ATTRIBUTE_GCC_DIAG(5,6); extern bool warning_at (location_t, int, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4); +extern bool warning_at_rich_loc (rich_location *, int, const char *, ...) + ATTRIBUTE_GCC_DIAG(3,4); extern void error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2); extern void error_n (location_t, int, const char *, const char *, ...) ATTRIBUTE_GCC_DIAG(3,5) ATTRIBUTE_GCC_DIAG(4,5); extern void error_at (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3); +extern void error_at_rich_loc (rich_location *, const char *, ...) + ATTRIBUTE_GCC_DIAG(2,3); extern void fatal_error (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3) ATTRIBUTE_NORETURN; /* Pass one of the OPT_W* from options.h as the second parameter. */ extern bool pedwarn (location_t, int, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4); extern bool permerror (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3); +extern bool permerror_at_rich_loc (rich_location *, const char *, + ...) ATTRIBUTE_GCC_DIAG(2,3); extern void sorry (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2); extern void inform (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3); +extern void inform_at_rich_loc (rich_location *, const char *, + ...) ATTRIBUTE_GCC_DIAG(2,3); extern void inform_n (location_t, int, const char *, const char *, ...) ATTRIBUTE_GCC_DIAG(3,5) ATTRIBUTE_GCC_DIAG(4,5); extern void verbatim (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2); diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c index 147a2b8b71d..22203cdbaa3 100644 --- a/gcc/diagnostic-show-locus.c +++ b/gcc/diagnostic-show-locus.c @@ -36,131 +36,686 @@ along with GCC; see the file COPYING3. If not see # include #endif -/* If LINE is longer than MAX_WIDTH, and COLUMN is not smaller than - MAX_WIDTH by some margin, then adjust the start of the line such - that the COLUMN is smaller than MAX_WIDTH minus the margin. The - margin is either CARET_LINE_MARGIN characters or the difference - between the column and the length of the line, whatever is smaller. - The length of LINE is given by LINE_WIDTH. */ -static const char * -adjust_line (const char *line, int line_width, - int max_width, int *column_p) -{ - int right_margin = CARET_LINE_MARGIN; - int column = *column_p; - - gcc_checking_assert (line_width >= column); - right_margin = MIN (line_width - column, right_margin); - right_margin = max_width - right_margin; - if (line_width >= max_width && column > right_margin) +/* Classes for rendering source code and diagnostics, within an + anonymous namespace. + The work is done by "class layout", which embeds and uses + "class colorizer" and "class layout_range" to get things done. */ + +namespace { + +/* The state at a given point of the source code, assuming that we're + in a range: which range are we in, and whether we should draw a caret at + this point. */ + +struct point_state +{ + int range_idx; + bool draw_caret_p; +}; + +/* A class to inject colorization codes when printing the diagnostic locus. + + It has one kind of colorization for each of: + - normal text + - range 0 (the "primary location") + - range 1 + - range 2 + + The class caches the lookup of the color codes for the above. + + The class also has responsibility for tracking which of the above is + active, filtering out unnecessary changes. This allows + layout::print_source_line and layout::print_annotation_line + to simply request a colorization code for *every* character they print, + via this class, and have the filtering be done for them here. */ + +class colorizer +{ + public: + colorizer (diagnostic_context *context, + const diagnostic_info *diagnostic); + ~colorizer (); + + void set_range (int range_idx) { set_state (range_idx); } + void set_normal_text () { set_state (STATE_NORMAL_TEXT); } + + private: + void set_state (int state); + void begin_state (int state); + void finish_state (int state); + + private: + static const int STATE_NORMAL_TEXT = -1; + + diagnostic_context *m_context; + const diagnostic_info *m_diagnostic; + int m_current_state; + const char *m_caret_cs; + const char *m_caret_ce; + const char *m_range1_cs; + const char *m_range2_cs; + const char *m_range_ce; +}; + +/* A point within a layout_range; similar to an expanded_location, + but after filtering on file. */ + +class layout_point +{ + public: + layout_point (const expanded_location &exploc) + : m_line (exploc.line), + m_column (exploc.column) {} + + int m_line; + int m_column; +}; + +/* A class for use by "class layout" below: a filtered location_range. */ + +class layout_range +{ + public: + layout_range (const location_range *loc_range); + + bool contains_point (int row, int column) const; + + layout_point m_start; + layout_point m_finish; + bool m_show_caret_p; + layout_point m_caret; +}; + +/* A struct for use by layout::print_source_line for telling + layout::print_annotation_line the extents of the source line that + it printed, so that underlines can be clipped appropriately. */ + +struct line_bounds +{ + int m_first_non_ws; + int m_last_non_ws; +}; + +/* A class to control the overall layout when printing a diagnostic. + + The layout is determined within the constructor. + It is then printed by repeatedly calling the "print_source_line" + and "print_annotation_line" methods. + + We assume we have disjoint ranges. */ + +class layout +{ + public: + layout (diagnostic_context *context, + const diagnostic_info *diagnostic); + + int get_first_line () const { return m_first_line; } + int get_last_line () const { return m_last_line; } + + bool print_source_line (int row, line_bounds *lbounds_out); + void print_annotation_line (int row, const line_bounds lbounds); + + private: + bool + get_state_at_point (/* Inputs. */ + int row, int column, + int first_non_ws, int last_non_ws, + /* Outputs. */ + point_state *out_state); + + int + get_x_bound_for_row (int row, int caret_column, + int last_non_ws); + + private: + diagnostic_context *m_context; + pretty_printer *m_pp; + diagnostic_t m_diagnostic_kind; + expanded_location m_exploc; + colorizer m_colorizer; + bool m_colorize_source_p; + auto_vec m_layout_ranges; + int m_first_line; + int m_last_line; + int m_x_offset; +}; + +/* Implementation of "class colorizer". */ + +/* The constructor for "colorizer". Lookup and store color codes for the + different kinds of things we might need to print. */ + +colorizer::colorizer (diagnostic_context *context, + const diagnostic_info *diagnostic) : + m_context (context), + m_diagnostic (diagnostic), + m_current_state (STATE_NORMAL_TEXT) +{ + m_caret_ce = colorize_stop (pp_show_color (context->printer)); + m_range1_cs = colorize_start (pp_show_color (context->printer), "range1"); + m_range2_cs = colorize_start (pp_show_color (context->printer), "range2"); + m_range_ce = colorize_stop (pp_show_color (context->printer)); +} + +/* The destructor for "colorize". If colorization is on, print a code to + turn it off. */ + +colorizer::~colorizer () +{ + finish_state (m_current_state); +} + +/* Update state, printing color codes if necessary if there's a state + change. */ + +void +colorizer::set_state (int new_state) +{ + if (m_current_state != new_state) { - line += column - right_margin; - *column_p = right_margin; + finish_state (m_current_state); + m_current_state = new_state; + begin_state (new_state); } - return line; } -/* Print the physical source line corresponding to the location of - this diagnostic, and a caret indicating the precise column. This - function only prints two caret characters if the two locations - given by DIAGNOSTIC are on the same line according to - diagnostic_same_line(). */ +/* Turn on any colorization for STATE. */ + void -diagnostic_show_locus (diagnostic_context * context, - const diagnostic_info *diagnostic) +colorizer::begin_state (int state) { - if (!context->show_caret - || diagnostic_location (diagnostic, 0) <= BUILTINS_LOCATION - || diagnostic_location (diagnostic, 0) == context->last_location) - return; + switch (state) + { + case STATE_NORMAL_TEXT: + break; - context->last_location = diagnostic_location (diagnostic, 0); - expanded_location s0 = diagnostic_expand_location (diagnostic, 0); - expanded_location s1 = { }; - /* Zero-initialized. This is checked later by diagnostic_print_caret_line. */ + case 0: + /* Make range 0 be the same color as the "kind" text + (error vs warning vs note). */ + pp_string + (m_context->printer, + colorize_start (pp_show_color (m_context->printer), + diagnostic_get_color_for_kind (m_diagnostic->kind))); + break; - if (diagnostic_location (diagnostic, 1) > BUILTINS_LOCATION) - s1 = diagnostic_expand_location (diagnostic, 1); + case 1: + pp_string (m_context->printer, m_range1_cs); + break; - diagnostic_print_caret_line (context, s0, s1, - context->caret_chars[0], - context->caret_chars[1]); + case 2: + pp_string (m_context->printer, m_range2_cs); + break; + + default: + /* We don't expect more than 3 ranges per diagnostic. */ + gcc_unreachable (); + break; + } } -/* Print (part) of the source line given by xloc1 with caret1 pointing - at the column. If xloc2.column != 0 and it fits within the same - line as xloc1 according to diagnostic_same_line (), then caret2 is - printed at xloc2.colum. Otherwise, the caller has to set up things - to print a second caret line for xloc2. */ +/* Turn off any colorization for STATE. */ + void -diagnostic_print_caret_line (diagnostic_context * context, - expanded_location xloc1, - expanded_location xloc2, - char caret1, char caret2) -{ - if (!diagnostic_same_line (context, xloc1, xloc2)) - /* This will mean ignore xloc2. */ - xloc2.column = 0; - else if (xloc1.column == xloc2.column) - xloc2.column++; - - int cmax = MAX (xloc1.column, xloc2.column); +colorizer::finish_state (int state) +{ + switch (state) + { + case STATE_NORMAL_TEXT: + break; + + case 0: + pp_string (m_context->printer, m_caret_ce); + break; + + default: + /* Within a range. */ + gcc_assert (state > 0); + pp_string (m_context->printer, m_range_ce); + break; + } +} + +/* Implementation of class layout_range. */ + +/* The constructor for class layout_range. + Initialize various layout_point fields from expanded_location + equivalents; we've already filtered on file. */ + +layout_range::layout_range (const location_range *loc_range) +: m_start (loc_range->m_start), + m_finish (loc_range->m_finish), + m_show_caret_p (loc_range->m_show_caret_p), + m_caret (loc_range->m_caret) +{ +} + +/* Is (column, row) within the given range? + We've already filtered on the file. + + Ranges are closed (both limits are within the range). + + Example A: a single-line range: + start: (col=22, line=2) + finish: (col=38, line=2) + + |00000011111111112222222222333333333344444444444 + |34567890123456789012345678901234567890123456789 +--+----------------------------------------------- +01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +02|bbbbbbbbbbbbbbbbbbbSwwwwwwwwwwwwwwwFaaaaaaaaaaa +03|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + Example B: a multiline range with + start: (col=14, line=3) + finish: (col=08, line=5) + + |00000011111111112222222222333333333344444444444 + |34567890123456789012345678901234567890123456789 +--+----------------------------------------------- +01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +02|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +03|bbbbbbbbbbbSwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww +04|wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww +05|wwwwwFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +06|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +--+----------------------------------------------- + + Legend: + - 'b' indicates a point *before* the range + - 'S' indicates the start of the range + - 'w' indicates a point within the range + - 'F' indicates the finish of the range (which is + within it). + - 'a' indicates a subsequent point *after* the range. */ + +bool +layout_range::contains_point (int row, int column) const +{ + gcc_assert (m_start.m_line <= m_finish.m_line); + /* ...but the equivalent isn't true for the columns; + consider example B in the comment above. */ + + if (row < m_start.m_line) + /* Points before the first line of the range are + outside it (corresponding to line 01 in example A + and lines 01 and 02 in example B above). */ + return false; + + if (row == m_start.m_line) + /* On same line as start of range (corresponding + to line 02 in example A and line 03 in example B). */ + { + if (column < m_start.m_column) + /* Points on the starting line of the range, but + before the column in which it begins. */ + return false; + + if (row < m_finish.m_line) + /* This is a multiline range; the point + is within it (corresponds to line 03 in example B + from column 14 onwards) */ + return true; + else + { + /* This is a single-line range. */ + gcc_assert (row == m_finish.m_line); + return column <= m_finish.m_column; + } + } + + /* The point is in a line beyond that containing the + start of the range: lines 03 onwards in example A, + and lines 04 onwards in example B. */ + gcc_assert (row > m_start.m_line); + + if (row > m_finish.m_line) + /* The point is beyond the final line of the range + (lines 03 onwards in example A, and lines 06 onwards + in example B). */ + return false; + + if (row < m_finish.m_line) + { + /* The point is in a line that's fully within a multiline + range (e.g. line 04 in example B). */ + gcc_assert (m_start.m_line < m_finish.m_line); + return true; + } + + gcc_assert (row == m_finish.m_line); + + return column <= m_finish.m_column; +} + +/* Given a source line LINE of length LINE_WIDTH, determine the width + without any trailing whitespace. */ + +static int +get_line_width_without_trailing_whitespace (const char *line, int line_width) +{ + int result = line_width; + while (result > 0) + { + char ch = line[result - 1]; + if (ch == ' ' || ch == '\t') + result--; + else + break; + } + gcc_assert (result >= 0); + gcc_assert (result <= line_width); + gcc_assert (result == 0 || + (line[result - 1] != ' ' + && line[result -1] != '\t')); + return result; +} + +/* Implementation of class layout. */ + +/* Constructor for class layout. + + Filter the ranges from the rich_location to those that we can + sanely print, populating m_layout_ranges. + Determine the range of lines that we will print. + Determine m_x_offset, to ensure that the primary caret + will fit within the max_width provided by the diagnostic_context. */ + +layout::layout (diagnostic_context * context, + const diagnostic_info *diagnostic) +: m_context (context), + m_pp (context->printer), + m_diagnostic_kind (diagnostic->kind), + m_exploc (diagnostic->richloc->lazily_expand_location ()), + m_colorizer (context, diagnostic), + m_colorize_source_p (context->colorize_source_p), + m_layout_ranges (rich_location::MAX_RANGES), + m_first_line (m_exploc.line), + m_last_line (m_exploc.line), + m_x_offset (0) +{ + rich_location *richloc = diagnostic->richloc; + for (unsigned int idx = 0; idx < richloc->get_num_locations (); idx++) + { + /* This diagnostic printer can only cope with "sufficiently sane" ranges. + Ignore any ranges that are awkward to handle. */ + location_range *loc_range = richloc->get_range (idx); + + /* If any part of the range isn't in the same file as the primary + location of this diagnostic, ignore the range. */ + if (loc_range->m_start.file != m_exploc.file) + continue; + if (loc_range->m_finish.file != m_exploc.file) + continue; + if (loc_range->m_show_caret_p) + if (loc_range->m_caret.file != m_exploc.file) + continue; + + /* Passed all the tests; add the range to m_layout_ranges so that + it will be printed. */ + layout_range ri (loc_range); + m_layout_ranges.safe_push (ri); + + /* Update m_first_line/m_last_line if necessary. */ + if (loc_range->m_start.line < m_first_line) + m_first_line = loc_range->m_start.line; + if (loc_range->m_finish.line > m_last_line) + m_last_line = loc_range->m_finish.line; + } + + /* Adjust m_x_offset. + Center the primary caret to fit in max_width; all columns + will be adjusted accordingly. */ + int max_width = m_context->caret_max_width; int line_width; - const char *line = location_get_source_line (xloc1.file, xloc1.line, + const char *line = location_get_source_line (m_exploc.file, m_exploc.line, &line_width); - if (line == NULL || cmax > line_width) - return; + if (line && m_exploc.column <= line_width) + { + int right_margin = CARET_LINE_MARGIN; + int column = m_exploc.column; + right_margin = MIN (line_width - column, right_margin); + right_margin = max_width - right_margin; + if (line_width >= max_width && column > right_margin) + m_x_offset = column - right_margin; + gcc_assert (m_x_offset >= 0); + } +} - /* Center the interesting part of the source line to fit in - max_width, and adjust all columns accordingly. */ - int max_width = context->caret_max_width; - int offset = (int) cmax; - line = adjust_line (line, line_width, max_width, &offset); - offset -= cmax; - cmax += offset; - xloc1.column += offset; - if (xloc2.column) - xloc2.column += offset; - - /* Print the source line. */ - pp_newline (context->printer); - const char *saved_prefix = pp_get_prefix (context->printer); - pp_set_prefix (context->printer, NULL); - pp_space (context->printer); - while (max_width > 0 && line_width > 0) +/* Attempt to print line ROW of source code, potentially colorized at any + ranges. + Return true if the line was printed, populating *LBOUNDS_OUT. + Return false if the source line could not be read, leaving *LBOUNDS_OUT + untouched. */ + +bool +layout::print_source_line (int row, line_bounds *lbounds_out) +{ + int line_width; + const char *line = location_get_source_line (m_exploc.file, row, + &line_width); + if (!line) + return false; + + line += m_x_offset; + + m_colorizer.set_normal_text (); + + /* We will stop printing the source line at any trailing + whitespace. */ + line_width = get_line_width_without_trailing_whitespace (line, + line_width); + + pp_space (m_pp); + int first_non_ws = INT_MAX; + int last_non_ws = 0; + int column; + for (column = 1 + m_x_offset; column <= line_width; column++) { + /* Assuming colorization is enabled for the caret and underline + characters, we may also colorize the associated characters + within the source line. + + For frontends that generate range information, we color the + associated characters in the source line the same as the + carets and underlines in the annotation line, to make it easier + for the reader to see the pertinent code. + + For frontends that only generate carets, we don't colorize the + characters above them, since this would look strange (e.g. + colorizing just the first character in a token). */ + if (m_colorize_source_p) + { + bool in_range_p; + point_state state; + in_range_p = get_state_at_point (row, column, + 0, INT_MAX, + &state); + if (in_range_p) + m_colorizer.set_range (state.range_idx); + else + m_colorizer.set_normal_text (); + } char c = *line == '\t' ? ' ' : *line; if (c == '\0') c = ' '; - pp_character (context->printer, c); - max_width--; - line_width--; + if (c != ' ') + { + last_non_ws = column; + if (first_non_ws == INT_MAX) + first_non_ws = column; + } + pp_character (m_pp, c); line++; } - pp_newline (context->printer); + pp_newline (m_pp); + + lbounds_out->m_first_non_ws = first_non_ws; + lbounds_out->m_last_non_ws = last_non_ws; + return true; +} + +/* Print a line consisting of the caret/underlines for the given + source line. */ - /* Print the caret under the line. */ - const char *caret_cs, *caret_ce; - caret_cs = colorize_start (pp_show_color (context->printer), "caret"); - caret_ce = colorize_stop (pp_show_color (context->printer)); - int cmin = xloc2.column - ? MIN (xloc1.column, xloc2.column) : xloc1.column; - int caret_min = cmin == xloc1.column ? caret1 : caret2; - int caret_max = cmin == xloc1.column ? caret2 : caret1; - - /* cmin is >= 1, but we indent with an extra space at the start like - we did above. */ +void +layout::print_annotation_line (int row, const line_bounds lbounds) +{ + int x_bound = get_x_bound_for_row (row, m_exploc.column, + lbounds.m_last_non_ws); + + pp_space (m_pp); + for (int column = 1 + m_x_offset; column < x_bound; column++) + { + bool in_range_p; + point_state state; + in_range_p = get_state_at_point (row, column, + lbounds.m_first_non_ws, + lbounds.m_last_non_ws, + &state); + if (in_range_p) + { + /* Within a range. Draw either the caret or an underline. */ + m_colorizer.set_range (state.range_idx); + if (state.draw_caret_p) + /* Draw the caret. */ + pp_character (m_pp, m_context->caret_chars[state.range_idx]); + else + pp_character (m_pp, '~'); + } + else + { + /* Not in a range. */ + m_colorizer.set_normal_text (); + pp_character (m_pp, ' '); + } + } + pp_newline (m_pp); +} + +/* Return true if (ROW/COLUMN) is within a range of the layout. + If it returns true, OUT_STATE is written to, with the + range index, and whether we should draw the caret at + (ROW/COLUMN) (as opposed to an underline). */ + +bool +layout::get_state_at_point (/* Inputs. */ + int row, int column, + int first_non_ws, int last_non_ws, + /* Outputs. */ + point_state *out_state) +{ + layout_range *range; int i; - for (i = 0; i < cmin; i++) - pp_space (context->printer); - pp_printf (context->printer, "%s%c%s", caret_cs, caret_min, caret_ce); + FOR_EACH_VEC_ELT (m_layout_ranges, i, range) + { + if (range->contains_point (row, column)) + { + out_state->range_idx = i; + + /* Are we at the range's caret? is it visible? */ + out_state->draw_caret_p = false; + if (row == range->m_caret.m_line + && column == range->m_caret.m_column) + out_state->draw_caret_p = range->m_show_caret_p; - if (xloc2.column) + /* Within a multiline range, don't display any underline + in any leading or trailing whitespace on a line. + We do display carets, however. */ + if (!out_state->draw_caret_p) + if (column < first_non_ws || column > last_non_ws) + return false; + + /* We are within a range. */ + return true; + } + } + + return false; +} + +/* Helper function for use by layout::print_line when printing the + annotation line under the source line. + Get the column beyond the rightmost one that could contain a caret or + range marker, given that we stop rendering at trailing whitespace. + ROW is the source line within the given file. + CARET_COLUMN is the column of range 0's caret. + LAST_NON_WS_COLUMN is the last column containing a non-whitespace + character of source (as determined when printing the source line). */ + +int +layout::get_x_bound_for_row (int row, int caret_column, + int last_non_ws_column) +{ + int result = caret_column + 1; + + layout_range *range; + int i; + FOR_EACH_VEC_ELT (m_layout_ranges, i, range) { - for (i++; i < cmax; i++) - pp_space (context->printer); - pp_printf (context->printer, "%s%c%s", caret_cs, caret_max, caret_ce); + if (row >= range->m_start.m_line) + { + if (range->m_finish.m_line == row) + { + /* On the final line within a range; ensure that + we render up to the end of the range. */ + if (result <= range->m_finish.m_column) + result = range->m_finish.m_column + 1; + } + else if (row < range->m_finish.m_line) + { + /* Within a multiline range; ensure that we render up to the + last non-whitespace column. */ + if (result <= last_non_ws_column) + result = last_non_ws_column + 1; + } + } } + + return result; +} + +} /* End of anonymous namespace. */ + +/* Print the physical source code corresponding to the location of + this diagnostic, with additional annotations. */ + +void +diagnostic_show_locus (diagnostic_context * context, + const diagnostic_info *diagnostic) +{ + if (!context->show_caret + || diagnostic_location (diagnostic, 0) <= BUILTINS_LOCATION + || diagnostic_location (diagnostic, 0) == context->last_location) + return; + + context->last_location = diagnostic_location (diagnostic, 0); + + pp_newline (context->printer); + + const char *saved_prefix = pp_get_prefix (context->printer); + pp_set_prefix (context->printer, NULL); + + { + layout layout (context, diagnostic); + int last_line = layout.get_last_line (); + for (int row = layout.get_first_line (); + row <= last_line; + row++) + { + /* Print the source line, followed by an annotation line + consisting of any caret/underlines. If the source line can't + be read, print nothing. */ + line_bounds lbounds; + if (layout.print_source_line (row, &lbounds)) + layout.print_annotation_line (row, lbounds); + } + + /* The closing scope here leads to the dtor for layout and thus + colorizer being called here, which affects the precise + place where colorization is turned off in the unittest + for colorized output. */ + } + pp_set_prefix (context->printer, saved_prefix); - pp_needs_newline (context->printer) = true; } diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 11c369d8292..ee034e77170 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -144,7 +144,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts) context->classify_diagnostic[i] = DK_UNSPECIFIED; context->show_caret = false; diagnostic_set_caret_max_width (context, pp_line_cutoff (context->printer)); - for (i = 0; i < MAX_LOCATIONS_PER_MESSAGE; i++) + for (i = 0; i < rich_location::MAX_RANGES; i++) context->caret_chars[i] = '^'; context->show_option_requested = false; context->abort_on_error = false; @@ -234,16 +234,15 @@ diagnostic_finish (diagnostic_context *context) translated. */ void diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg, - va_list *args, location_t location, + va_list *args, rich_location *richloc, diagnostic_t kind) { + gcc_assert (richloc); diagnostic->message.err_no = errno; diagnostic->message.args_ptr = args; diagnostic->message.format_spec = msg; - diagnostic->message.set_location (0, location); - for (int i = 1; i < MAX_LOCATIONS_PER_MESSAGE; i++) - diagnostic->message.set_location (i, UNKNOWN_LOCATION); - diagnostic->override_column = 0; + diagnostic->message.m_richloc = richloc; + diagnostic->richloc = richloc; diagnostic->kind = kind; diagnostic->option_index = 0; } @@ -252,10 +251,27 @@ diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg, translated. */ void diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid, - va_list *args, location_t location, + va_list *args, rich_location *richloc, diagnostic_t kind) { - diagnostic_set_info_translated (diagnostic, _(gmsgid), args, location, kind); + gcc_assert (richloc); + diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind); +} + +static const char *const diagnostic_kind_color[] = { +#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C), +#include "diagnostic.def" +#undef DEFINE_DIAGNOSTIC_KIND + NULL +}; + +/* Get a color name for diagnostics of type KIND + Result could be NULL. */ + +const char * +diagnostic_get_color_for_kind (diagnostic_t kind) +{ + return diagnostic_kind_color[kind]; } /* Return a malloc'd string describing a location. The caller is @@ -270,12 +286,6 @@ diagnostic_build_prefix (diagnostic_context *context, #undef DEFINE_DIAGNOSTIC_KIND "must-not-happen" }; - static const char *const diagnostic_kind_color[] = { -#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C), -#include "diagnostic.def" -#undef DEFINE_DIAGNOSTIC_KIND - NULL - }; gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND); const char *text = _(diagnostic_kind_text[diagnostic->kind]); @@ -770,10 +780,14 @@ diagnostic_report_diagnostic (diagnostic_context *context, if (option_text) { + const char *cs + = colorize_start (pp_show_color (context->printer), + diagnostic_kind_color[diagnostic->kind]); + const char *ce = colorize_stop (pp_show_color (context->printer)); diagnostic->message.format_spec = ACONCAT ((diagnostic->message.format_spec, " ", - "[", option_text, "]", + "[", cs, option_text, ce, "]", NULL)); free (option_text); } @@ -853,9 +867,40 @@ diagnostic_append_note (diagnostic_context *context, diagnostic_info diagnostic; va_list ap; const char *saved_prefix; + rich_location richloc (location); va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_NOTE); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE); + if (context->inhibit_notes_p) + { + va_end (ap); + return; + } + saved_prefix = pp_get_prefix (context->printer); + pp_set_prefix (context->printer, + diagnostic_build_prefix (context, &diagnostic)); + pp_newline (context->printer); + pp_format (context->printer, &diagnostic.message); + pp_output_formatted_text (context->printer); + pp_destroy_prefix (context->printer); + pp_set_prefix (context->printer, saved_prefix); + diagnostic_show_locus (context, &diagnostic); + va_end (ap); +} + +/* Same as diagnostic_append_note, but at RICHLOC. */ + +void +diagnostic_append_note_at_rich_loc (diagnostic_context *context, + rich_location *richloc, + const char * gmsgid, ...) +{ + diagnostic_info diagnostic; + va_list ap; + const char *saved_prefix; + + va_start (ap, gmsgid); + diagnostic_set_info (&diagnostic, gmsgid, &ap, richloc, DK_NOTE); if (context->inhibit_notes_p) { va_end (ap); @@ -880,16 +925,17 @@ emit_diagnostic (diagnostic_t kind, location_t location, int opt, diagnostic_info diagnostic; va_list ap; bool ret; + rich_location richloc (location); va_start (ap, gmsgid); if (kind == DK_PERMERROR) { - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, permissive_error_kind (global_dc)); diagnostic.option_index = permissive_error_option (global_dc); } else { - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, kind); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, kind); if (kind == DK_WARNING || kind == DK_PEDWARN) diagnostic.option_index = opt; } @@ -903,12 +949,26 @@ emit_diagnostic (diagnostic_t kind, location_t location, int opt, message. */ void inform (location_t location, const char *gmsgid, ...) +{ + diagnostic_info diagnostic; + va_list ap; + rich_location richloc (location); + + va_start (ap, gmsgid); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE); + report_diagnostic (&diagnostic); + va_end (ap); +} + +/* Same as "inform", but at RICHLOC. */ +void +inform_at_rich_loc (rich_location *richloc, const char *gmsgid, ...) { diagnostic_info diagnostic; va_list ap; va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_NOTE); + diagnostic_set_info (&diagnostic, gmsgid, &ap, richloc, DK_NOTE); report_diagnostic (&diagnostic); va_end (ap); } @@ -921,11 +981,12 @@ inform_n (location_t location, int n, const char *singular_gmsgid, { diagnostic_info diagnostic; va_list ap; + rich_location richloc (location); va_start (ap, plural_gmsgid); diagnostic_set_info_translated (&diagnostic, ngettext (singular_gmsgid, plural_gmsgid, n), - &ap, location, DK_NOTE); + &ap, &richloc, DK_NOTE); report_diagnostic (&diagnostic); va_end (ap); } @@ -939,9 +1000,10 @@ warning (int opt, const char *gmsgid, ...) diagnostic_info diagnostic; va_list ap; bool ret; + rich_location richloc (input_location); va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_WARNING); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_WARNING); diagnostic.option_index = opt; ret = report_diagnostic (&diagnostic); @@ -955,13 +1017,31 @@ warning (int opt, const char *gmsgid, ...) bool warning_at (location_t location, int opt, const char *gmsgid, ...) +{ + diagnostic_info diagnostic; + va_list ap; + bool ret; + rich_location richloc (location); + + va_start (ap, gmsgid); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_WARNING); + diagnostic.option_index = opt; + ret = report_diagnostic (&diagnostic); + va_end (ap); + return ret; +} + +/* Same as warning at, but using RICHLOC. */ + +bool +warning_at_rich_loc (rich_location *richloc, int opt, const char *gmsgid, ...) { diagnostic_info diagnostic; va_list ap; bool ret; va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_WARNING); + diagnostic_set_info (&diagnostic, gmsgid, &ap, richloc, DK_WARNING); diagnostic.option_index = opt; ret = report_diagnostic (&diagnostic); va_end (ap); @@ -979,11 +1059,13 @@ warning_n (location_t location, int opt, int n, const char *singular_gmsgid, diagnostic_info diagnostic; va_list ap; bool ret; + rich_location richloc (location); va_start (ap, plural_gmsgid); diagnostic_set_info_translated (&diagnostic, ngettext (singular_gmsgid, plural_gmsgid, n), - &ap, location, DK_WARNING); + &ap, &richloc, DK_WARNING +); diagnostic.option_index = opt; ret = report_diagnostic (&diagnostic); va_end (ap); @@ -1009,9 +1091,10 @@ pedwarn (location_t location, int opt, const char *gmsgid, ...) diagnostic_info diagnostic; va_list ap; bool ret; + rich_location richloc (location); va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_PEDWARN); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN); diagnostic.option_index = opt; ret = report_diagnostic (&diagnostic); va_end (ap); @@ -1031,9 +1114,28 @@ permerror (location_t location, const char *gmsgid, ...) diagnostic_info diagnostic; va_list ap; bool ret; + rich_location richloc (location); va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, location, + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, + permissive_error_kind (global_dc)); + diagnostic.option_index = permissive_error_option (global_dc); + ret = report_diagnostic (&diagnostic); + va_end (ap); + return ret; +} + +/* Same as "permerror", but at RICHLOC. */ + +bool +permerror_at_rich_loc (rich_location *richloc, const char *gmsgid, ...) +{ + diagnostic_info diagnostic; + va_list ap; + bool ret; + + va_start (ap, gmsgid); + diagnostic_set_info (&diagnostic, gmsgid, &ap, richloc, permissive_error_kind (global_dc)); diagnostic.option_index = permissive_error_option (global_dc); ret = report_diagnostic (&diagnostic); @@ -1048,9 +1150,10 @@ error (const char *gmsgid, ...) { diagnostic_info diagnostic; va_list ap; + rich_location richloc (input_location); va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_ERROR); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_ERROR); report_diagnostic (&diagnostic); va_end (ap); } @@ -1063,11 +1166,12 @@ error_n (location_t location, int n, const char *singular_gmsgid, { diagnostic_info diagnostic; va_list ap; + rich_location richloc (location); va_start (ap, plural_gmsgid); diagnostic_set_info_translated (&diagnostic, ngettext (singular_gmsgid, plural_gmsgid, n), - &ap, location, DK_ERROR); + &ap, &richloc, DK_ERROR); report_diagnostic (&diagnostic); va_end (ap); } @@ -1078,9 +1182,25 @@ error_at (location_t loc, const char *gmsgid, ...) { diagnostic_info diagnostic; va_list ap; + rich_location richloc (loc); va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, loc, DK_ERROR); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_ERROR); + report_diagnostic (&diagnostic); + va_end (ap); +} + +/* Same as above, but use RICH_LOC. */ + +void +error_at_rich_loc (rich_location *rich_loc, const char *gmsgid, ...) +{ + diagnostic_info diagnostic; + va_list ap; + + va_start (ap, gmsgid); + diagnostic_set_info (&diagnostic, gmsgid, &ap, rich_loc, + DK_ERROR); report_diagnostic (&diagnostic); va_end (ap); } @@ -1093,9 +1213,10 @@ sorry (const char *gmsgid, ...) { diagnostic_info diagnostic; va_list ap; + rich_location richloc (input_location); va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_SORRY); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_SORRY); report_diagnostic (&diagnostic); va_end (ap); } @@ -1116,9 +1237,10 @@ fatal_error (location_t loc, const char *gmsgid, ...) { diagnostic_info diagnostic; va_list ap; + rich_location richloc (loc); va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, loc, DK_FATAL); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_FATAL); report_diagnostic (&diagnostic); va_end (ap); @@ -1134,9 +1256,10 @@ internal_error (const char *gmsgid, ...) { diagnostic_info diagnostic; va_list ap; + rich_location richloc (input_location); va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_ICE); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_ICE); report_diagnostic (&diagnostic); va_end (ap); @@ -1151,9 +1274,10 @@ internal_error_no_backtrace (const char *gmsgid, ...) { diagnostic_info diagnostic; va_list ap; + rich_location richloc (input_location); va_start (ap, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_ICE_NOBT); + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_ICE_NOBT); report_diagnostic (&diagnostic); va_end (ap); @@ -1217,3 +1341,17 @@ real_abort (void) { abort (); } + +/* Display the given source_range instance, with MSG as a descriptive + comment. This issues a "note" diagnostic at the range. + + This is declared within libcpp, but implemented here, since it + makes use of the diagnostic-printing machinery. */ + +DEBUG_FUNCTION void +source_range::debug (const char *msg) const +{ + rich_location richloc (m_start); + richloc.add_range (m_start, m_finish, false); + inform_at_rich_loc (&richloc, "%s", msg); +} diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 7fcb6a8cd0e..9096e16eb07 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -29,10 +29,12 @@ along with GCC; see the file COPYING3. If not see list in diagnostic.def. */ struct diagnostic_info { - /* Text to be formatted. It also contains the location(s) for this - diagnostic. */ + /* Text to be formatted. */ text_info message; - unsigned int override_column; + + /* The location at which the diagnostic is to be reported. */ + rich_location *richloc; + /* Auxiliary data for client. */ void *x_data; /* The kind of diagnostic it is about. */ @@ -102,8 +104,8 @@ struct diagnostic_context /* Maximum width of the source line printed. */ int caret_max_width; - /* Characters used for caret diagnostics. */ - char caret_chars[MAX_LOCATIONS_PER_MESSAGE]; + /* Character used for caret diagnostics. */ + char caret_chars[rich_location::MAX_RANGES]; /* True if we should print the command line option which controls each diagnostic, if known. */ @@ -181,6 +183,15 @@ struct diagnostic_context int lock; bool inhibit_notes_p; + + /* When printing source code, should the characters at carets and ranges + be colorized? (assuming colorization is on at all). + This should be true for frontends that generate range information + (so that the ranges of code are colorized), + and false for frontends that merely specify points within the + source code (to avoid e.g. colorizing just the first character in + a token, which would look strange). */ + bool colorize_source_p; }; static inline void @@ -252,10 +263,6 @@ extern diagnostic_context *global_dc; #define report_diagnostic(D) diagnostic_report_diagnostic (global_dc, D) -/* Override the column number to be used for reporting a - diagnostic. */ -#define diagnostic_override_column(DI, COL) (DI)->override_column = (COL) - /* Override the option index to be used for reporting a diagnostic. */ #define diagnostic_override_option_index(DI, OPTIDX) \ @@ -279,13 +286,17 @@ extern bool diagnostic_report_diagnostic (diagnostic_context *, diagnostic_info *); #ifdef ATTRIBUTE_GCC_DIAG extern void diagnostic_set_info (diagnostic_info *, const char *, va_list *, - location_t, diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0); + rich_location *, diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0); extern void diagnostic_set_info_translated (diagnostic_info *, const char *, - va_list *, location_t, + va_list *, rich_location *, diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0); extern void diagnostic_append_note (diagnostic_context *, location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4); +extern void diagnostic_append_note_at_rich_loc (diagnostic_context *, + rich_location *, + const char *, ...) + ATTRIBUTE_GCC_DIAG(3,4); #endif extern char *diagnostic_build_prefix (diagnostic_context *, const diagnostic_info *); void default_diagnostic_starter (diagnostic_context *, diagnostic_info *); @@ -306,6 +317,14 @@ diagnostic_location (const diagnostic_info * diagnostic, int which = 0) return diagnostic->message.get_location (which); } +/* Return the number of locations to be printed in DIAGNOSTIC. */ + +static inline unsigned int +diagnostic_num_locations (const diagnostic_info * diagnostic) +{ + return diagnostic->message.m_richloc->get_num_locations (); +} + /* Expand the location of this diagnostic. Use this function for consistency. Parameter WHICH specifies which location. By default, expand the first one. */ @@ -313,12 +332,7 @@ diagnostic_location (const diagnostic_info * diagnostic, int which = 0) static inline expanded_location diagnostic_expand_location (const diagnostic_info * diagnostic, int which = 0) { - expanded_location s - = expand_location_to_spelling_point (diagnostic_location (diagnostic, - which)); - if (which == 0 && diagnostic->override_column) - s.column = diagnostic->override_column; - return s; + return diagnostic->richloc->get_range (which)->m_caret; } /* This is somehow the right-side margin of a caret line, that is, we @@ -338,11 +352,7 @@ diagnostic_same_line (const diagnostic_context *context, && context->caret_max_width - CARET_LINE_MARGIN > abs (s1.column - s2.column); } -void -diagnostic_print_caret_line (diagnostic_context * context, - expanded_location xloc1, - expanded_location xloc2, - char caret1, char caret2); +extern const char *diagnostic_get_color_for_kind (diagnostic_t kind); /* Pure text formatting support functions. */ extern char *file_name_as_prefix (diagnostic_context *, const char *); diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 26afc00c570..aab6bad905c 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1261,8 +1261,8 @@ As an extension, GNU C supports named address spaces as defined in the N1275 draft of ISO/IEC DTR 18037. Support for named address spaces in GCC will evolve as the draft technical report changes. Calling conventions for any target might also change. At -present, only the AVR, SPU, M32C, and RL78 targets support address -spaces other than the generic address space. +present, only the AVR, SPU, M32C, RL78, and x86 targets support +address spaces other than the generic address space. Address space identifiers may be used exactly like any other C type qualifier (e.g., @code{const} or @code{volatile}). See the N1275 @@ -1451,6 +1451,49 @@ It may use runtime library support, or generate special machine instructions to access that address space. +@subsection x86 Named Address Spaces +@cindex x86 named address spaces + +On the x86 target, variables may be declared as being relative +to the @code{%fs} or @code{%gs} segments. + +@table @code +@item __seg_fs +@itemx __seg_gs +@cindex @code{__seg_fs} x86 named address space +@cindex @code{__seg_gs} x86 named address space +The object is accessed with the respective segment override prefix. + +The respective segment base must be set via some method specific to +the operating system. Rather than require an expensive system call +to retrieve the segment base, these address spaces are not considered +to be subspaces of the generic (flat) address space. This means that +explicit casts are required to convert pointers between these address +spaces and the generic address space. In practice the application +should cast to @code{uintptr_t} and apply the segment base offset +that it installed previously. + +The preprocessor symbols @code{__SEG_FS} and @code{__SEG_GS} are +defined when these address spaces are supported. + +@item __seg_tls +@cindex @code{__seg_tls} x86 named address space +Some operating systems define either the @code{%fs} or @code{%gs} +segment as the thread-local storage base for each thread. Objects +within this address space are accessed with the appropriate +segment override prefix. + +The pointer located at address 0 within the segment contains the +offset of the segment within the generic address space. Thus this +address space is considered a subspace of the generic address space, +and the known segment offset is applied when converting addresses +to and from the generic address space. + +The preprocessor symbol @code{__SEG_TLS} is defined when this +address space is supported. + +@end table + @node Zero Length @section Arrays of Length Zero @cindex arrays of length zero @@ -6395,6 +6438,42 @@ of the structure or union is placed to minimize the memory required. When attached to an @code{enum} definition, it indicates that the smallest integral type should be used. +@item scalar_storage_order ("@var{endianness}") +@cindex @code{scalar_storage_order} type attribute +When attached to a @code{union} or a @code{struct}, this attribute sets +the storage order, aka endianness, of the scalar fields of the type, as +well as the array fields whose component is scalar. The supported +endianness are @code{big-endian} and @code{little-endian}. The attribute +has no effects on fields which are themselves a @code{union}, a @code{struct} +or an array whose component is a @code{union} or a @code{struct}, and it is +possible to have fields with a different scalar storage order than the +enclosing type. + +This attribute is supported only for targets that use a uniform default +scalar storage order (fortunately, most of them), i.e. targets that store +the scalars either all in big-endian or all in little-endian. + +Additional restrictions are enforced for types with the reverse scalar +storage order with regard to the scalar storage order of the target: + +@itemize +@item Taking the address of a scalar field of a @code{union} or a +@code{struct} with reverse scalar storage order is not permitted and will +yield an error. +@item Taking the address of an array field, whose component is scalar, of +a @code{union} or a @code{struct} with reverse scalar storage order is +permitted but will yield a warning, unless @option{-Wno-scalar-storage-order} +is specified. +@item Taking the address of a @code{union} or a @code{struct} with reverse +scalar storage order is permitted. +@end itemize + +These restrictions exist because the storage order attribute is lost when +the address of a scalar or the address of an array with scalar component +is taken, so storing indirectly through this address will generally not work. +The second case is nevertheless allowed to be able to perform a block copy +from or to the array. + @item transparent_union @cindex @code{transparent_union} type attribute @@ -18432,7 +18511,7 @@ for further explanation. * Darwin Pragmas:: * Solaris Pragmas:: * Symbol-Renaming Pragmas:: -* Structure-Packing Pragmas:: +* Structure-Layout Pragmas:: * Weak Pragmas:: * Diagnostic Pragmas:: * Visibility Pragmas:: @@ -18708,8 +18787,8 @@ the name does not change. always the C-language name. @end enumerate -@node Structure-Packing Pragmas -@subsection Structure-Packing Pragmas +@node Structure-Layout Pragmas +@subsection Structure-Layout Pragmas For compatibility with Microsoft Windows compilers, GCC supports a set of @code{#pragma} directives that change the maximum alignment of @@ -18732,17 +18811,30 @@ multiple @code{#pragma pack(@var{n})} instances and finalized by a single @code{#pragma pack(pop)}. @end enumerate -Some targets, e.g.@: x86 and PowerPC, support the @code{ms_struct} -@code{#pragma} which lays out a structure as the documented -@code{__attribute__ ((ms_struct))}. +Some targets, e.g.@: x86 and PowerPC, support the @code{#pragma ms_struct} +directive which lays out structures and unions subsequently defined as the +documented @code{__attribute__ ((ms_struct))}. + @enumerate -@item @code{#pragma ms_struct on} turns on the layout for structures -declared. -@item @code{#pragma ms_struct off} turns off the layout for structures -declared. +@item @code{#pragma ms_struct on} turns on the Microsoft layout. +@item @code{#pragma ms_struct off} turns off the Microsoft layout. @item @code{#pragma ms_struct reset} goes back to the default layout. @end enumerate +Most targets also support the @code{#pragma scalar_storage_order} directive +which lays out structures and unions subsequently defined as the documented +@code{__attribute__ ((scalar_storage_order))}. + +@enumerate +@item @code{#pragma scalar_storage_order big-endian} sets the storage order +of the scalar fields to big-endian. +@item @code{#pragma scalar_storage_order little-endian} sets the storage order +of the scalar fields to little-endian. +@item @code{#pragma scalar_storage_order default} goes back to the endianness +that was in effect when compilation started (see also command-line option +@option{-fsso-struct=@var{endianness}} @pxref{C Dialect Options}). +@end enumerate + @node Weak Pragmas @subsection Weak Pragmas diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 587e30e613d..dc9a4e73712 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -169,10 +169,11 @@ in the following sections. -aux-info @var{filename} -fallow-parameterless-variadic-functions @gol -fno-asm -fno-builtin -fno-builtin-@var{function} @gol -fhosted -ffreestanding -fopenacc -fopenmp -fopenmp-simd @gol --fms-extensions -fplan9-extensions -trigraphs -traditional -traditional-cpp @gol +-fms-extensions -fplan9-extensions -fsso-struct=@var{endianness} -fallow-single-precision -fcond-mismatch -flax-vector-conversions @gol -fsigned-bitfields -fsigned-char @gol --funsigned-bitfields -funsigned-char} +-funsigned-bitfields -funsigned-char @gol +-trigraphs -traditional -traditional-cpp} @item C++ Language Options @xref{C++ Dialect Options,,Options Controlling C++ Dialect}. @@ -278,6 +279,7 @@ Objective-C and Objective-C++ Dialects}. -Wshift-overflow -Wshift-overflow=@var{n} @gol -Wshift-count-negative -Wshift-count-overflow -Wshift-negative-value @gol -Wsign-compare -Wsign-conversion -Wfloat-conversion @gol +-Wno-scalar-storage-order @gol -Wsizeof-pointer-memaccess -Wsizeof-array-argument @gol -Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol -Wstrict-aliasing=n @gol -Wstrict-overflow -Wstrict-overflow=@var{n} @gol @@ -521,6 +523,7 @@ Objective-C and Objective-C++ Dialects}. -mtls-size=@var{size} @gol -mfix-cortex-a53-835769 -mno-fix-cortex-a53-835769 @gol -mfix-cortex-a53-843419 -mno-fix-cortex-a53-843419 @gol +-mlow-precision-recip-sqrt -mno-low-precision-recip-sqrt@gol -march=@var{name} -mcpu=@var{name} -mtune=@var{name}} @emph{Adapteva Epiphany Options} @@ -2075,6 +2078,17 @@ These options control whether a bit-field is signed or unsigned, when the declaration does not use either @code{signed} or @code{unsigned}. By default, such a bit-field is signed, because this is consistent: the basic integer types such as @code{int} are signed types. + +@item -fsso-struct=@var{endianness} +@opindex fsso-struct +Set the default scalar storage order of structures and unions to the +specified endianness. The accepted values are @samp{big-endian} and +@samp{little-endian}. If the option is not passed, the compiler uses +the native endianness of the target. This option is not supported for C++. + +@strong{Warning:} the @option{-fsso-struct} switch causes GCC to generate +code that is not binary compatible with code generated without it if the +specified endianness is not the native endianness of the target. @end table @node C++ Dialect Options @@ -5112,6 +5126,11 @@ This includes conversions from real to integer, and from higher precision real to lower precision real values. This option is also enabled by @option{-Wconversion}. +@item -Wno-scalar-storage-order +@opindex -Wno-scalar-storage-order +@opindex -Wscalar-storage-order +Do not warn on suspicious constructs involving reverse scalar storage order. + @item -Wsized-deallocation @r{(C++ and Objective-C++ only)} @opindex Wsized-deallocation @opindex Wno-sized-deallocation @@ -12519,6 +12538,17 @@ Enable or disable the workaround for the ARM Cortex-A53 erratum number 843419. This erratum workaround is made at link time and this will only pass the corresponding flag to the linker. +@item -mlow-precision-recip-sqrt +@item -mno-low-precision-recip-sqrt +@opindex -mlow-precision-recip-sqrt +@opindex -mno-low-precision-recip-sqrt +The square root estimate uses two steps instead of three for double-precision, +and one step instead of two for single-precision. +Thus reducing latency and precision. +This is only relevant if @option{-ffast-math} activates +reciprocal square root estimate instructions. +Which in turn depends on the target processor. + @item -march=@var{name} @opindex march Specify the name of the target architecture, optionally suffixed by one or @@ -13745,10 +13775,9 @@ off by default. @item -masm-syntax-unified @opindex masm-syntax-unified Assume inline assembler is using unified asm syntax. The default is -currently off which implies divided syntax. Currently this option is -available only for Thumb1 and has no effect on ARM state and Thumb2. -However, this may change in future releases of GCC. Divided syntax -should be considered deprecated. +currently off which implies divided syntax. This option has no impact +on Thumb2. However, this may change in future releases of GCC. +Divided syntax should be considered deprecated. @item -mrestrict-it @opindex mrestrict-it diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 619259fc393..ee629e23381 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -1465,6 +1465,8 @@ can be described by a series of letters for each operand. The overall constraint for an operand is made from the letters for this operand from the first alternative, a comma, the letters for this operand from the second alternative, a comma, and so on until the last alternative. +All operands for a single instruction must have the same number of +alternatives. @ifset INTERNALS Here is how it is done for fullword logical-or on the 68000: @@ -1482,9 +1484,7 @@ operand 1 (meaning it must match operand 0), and @samp{dKs} for operand @samp{0} for operand 1, and @samp{dmKs} for operand 2. The @samp{=} and @samp{%} in the constraints apply to all the alternatives; their meaning is explained in the next section (@pxref{Class Preferences}). -@end ifset -@c FIXME Is this ? and ! stuff of use in asm()? If not, hide unless INTERNAL If all the operands fit any one alternative, the instruction is valid. Otherwise, for each alternative, the compiler counts how many instructions must be added to copy the operands so that that alternative applies. @@ -1521,7 +1521,6 @@ This constraint is analogous to @samp{!} but it disparages severely the alternative only if the operand with the @samp{$} needs a reload. @end table -@ifset INTERNALS When an insn pattern has multiple alternatives in its constraints, often the appearance of the assembler code is determined mostly by which alternative was matched. When this is so, the C code for writing the @@ -1529,6 +1528,21 @@ assembler code can use the variable @code{which_alternative}, which is the ordinal number of the alternative that was actually satisfied (0 for the first, 1 for the second alternative, etc.). @xref{Output Statement}. @end ifset +@ifclear INTERNALS + +So the first alternative for the 68000's logical-or could be written as +@code{"+m" (output) : "ir" (input)}. The second could be @code{"+r" +(output): "irm" (input)}. However, the fact that two memory locations +cannot be used in a single instruction prevents simply using @code{"+rm" +(output) : "irm" (input)}. Using multi-alternatives, this might be +written as @code{"+m,r" (output) : "ir,irm" (input)}. This describes +all the available alternatives to the compiler, allowing it to choose +the most efficient one for the current conditions. + +There is no way within the template to determine which alternative was +chosen. However you may be able to wrap your @code{asm} statements with +builtins such as @code{__builtin_constant_p} to achieve the desired results. +@end ifclear @ifset INTERNALS @node Class Preferences diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index f394db7d0a6..5609a98a430 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10365,6 +10365,11 @@ arithmetic operations. Pointers to a superset address space can be converted to pointers to a subset address space via explicit casts. @end deftypefn +@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID (addr_space_t @var{as}) +Define this to modify the default handling of address 0 for the +address space. Return true if 0 should be considered a valid address. +@end deftypefn + @deftypefn {Target Hook} rtx TARGET_ADDR_SPACE_CONVERT (rtx @var{op}, tree @var{from_type}, tree @var{to_type}) Define this to convert the pointer expression represented by the RTL @var{op} with type @var{from_type} that points to a named address @@ -10374,6 +10379,11 @@ guaranteed that one of the two address spaces is a subset of the other, as determined by the @code{TARGET_ADDR_SPACE_SUBSET_P} target hook. @end deftypefn +@deftypefn {Target Hook} int TARGET_ADDR_SPACE_DEBUG (addr_space_t @var{as}) +Define this to define how the address space is encoded in dwarf. +The result is the value to be used with @code{DW_AT_address_class}. +@end deftypefn + @node Misc @section Miscellaneous Parameters @cindex parameters, miscellaneous diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index d188c57b75c..96ca063a391 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7455,8 +7455,12 @@ c_register_addr_space ("__ea", ADDR_SPACE_EA); @hook TARGET_ADDR_SPACE_SUBSET_P +@hook TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID + @hook TARGET_ADDR_SPACE_CONVERT +@hook TARGET_ADDR_SPACE_DEBUG + @node Misc @section Miscellaneous Parameters @cindex parameters, miscellaneous diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 9ce3f0921fc..f1847500910 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -368,12 +368,14 @@ dump_struct_debug (tree type, enum debug_info_usage usage, #endif /* Get the number of HOST_WIDE_INTs needed to represent the precision - of the number. */ + of the number. Some constants have a large uniform precision, so + we get the precision needed for the actual value of the number. */ static unsigned int get_full_len (const wide_int &op) { - return ((op.get_precision () + HOST_BITS_PER_WIDE_INT - 1) + int prec = wi::min_precision (op, UNSIGNED); + return ((prec + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT); } @@ -5271,9 +5273,10 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label) && TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR)) { HOST_WIDE_INT maxsize; - tree innerdecl; - innerdecl - = get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize); + bool reverse; + tree innerdecl + = get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize, + &reverse); if (!DECL_P (innerdecl) || DECL_IGNORED_P (innerdecl) || TREE_STATIC (innerdecl) @@ -9010,14 +9013,14 @@ output_die (dw_die_ref die) { dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i), "%s", name); - name = NULL; + name = ""; } else for (i = 0; i < len; ++i) { dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i), "%s", name); - name = NULL; + name = ""; } } break; @@ -10896,29 +10899,39 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die) mod_type_die = d; } } - else if (code == POINTER_TYPE) + else if (code == POINTER_TYPE || code == REFERENCE_TYPE) { - mod_type_die = new_die (DW_TAG_pointer_type, mod_scope, type); - add_AT_unsigned (mod_type_die, DW_AT_byte_size, - simple_type_size_in_bits (type) / BITS_PER_UNIT); - item_type = TREE_TYPE (type); - if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (item_type))) - add_AT_unsigned (mod_type_die, DW_AT_address_class, - TYPE_ADDR_SPACE (item_type)); - } - else if (code == REFERENCE_TYPE) - { - if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4) - mod_type_die = new_die (DW_TAG_rvalue_reference_type, mod_scope, - type); - else - mod_type_die = new_die (DW_TAG_reference_type, mod_scope, type); + dwarf_tag tag = DW_TAG_pointer_type; + if (code == REFERENCE_TYPE) + { + if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4) + tag = DW_TAG_rvalue_reference_type; + else + tag = DW_TAG_reference_type; + } + mod_type_die = new_die (tag, mod_scope, type); + add_AT_unsigned (mod_type_die, DW_AT_byte_size, simple_type_size_in_bits (type) / BITS_PER_UNIT); item_type = TREE_TYPE (type); - if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (item_type))) - add_AT_unsigned (mod_type_die, DW_AT_address_class, - TYPE_ADDR_SPACE (item_type)); + + addr_space_t as = TYPE_ADDR_SPACE (item_type); + if (!ADDR_SPACE_GENERIC_P (as)) + { + int action = targetm.addr_space.debug (as); + if (action >= 0) + { + /* Positive values indicate an address_class. */ + add_AT_unsigned (mod_type_die, DW_AT_address_class, action); + } + else + { + /* Negative values indicate an (inverted) segment base reg. */ + dw_loc_descr_ref d + = one_reg_loc_descriptor (~action, VAR_INIT_STATUS_INITIALIZED); + add_AT_loc (mod_type_die, DW_AT_segment, d); + } + } } else if (code == INTEGER_TYPE && TREE_TYPE (type) != NULL_TREE @@ -14461,12 +14474,12 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev, tree obj, offset; HOST_WIDE_INT bitsize, bitpos, bytepos; machine_mode mode; - int unsignedp, volatilep = 0; + int unsignedp, reversep, volatilep = 0; dw_loc_list_ref list_ret = NULL, list_ret1 = NULL; obj = get_inner_reference (TREE_OPERAND (loc, 0), &bitsize, &bitpos, &offset, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &reversep, &volatilep, false); STRIP_NOPS (obj); if (bitpos % BITS_PER_UNIT) { @@ -14795,10 +14808,10 @@ loc_list_from_tree (tree loc, int want_address, tree obj, offset; HOST_WIDE_INT bitsize, bitpos, bytepos; machine_mode mode; - int unsignedp, volatilep = 0; + int unsignedp, reversep, volatilep = 0; obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &reversep, &volatilep, false); gcc_assert (obj != loc); @@ -15593,8 +15606,13 @@ add_const_value_attribute (dw_die_ref die, rtx rtl) return true; case CONST_WIDE_INT: - add_AT_wide (die, DW_AT_const_value, - std::make_pair (rtl, GET_MODE (rtl))); + { + wide_int w1 = std::make_pair (rtl, MAX_MODE_INT); + unsigned int prec = MIN (wi::min_precision (w1, UNSIGNED), + (unsigned int)CONST_WIDE_INT_NUNITS (rtl) * HOST_BITS_PER_WIDE_INT); + wide_int w = wi::zext (w1, prec); + add_AT_wide (die, DW_AT_const_value, w); + } return true; case CONST_DOUBLE: @@ -16095,7 +16113,7 @@ fortran_common (tree decl, HOST_WIDE_INT *value) machine_mode mode; HOST_WIDE_INT bitsize, bitpos; tree offset; - int unsignedp, volatilep = 0; + int unsignedp, reversep, volatilep = 0; /* If the decl isn't a VAR_DECL, or if it isn't static, or if it does not have a value (the offset into the common area), or if it @@ -16111,8 +16129,8 @@ fortran_common (tree decl, HOST_WIDE_INT *value) if (TREE_CODE (val_expr) != COMPONENT_REF) return NULL_TREE; - cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, true); + cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset, &mode, + &unsignedp, &reversep, &volatilep, true); if (cvar == NULL_TREE || TREE_CODE (cvar) != VAR_DECL diff --git a/gcc/expmed.c b/gcc/expmed.c index a06576c4fdd..97a15130e4f 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -48,24 +48,24 @@ static void store_fixed_bit_field (rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, - rtx); + rtx, bool); static void store_fixed_bit_field_1 (rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, - rtx); + rtx, bool); static void store_split_bit_field (rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, - rtx); + rtx, bool); static rtx extract_fixed_bit_field (machine_mode, rtx, unsigned HOST_WIDE_INT, - unsigned HOST_WIDE_INT, rtx, int); + unsigned HOST_WIDE_INT, rtx, int, bool); static rtx extract_fixed_bit_field_1 (machine_mode, rtx, unsigned HOST_WIDE_INT, - unsigned HOST_WIDE_INT, rtx, int); + unsigned HOST_WIDE_INT, rtx, int, bool); static rtx lshift_value (machine_mode, unsigned HOST_WIDE_INT, int); static rtx extract_split_bit_field (rtx, unsigned HOST_WIDE_INT, - unsigned HOST_WIDE_INT, int); + unsigned HOST_WIDE_INT, int, bool); static void do_cmp_and_jump (rtx, rtx, enum rtx_code, machine_mode, rtx_code_label *); static rtx expand_smod_pow2 (machine_mode, rtx, HOST_WIDE_INT); static rtx expand_sdiv_pow2 (machine_mode, rtx, HOST_WIDE_INT); @@ -323,6 +323,94 @@ negate_rtx (machine_mode mode, rtx x) return result; } +/* Whether reverse storage order is supported on the target. */ +static int reverse_storage_order_supported = -1; + +/* Check whether reverse storage order is supported on the target. */ + +static void +check_reverse_storage_order_support (void) +{ + if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN) + { + reverse_storage_order_supported = 0; + sorry ("reverse scalar storage order"); + } + else + reverse_storage_order_supported = 1; +} + +/* Whether reverse FP storage order is supported on the target. */ +static int reverse_float_storage_order_supported = -1; + +/* Check whether reverse FP storage order is supported on the target. */ + +static void +check_reverse_float_storage_order_support (void) +{ + if (FLOAT_WORDS_BIG_ENDIAN != WORDS_BIG_ENDIAN) + { + reverse_float_storage_order_supported = 0; + sorry ("reverse floating-point scalar storage order"); + } + else + reverse_float_storage_order_supported = 1; +} + +/* Return an rtx representing value of X with reverse storage order. + MODE is the intended mode of the result, + useful if X is a CONST_INT. */ + +rtx +flip_storage_order (enum machine_mode mode, rtx x) +{ + enum machine_mode int_mode; + rtx result; + + if (mode == QImode) + return x; + + if (COMPLEX_MODE_P (mode)) + { + rtx real = read_complex_part (x, false); + rtx imag = read_complex_part (x, true); + + real = flip_storage_order (GET_MODE_INNER (mode), real); + imag = flip_storage_order (GET_MODE_INNER (mode), imag); + + return gen_rtx_CONCAT (mode, real, imag); + } + + if (__builtin_expect (reverse_storage_order_supported < 0, 0)) + check_reverse_storage_order_support (); + + if (SCALAR_INT_MODE_P (mode)) + int_mode = mode; + else + { + if (FLOAT_MODE_P (mode) + && __builtin_expect (reverse_float_storage_order_supported < 0, 0)) + check_reverse_float_storage_order_support (); + + int_mode = mode_for_size (GET_MODE_PRECISION (mode), MODE_INT, 0); + if (int_mode == BLKmode) + { + sorry ("reverse storage order for %smode", GET_MODE_NAME (mode)); + return x; + } + x = gen_lowpart (int_mode, x); + } + + result = simplify_unary_operation (BSWAP, int_mode, x, int_mode); + if (result == 0) + result = expand_unop (int_mode, bswap_optab, x, NULL_RTX, 1); + + if (int_mode != mode) + result = gen_lowpart (mode, result); + + return result; +} + /* Adjust bitfield memory MEM so that it points to the first unit of mode MODE that contains a bitfield of size BITSIZE at bit position BITNUM. If MODE is BLKmode, return a reference to every byte in the bitfield. @@ -626,7 +714,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT bitregion_start, unsigned HOST_WIDE_INT bitregion_end, machine_mode fieldmode, - rtx value, bool fallback_p) + rtx value, bool reverse, bool fallback_p) { rtx op0 = str_rtx; rtx orig_value; @@ -642,7 +730,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, int outer_mode_size = GET_MODE_SIZE (GET_MODE (op0)); int byte_offset = 0; - /* Paradoxical subregs need special handling on big endian machines. */ + /* Paradoxical subregs need special handling on big-endian machines. */ if (SUBREG_BYTE (op0) == 0 && inner_mode_size < outer_mode_size) { int difference = inner_mode_size - outer_mode_size; @@ -704,6 +792,8 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, sub = simplify_gen_subreg (GET_MODE (op0), value, fieldmode, 0); if (sub) { + if (reverse) + sub = flip_storage_order (GET_MODE (op0), sub); emit_move_insn (op0, sub); return true; } @@ -714,6 +804,8 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, bitnum / BITS_PER_UNIT); if (sub) { + if (reverse) + value = flip_storage_order (fieldmode, value); emit_move_insn (sub, value); return true; } @@ -726,6 +818,8 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (simple_mem_bitfield_p (op0, bitsize, bitnum, fieldmode)) { op0 = adjust_bitfield_address (op0, fieldmode, bitnum / BITS_PER_UNIT); + if (reverse) + value = flip_storage_order (fieldmode, value); emit_move_insn (op0, value); return true; } @@ -752,6 +846,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, can be done with a movstrict instruction. */ if (!MEM_P (op0) + && !reverse && lowpart_bit_field_p (bitnum, bitsize, GET_MODE (op0)) && bitsize == GET_MODE_BITSIZE (fieldmode) && optab_handler (movstrict_optab, fieldmode) != CODE_FOR_nothing) @@ -795,7 +890,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, be less than full. However, only do that if the value is not BLKmode. */ - unsigned int backwards = WORDS_BIG_ENDIAN && fieldmode != BLKmode; + const bool backwards = WORDS_BIG_ENDIAN && fieldmode != BLKmode; unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD; unsigned int i; rtx_insn *last; @@ -818,7 +913,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ? GET_MODE_SIZE (fieldmode) / UNITS_PER_WORD - i - 1 : i); - unsigned int bit_offset = (backwards + unsigned int bit_offset = (backwards ^ reverse ? MAX ((int) bitsize - ((int) i + 1) * BITS_PER_WORD, 0) @@ -828,7 +923,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, MIN (BITS_PER_WORD, bitsize - i * BITS_PER_WORD); /* If the remaining chunk doesn't have full wordsize we have - to make sure that for big endian machines the higher order + to make sure that for big-endian machines the higher order bits are used. */ if (new_bitsize < BITS_PER_WORD && BYTES_BIG_ENDIAN && !backwards) value_word = simplify_expand_binop (word_mode, lshr_optab, @@ -842,7 +937,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, bitnum + bit_offset, bitregion_start, bitregion_end, word_mode, - value_word, fallback_p)) + value_word, reverse, fallback_p)) { delete_insns_since (last); return false; @@ -878,7 +973,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, return false; store_split_bit_field (op0, bitsize, bitnum, bitregion_start, - bitregion_end, value); + bitregion_end, value, reverse); return true; } } @@ -889,6 +984,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, extraction_insn insv; if (!MEM_P (op0) + && !reverse && get_best_reg_extraction_insn (&insv, EP_insv, GET_MODE_BITSIZE (GET_MODE (op0)), fieldmode) @@ -897,7 +993,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, /* If OP0 is a memory, try copying it to a register and seeing if a cheap register alternative is available. */ - if (MEM_P (op0)) + if (MEM_P (op0) && !reverse) { if (get_best_mem_extraction_insn (&insv, EP_insv, bitsize, bitnum, fieldmode) @@ -917,7 +1013,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, rtx tempreg = copy_to_reg (xop0); if (store_bit_field_1 (tempreg, bitsize, bitpos, bitregion_start, bitregion_end, - fieldmode, orig_value, false)) + fieldmode, orig_value, reverse, false)) { emit_move_insn (xop0, tempreg); return true; @@ -930,7 +1026,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, return false; store_fixed_bit_field (op0, bitsize, bitnum, bitregion_start, - bitregion_end, value); + bitregion_end, value, reverse); return true; } @@ -943,7 +1039,9 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, These two fields are 0, if the C++ memory model does not apply, or we are not interested in keeping track of bitfield regions. - FIELDMODE is the machine-mode of the FIELD_DECL node for this field. */ + FIELDMODE is the machine-mode of the FIELD_DECL node for this field. + + If REVERSE is true, the store is to be done in reverse order. */ void store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, @@ -951,7 +1049,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT bitregion_start, unsigned HOST_WIDE_INT bitregion_end, machine_mode fieldmode, - rtx value) + rtx value, bool reverse) { /* Handle -fstrict-volatile-bitfields in the cases where it applies. */ if (strict_volatile_bitfield_p (str_rtx, bitsize, bitnum, fieldmode, @@ -965,6 +1063,8 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, { str_rtx = adjust_bitfield_address (str_rtx, fieldmode, bitnum / BITS_PER_UNIT); + if (reverse) + value = flip_storage_order (fieldmode, value); gcc_assert (bitnum % BITS_PER_UNIT == 0); emit_move_insn (str_rtx, value); } @@ -977,7 +1077,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, gcc_assert (bitnum + bitsize <= GET_MODE_BITSIZE (fieldmode)); temp = copy_to_reg (str_rtx); if (!store_bit_field_1 (temp, bitsize, bitnum, 0, 0, - fieldmode, value, true)) + fieldmode, value, reverse, true)) gcc_unreachable (); emit_move_insn (str_rtx, temp); @@ -1010,19 +1110,21 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (!store_bit_field_1 (str_rtx, bitsize, bitnum, bitregion_start, bitregion_end, - fieldmode, value, true)) + fieldmode, value, reverse, true)) gcc_unreachable (); } /* Use shifts and boolean operations to store VALUE into a bit field of - width BITSIZE in OP0, starting at bit BITNUM. */ + width BITSIZE in OP0, starting at bit BITNUM. + + If REVERSE is true, the store is to be done in reverse order. */ static void store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT bitnum, unsigned HOST_WIDE_INT bitregion_start, unsigned HOST_WIDE_INT bitregion_end, - rtx value) + rtx value, bool reverse) { /* There is a case not handled here: a structure with a known alignment of just a halfword @@ -1045,14 +1147,14 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, /* The only way this should occur is if the field spans word boundaries. */ store_split_bit_field (op0, bitsize, bitnum, bitregion_start, - bitregion_end, value); + bitregion_end, value, reverse); return; } op0 = narrow_bit_field_mem (op0, mode, bitsize, bitnum, &bitnum); } - store_fixed_bit_field_1 (op0, bitsize, bitnum, value); + store_fixed_bit_field_1 (op0, bitsize, bitnum, value, reverse); } /* Helper function for store_fixed_bit_field, stores @@ -1061,7 +1163,7 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, static void store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT bitnum, - rtx value) + rtx value, bool reverse) { machine_mode mode; rtx temp; @@ -1074,7 +1176,7 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize, /* Note that bitsize + bitnum can be greater than GET_MODE_BITSIZE (mode) for invalid input, such as f5 from gcc.dg/pr48335-2.c. */ - if (BYTES_BIG_ENDIAN) + if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN) /* BITNUM is the distance between our msb and that of the containing datum. Convert it to the distance from the lsb. */ @@ -1120,6 +1222,9 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize, bitnum, NULL_RTX, 1); } + if (reverse) + value = flip_storage_order (mode, value); + /* Now clear the chosen bits in OP0, except that if VALUE is -1 we need not bother. */ /* We keep the intermediates in registers to allow CSE to combine @@ -1129,8 +1234,10 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize, if (! all_one) { - temp = expand_binop (mode, and_optab, temp, - mask_rtx (mode, bitnum, bitsize, 1), + rtx mask = mask_rtx (mode, bitnum, bitsize, 1); + if (reverse) + mask = flip_storage_order (mode, mask); + temp = expand_binop (mode, and_optab, temp, mask, NULL_RTX, 1, OPTAB_LIB_WIDEN); temp = force_reg (mode, temp); } @@ -1158,6 +1265,8 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize, (within the word). VALUE is the value to store. + If REVERSE is true, the store is to be done in reverse order. + This does not yet handle fields wider than BITS_PER_WORD. */ static void @@ -1165,10 +1274,9 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT bitpos, unsigned HOST_WIDE_INT bitregion_start, unsigned HOST_WIDE_INT bitregion_end, - rtx value) + rtx value, bool reverse) { - unsigned int unit; - unsigned int bitsdone = 0; + unsigned int unit, total_bits, bitsdone = 0; /* Make sure UNIT isn't larger than BITS_PER_WORD, we can only handle that much at a time. */ @@ -1199,12 +1307,14 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, : word_mode, value)); } + total_bits = GET_MODE_BITSIZE (GET_MODE (value)); + while (bitsdone < bitsize) { unsigned HOST_WIDE_INT thissize; - rtx part, word; unsigned HOST_WIDE_INT thispos; unsigned HOST_WIDE_INT offset; + rtx part, word; offset = (bitpos + bitsdone) / unit; thispos = (bitpos + bitsdone) % unit; @@ -1229,13 +1339,18 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, thissize = MIN (bitsize - bitsdone, BITS_PER_WORD); thissize = MIN (thissize, unit - thispos); - if (BYTES_BIG_ENDIAN) + if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN) { /* Fetch successively less significant portions. */ if (CONST_INT_P (value)) part = GEN_INT (((unsigned HOST_WIDE_INT) (INTVAL (value)) >> (bitsize - bitsdone - thissize)) & (((HOST_WIDE_INT) 1 << thissize) - 1)); + /* Likewise, but the source is little-endian. */ + else if (reverse) + part = extract_fixed_bit_field (word_mode, value, thissize, + bitsize - bitsdone - thissize, + NULL_RTX, 1, false); else { int total_bits = GET_MODE_BITSIZE (GET_MODE (value)); @@ -1244,7 +1359,7 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, endianness compensation) to fetch the piece we want. */ part = extract_fixed_bit_field (word_mode, value, thissize, total_bits - bitsize + bitsdone, - NULL_RTX, 1); + NULL_RTX, 1, false); } } else @@ -1254,9 +1369,14 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, part = GEN_INT (((unsigned HOST_WIDE_INT) (INTVAL (value)) >> bitsdone) & (((HOST_WIDE_INT) 1 << thissize) - 1)); + /* Likewise, but the source is big-endian. */ + else if (reverse) + part = extract_fixed_bit_field (word_mode, value, thissize, + total_bits - bitsdone - thissize, + NULL_RTX, 1, false); else part = extract_fixed_bit_field (word_mode, value, thissize, - bitsdone, NULL_RTX, 1); + bitsdone, NULL_RTX, 1, false); } /* If OP0 is a register, then handle OFFSET here. @@ -1294,7 +1414,8 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, it is just an out-of-bounds access. Ignore it. */ if (word != const0_rtx) store_fixed_bit_field (word, thissize, offset * unit + thispos, - bitregion_start, bitregion_end, part); + bitregion_start, bitregion_end, part, + reverse); bitsdone += thissize; } } @@ -1419,7 +1540,7 @@ static rtx extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target, machine_mode mode, machine_mode tmode, - bool fallback_p) + bool reverse, bool fallback_p) { rtx op0 = str_rtx; machine_mode int_mode; @@ -1445,6 +1566,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, && bitnum == 0 && bitsize == GET_MODE_BITSIZE (GET_MODE (op0))) { + if (reverse) + op0 = flip_storage_order (mode, op0); /* We're trying to extract a full register from itself. */ return op0; } @@ -1561,6 +1684,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, as the least significant bit of the value is the least significant bit of either OP0 or a word of OP0. */ if (!MEM_P (op0) + && !reverse && lowpart_bit_field_p (bitnum, bitsize, GET_MODE (op0)) && bitsize == GET_MODE_BITSIZE (mode1) && TRULY_NOOP_TRUNCATION_MODES_P (mode1, GET_MODE (op0))) @@ -1576,6 +1700,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (simple_mem_bitfield_p (op0, bitsize, bitnum, mode1)) { op0 = adjust_bitfield_address (op0, mode1, bitnum / BITS_PER_UNIT); + if (reverse) + op0 = flip_storage_order (mode1, op0); return convert_extracted_bit_field (op0, mode, tmode, unsignedp); } @@ -1588,7 +1714,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, This is because the most significant word is the one which may be less than full. */ - unsigned int backwards = WORDS_BIG_ENDIAN; + const bool backwards = WORDS_BIG_ENDIAN; unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD; unsigned int i; rtx_insn *last; @@ -1615,7 +1741,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ? GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD - i - 1 : i); /* Offset from start of field in OP0. */ - unsigned int bit_offset = (backwards + unsigned int bit_offset = (backwards ^ reverse ? MAX ((int) bitsize - ((int) i + 1) * BITS_PER_WORD, 0) @@ -1625,7 +1751,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, = extract_bit_field_1 (op0, MIN (BITS_PER_WORD, bitsize - i * BITS_PER_WORD), bitnum + bit_offset, 1, target_part, - mode, word_mode, fallback_p); + mode, word_mode, reverse, fallback_p); gcc_assert (target_part); if (!result_part) @@ -1675,7 +1801,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, { if (!fallback_p) return NULL_RTX; - target = extract_split_bit_field (op0, bitsize, bitnum, unsignedp); + target = extract_split_bit_field (op0, bitsize, bitnum, unsignedp, + reverse); return convert_extracted_bit_field (target, mode, tmode, unsignedp); } } @@ -1685,6 +1812,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, enum extraction_pattern pattern = unsignedp ? EP_extzv : EP_extv; extraction_insn extv; if (!MEM_P (op0) + && !reverse /* ??? We could limit the structure size to the part of OP0 that contains the field, with appropriate checks for endianness and TRULY_NOOP_TRUNCATION. */ @@ -1701,7 +1829,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, /* If OP0 is a memory, try copying it to a register and seeing if a cheap register alternative is available. */ - if (MEM_P (op0)) + if (MEM_P (op0) & !reverse) { if (get_best_mem_extraction_insn (&extv, pattern, bitsize, bitnum, tmode)) @@ -1726,7 +1854,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, xop0 = copy_to_reg (xop0); rtx result = extract_bit_field_1 (xop0, bitsize, bitpos, unsignedp, target, - mode, tmode, false); + mode, tmode, reverse, false); if (result) return result; delete_insns_since (last); @@ -1744,9 +1872,21 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, /* Should probably push op0 out to memory and then do a load. */ gcc_assert (int_mode != BLKmode); - target = extract_fixed_bit_field (int_mode, op0, bitsize, bitnum, - target, unsignedp); - return convert_extracted_bit_field (target, mode, tmode, unsignedp); + target = extract_fixed_bit_field (int_mode, op0, bitsize, bitnum, target, + unsignedp, reverse); + + /* Complex values must be reversed piecewise, so we need to undo the global + reversal, convert to the complex mode and reverse again. */ + if (reverse && COMPLEX_MODE_P (tmode)) + { + target = flip_storage_order (int_mode, target); + target = convert_extracted_bit_field (target, mode, tmode, unsignedp); + target = flip_storage_order (tmode, target); + } + else + target = convert_extracted_bit_field (target, mode, tmode, unsignedp); + + return target; } /* Generate code to extract a byte-field from STR_RTX @@ -1760,6 +1900,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, TMODE is the mode the caller would like the value to have; but the value may be returned with type MODE instead. + If REVERSE is true, the extraction is to be done in reverse order. + If a TARGET is specified and we can store in it at no extra cost, we do so, and return TARGET. Otherwise, we return a REG of mode TMODE or MODE, with TMODE preferred @@ -1768,7 +1910,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, rtx extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target, - machine_mode mode, machine_mode tmode) + machine_mode mode, machine_mode tmode, bool reverse) { machine_mode mode1; @@ -1790,6 +1932,8 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, { rtx result = adjust_bitfield_address (str_rtx, mode1, bitnum / BITS_PER_UNIT); + if (reverse) + result = flip_storage_order (mode1, result); gcc_assert (bitnum % BITS_PER_UNIT == 0); return convert_extracted_bit_field (result, mode, tmode, unsignedp); } @@ -1801,13 +1945,15 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, } return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp, - target, mode, tmode, true); + target, mode, tmode, reverse, true); } /* Use shifts and boolean operations to extract a field of BITSIZE bits from bit BITNUM of OP0. UNSIGNEDP is nonzero for an unsigned bit field (don't sign-extend value). + If REVERSE is true, the extraction is to be done in reverse order. + If TARGET is nonzero, attempts to store the value there and return TARGET, but this is not guaranteed. If TARGET is not used, create a pseudo-reg of mode TMODE for the value. */ @@ -1816,7 +1962,7 @@ static rtx extract_fixed_bit_field (machine_mode tmode, rtx op0, unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT bitnum, rtx target, - int unsignedp) + int unsignedp, bool reverse) { if (MEM_P (op0)) { @@ -1827,13 +1973,14 @@ extract_fixed_bit_field (machine_mode tmode, rtx op0, if (mode == VOIDmode) /* The only way this should occur is if the field spans word boundaries. */ - return extract_split_bit_field (op0, bitsize, bitnum, unsignedp); + return extract_split_bit_field (op0, bitsize, bitnum, unsignedp, + reverse); op0 = narrow_bit_field_mem (op0, mode, bitsize, bitnum, &bitnum); } return extract_fixed_bit_field_1 (tmode, op0, bitsize, bitnum, - target, unsignedp); + target, unsignedp, reverse); } /* Helper function for extract_fixed_bit_field, extracts @@ -1843,7 +1990,7 @@ static rtx extract_fixed_bit_field_1 (machine_mode tmode, rtx op0, unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT bitnum, rtx target, - int unsignedp) + int unsignedp, bool reverse) { machine_mode mode = GET_MODE (op0); gcc_assert (SCALAR_INT_MODE_P (mode)); @@ -1852,13 +1999,15 @@ extract_fixed_bit_field_1 (machine_mode tmode, rtx op0, for invalid input, such as extract equivalent of f5 from gcc.dg/pr48335-2.c. */ - if (BYTES_BIG_ENDIAN) + if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN) /* BITNUM is the distance between our msb and that of OP0. Convert it to the distance from the lsb. */ bitnum = GET_MODE_BITSIZE (mode) - bitsize - bitnum; /* Now BITNUM is always the distance between the field's lsb and that of OP0. We have reduced the big-endian case to the little-endian case. */ + if (reverse) + op0 = flip_storage_order (mode, op0); if (unsignedp) { @@ -1930,11 +2079,14 @@ lshift_value (machine_mode mode, unsigned HOST_WIDE_INT value, OP0 is the REG, SUBREG or MEM rtx for the first of the two words. BITSIZE is the field width; BITPOS, position of its first bit, in the word. - UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend. */ + UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend. + + If REVERSE is true, the extraction is to be done in reverse order. */ static rtx extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, - unsigned HOST_WIDE_INT bitpos, int unsignedp) + unsigned HOST_WIDE_INT bitpos, int unsignedp, + bool reverse) { unsigned int unit; unsigned int bitsdone = 0; @@ -1989,11 +2141,11 @@ extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, whose meaning is determined by BYTES_PER_UNIT. OFFSET is in UNITs, and UNIT is in bits. */ part = extract_fixed_bit_field (word_mode, word, thissize, - offset * unit + thispos, 0, 1); + offset * unit + thispos, 0, 1, reverse); bitsdone += thissize; /* Shift this part into place for the result. */ - if (BYTES_BIG_ENDIAN) + if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN) { if (bitsize != bitsdone) part = expand_shift (LSHIFT_EXPR, word_mode, part, diff --git a/gcc/expmed.h b/gcc/expmed.h index 1378192703b..0a7afd2c3cf 100644 --- a/gcc/expmed.h +++ b/gcc/expmed.h @@ -676,6 +676,10 @@ extern rtx emit_cstore (rtx target, enum insn_code icode, enum rtx_code code, May emit insns. */ extern rtx negate_rtx (machine_mode, rtx); +/* Arguments MODE, RTX: return an rtx for the flipping of that value. + May emit insns. */ +extern rtx flip_storage_order (enum machine_mode, rtx); + /* Expand a logical AND operation. */ extern rtx expand_and (machine_mode, rtx, rtx, rtx); @@ -707,10 +711,10 @@ extern void store_bit_field (rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, - machine_mode, rtx); + machine_mode, rtx, bool); extern rtx extract_bit_field (rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, int, rtx, - machine_mode, machine_mode); + machine_mode, machine_mode, bool); extern rtx extract_low_bits (machine_mode, machine_mode, rtx); extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int); extern rtx expand_mult_highpart_adjust (machine_mode, rtx, rtx, rtx, rtx, int); diff --git a/gcc/expr.c b/gcc/expr.c index 11c25315238..050642daa4f 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -121,11 +121,11 @@ static rtx_insn *compress_float_constant (rtx, rtx); static rtx get_subtarget (rtx); static void store_constructor_field (rtx, unsigned HOST_WIDE_INT, HOST_WIDE_INT, machine_mode, - tree, int, alias_set_type); -static void store_constructor (tree, rtx, int, HOST_WIDE_INT); + tree, int, alias_set_type, bool); +static void store_constructor (tree, rtx, int, HOST_WIDE_INT, bool); static rtx store_field (rtx, HOST_WIDE_INT, HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, - machine_mode, tree, alias_set_type, bool); + machine_mode, tree, alias_set_type, bool, bool); static unsigned HOST_WIDE_INT highest_pow2_factor_for_target (const_tree, const_tree); @@ -1678,7 +1678,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize) && (!REG_P (tmps[i]) || GET_MODE (tmps[i]) != mode)) tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT, (bytepos % slen0) * BITS_PER_UNIT, - 1, NULL_RTX, mode, mode); + 1, NULL_RTX, mode, mode, false); } else { @@ -1688,7 +1688,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize) mem = assign_stack_temp (GET_MODE (src), slen); emit_move_insn (mem, src); tmps[i] = extract_bit_field (mem, bytelen * BITS_PER_UNIT, - 0, 1, NULL_RTX, mode, mode); + 0, 1, NULL_RTX, mode, mode, false); } } /* FIXME: A SIMD parallel will eventually lead to a subreg of a @@ -1731,7 +1731,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize) else tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT, 1, NULL_RTX, - mode, mode); + mode, mode, false); if (shift) tmps[i] = expand_shift (LSHIFT_EXPR, mode, tmps[i], @@ -2039,7 +2039,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize) store_bit_field (dest, adj_bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT, bytepos * BITS_PER_UNIT, ssize * BITS_PER_UNIT - 1, - VOIDmode, tmps[i]); + VOIDmode, tmps[i], false); } /* Optimize the access just a bit. */ @@ -2052,7 +2052,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize) else store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT, - 0, 0, mode, tmps[i]); + 0, 0, mode, tmps[i], false); } /* Copy from the pseudo into the (probable) hard reg. */ @@ -2182,7 +2182,9 @@ copy_blkmode_from_reg (rtx target, rtx srcreg, tree type) store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, 0, 0, copy_mode, extract_bit_field (src, bitsize, xbitpos % BITS_PER_WORD, 1, - NULL_RTX, copy_mode, copy_mode)); + NULL_RTX, copy_mode, copy_mode, + false), + false); } } @@ -2259,7 +2261,9 @@ copy_blkmode_to_reg (machine_mode mode, tree src) 0, 0, word_mode, extract_bit_field (src_word, bitsize, bitpos % BITS_PER_WORD, 1, - NULL_RTX, word_mode, word_mode)); + NULL_RTX, word_mode, word_mode, + false), + false); } if (mode == BLKmode) @@ -3004,7 +3008,8 @@ write_complex_part (rtx cplx, rtx val, bool imag_p) gcc_assert (MEM_P (cplx) && ibitsize < BITS_PER_WORD); } - store_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0, 0, 0, imode, val); + store_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0, 0, 0, imode, val, + false); } /* Extract one of the components of the complex value CPLX. Extract the @@ -3067,7 +3072,7 @@ read_complex_part (rtx cplx, bool imag_p) } return extract_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0, - true, NULL_RTX, imode, imode); + true, NULL_RTX, imode, imode, false); } /* A subroutine of emit_move_insn_1. Yet another lowpart generator. @@ -4457,7 +4462,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT bitregion_start, unsigned HOST_WIDE_INT bitregion_end, machine_mode mode1, rtx str_rtx, - tree to, tree src) + tree to, tree src, bool reverse) { machine_mode str_mode = GET_MODE (str_rtx); unsigned int str_bitsize = GET_MODE_BITSIZE (str_mode); @@ -4530,6 +4535,8 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize, } else if (!REG_P (str_rtx) && GET_CODE (str_rtx) != SUBREG) return false; + else + gcc_assert (!reverse); /* If the bit field covers the whole REG/MEM, store_field will likely generate better code. */ @@ -4540,7 +4547,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize, if (bitpos + bitsize > str_bitsize) return false; - if (BYTES_BIG_ENDIAN) + if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN) bitpos = str_bitsize - bitpos - bitsize; switch (code) @@ -4553,7 +4560,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize, We might win by one instruction for the other bitfields too if insv/extv instructions aren't used, so that can be added later. */ - if (bitpos + bitsize != str_bitsize + if ((reverse || bitpos + bitsize != str_bitsize) && (bitsize != 1 || TREE_CODE (op1) != INTEGER_CST)) break; @@ -4571,13 +4578,17 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize, set_mem_expr (str_rtx, 0); } - binop = code == PLUS_EXPR ? add_optab : sub_optab; - if (bitsize == 1 && bitpos + bitsize != str_bitsize) + if (bitsize == 1 && (reverse || bitpos + bitsize != str_bitsize)) { value = expand_and (str_mode, value, const1_rtx, NULL); binop = xor_optab; } + else + binop = code == PLUS_EXPR ? add_optab : sub_optab; + value = expand_shift (LSHIFT_EXPR, str_mode, value, bitpos, NULL_RTX, 1); + if (reverse) + value = flip_storage_order (str_mode, value); result = expand_binop (str_mode, binop, str_rtx, value, str_rtx, 1, OPTAB_WIDEN); if (result != str_rtx) @@ -4610,6 +4621,8 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize, value = expand_and (str_mode, value, mask, NULL_RTX); } value = expand_shift (LSHIFT_EXPR, str_mode, value, bitpos, NULL_RTX, 1); + if (reverse) + value = flip_storage_order (str_mode, value); result = expand_binop (str_mode, binop, str_rtx, value, str_rtx, 1, OPTAB_WIDEN); if (result != str_rtx) @@ -4664,10 +4677,10 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart, machine_mode rmode; HOST_WIDE_INT rbitsize, rbitpos; tree roffset; - int unsignedp; - int volatilep = 0; + int unsignedp, reversep, volatilep = 0; get_inner_reference (TREE_OPERAND (exp, 0), &rbitsize, &rbitpos, - &roffset, &rmode, &unsignedp, &volatilep, false); + &roffset, &rmode, &unsignedp, &reversep, + &volatilep, false); if ((rbitpos % BITS_PER_UNIT) != 0) { *bitstart = *bitend = 0; @@ -4783,6 +4796,8 @@ expand_assignment (tree to, tree from, bool nontemporal) reg = expand_expr (from, NULL_RTX, VOIDmode, EXPAND_NORMAL); reg = force_not_mem (reg); mem = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE); + if (TREE_CODE (to) == MEM_REF && REF_REVERSE_STORAGE_ORDER (to)) + reg = flip_storage_order (mode, reg); if (icode != CODE_FOR_nothing) { @@ -4795,7 +4810,8 @@ expand_assignment (tree to, tree from, bool nontemporal) expand_insn (icode, 2, ops); } else - store_bit_field (mem, GET_MODE_BITSIZE (mode), 0, 0, 0, mode, reg); + store_bit_field (mem, GET_MODE_BITSIZE (mode), 0, 0, 0, mode, reg, + false); return; } @@ -4806,7 +4822,8 @@ expand_assignment (tree to, tree from, bool nontemporal) problem. Same for (partially) storing into a non-memory object. */ if (handled_component_p (to) || (TREE_CODE (to) == MEM_REF - && mem_ref_refers_to_non_mem_p (to)) + && (REF_REVERSE_STORAGE_ORDER (to) + || mem_ref_refers_to_non_mem_p (to))) || TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE) { machine_mode mode1; @@ -4814,13 +4831,12 @@ expand_assignment (tree to, tree from, bool nontemporal) unsigned HOST_WIDE_INT bitregion_start = 0; unsigned HOST_WIDE_INT bitregion_end = 0; tree offset; - int unsignedp; - int volatilep = 0; + int unsignedp, reversep, volatilep = 0; tree tem; push_temp_slots (); tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1, - &unsignedp, &volatilep, true); + &unsignedp, &reversep, &volatilep, true); /* Make sure bitpos is not negative, it can wreak havoc later. */ if (bitpos < 0) @@ -4939,22 +4955,22 @@ expand_assignment (tree to, tree from, bool nontemporal) if (COMPLEX_MODE_P (TYPE_MODE (TREE_TYPE (from))) && bitpos == 0 && bitsize == mode_bitsize) - result = store_expr (from, to_rtx, false, nontemporal); + result = store_expr (from, to_rtx, false, nontemporal, reversep); else if (bitsize == mode_bitsize / 2 && (bitpos == 0 || bitpos == mode_bitsize / 2)) result = store_expr (from, XEXP (to_rtx, bitpos != 0), false, - nontemporal); + nontemporal, reversep); else if (bitpos + bitsize <= mode_bitsize / 2) result = store_field (XEXP (to_rtx, 0), bitsize, bitpos, bitregion_start, bitregion_end, - mode1, from, - get_alias_set (to), nontemporal); + mode1, from, get_alias_set (to), + nontemporal, reversep); else if (bitpos >= mode_bitsize / 2) result = store_field (XEXP (to_rtx, 1), bitsize, bitpos - mode_bitsize / 2, bitregion_start, bitregion_end, - mode1, from, - get_alias_set (to), nontemporal); + mode1, from, get_alias_set (to), + nontemporal, reversep); else if (bitpos == 0 && bitsize == mode_bitsize) { rtx from_rtx; @@ -4974,8 +4990,8 @@ expand_assignment (tree to, tree from, bool nontemporal) write_complex_part (temp, XEXP (to_rtx, 1), true); result = store_field (temp, bitsize, bitpos, bitregion_start, bitregion_end, - mode1, from, - get_alias_set (to), nontemporal); + mode1, from, get_alias_set (to), + nontemporal, reversep); emit_move_insn (XEXP (to_rtx, 0), read_complex_part (temp, false)); emit_move_insn (XEXP (to_rtx, 1), read_complex_part (temp, true)); } @@ -4994,14 +5010,14 @@ expand_assignment (tree to, tree from, bool nontemporal) if (optimize_bitfield_assignment_op (bitsize, bitpos, bitregion_start, bitregion_end, - mode1, - to_rtx, to, from)) + mode1, to_rtx, to, from, + reversep)) result = NULL; else result = store_field (to_rtx, bitsize, bitpos, bitregion_start, bitregion_end, - mode1, from, - get_alias_set (to), nontemporal); + mode1, from, get_alias_set (to), + nontemporal, reversep); } if (result) @@ -5155,7 +5171,7 @@ expand_assignment (tree to, tree from, bool nontemporal) /* Compute FROM and store the value in the rtx we got. */ push_temp_slots (); - result = store_expr_with_bounds (from, to_rtx, 0, nontemporal, to); + result = store_expr_with_bounds (from, to_rtx, 0, nontemporal, false, to); preserve_temp_slots (result); pop_temp_slots (); return; @@ -5194,12 +5210,14 @@ emit_storent_insn (rtx to, rtx from) If NONTEMPORAL is true, try using a nontemporal store instruction. + If REVERSE is true, the store is to be done in reverse order. + If BTARGET is not NULL then computed bounds of EXP are associated with BTARGET. */ rtx store_expr_with_bounds (tree exp, rtx target, int call_param_p, - bool nontemporal, tree btarget) + bool nontemporal, bool reverse, tree btarget) { rtx temp; rtx alt_rtl = NULL_RTX; @@ -5221,7 +5239,8 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p, expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, call_param_p ? EXPAND_STACK_PARM : EXPAND_NORMAL); return store_expr_with_bounds (TREE_OPERAND (exp, 1), target, - call_param_p, nontemporal, btarget); + call_param_p, nontemporal, reverse, + btarget); } else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode) { @@ -5236,12 +5255,12 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p, NO_DEFER_POP; jumpifnot (TREE_OPERAND (exp, 0), lab1, -1); store_expr_with_bounds (TREE_OPERAND (exp, 1), target, call_param_p, - nontemporal, btarget); + nontemporal, reverse, btarget); emit_jump_insn (targetm.gen_jump (lab2)); emit_barrier (); emit_label (lab1); store_expr_with_bounds (TREE_OPERAND (exp, 2), target, call_param_p, - nontemporal, btarget); + nontemporal, reverse, btarget); emit_label (lab2); OK_DEFER_POP; @@ -5380,9 +5399,9 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p, rtx tmp_target; normal_expr: - /* If we want to use a nontemporal store, force the value to - register first. */ - tmp_target = nontemporal ? NULL_RTX : target; + /* If we want to use a nontemporal or a reverse order store, force the + value into a register first. */ + tmp_target = nontemporal || reverse ? NULL_RTX : target; temp = expand_expr_real (exp, tmp_target, GET_MODE (target), (call_param_p ? EXPAND_STACK_PARM : EXPAND_NORMAL), @@ -5457,7 +5476,7 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p, else store_bit_field (target, INTVAL (expr_size (exp)) * BITS_PER_UNIT, - 0, 0, 0, GET_MODE (temp), temp); + 0, 0, 0, GET_MODE (temp), temp, reverse); } else convert_move (target, temp, TYPE_UNSIGNED (TREE_TYPE (exp))); @@ -5556,6 +5575,8 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p, ; else { + if (reverse) + temp = flip_storage_order (GET_MODE (target), temp); temp = force_operand (temp, target); if (temp != target) emit_move_insn (target, temp); @@ -5567,9 +5588,11 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p, /* Same as store_expr_with_bounds but ignoring bounds of EXP. */ rtx -store_expr (tree exp, rtx target, int call_param_p, bool nontemporal) +store_expr (tree exp, rtx target, int call_param_p, bool nontemporal, + bool reverse) { - return store_expr_with_bounds (exp, target, call_param_p, nontemporal, NULL); + return store_expr_with_bounds (exp, target, call_param_p, nontemporal, + reverse, NULL); } /* Return true if field F of structure TYPE is a flexible array. */ @@ -5789,8 +5812,12 @@ categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts, init_elts += mult * tc; if (const_from_elts_p && const_p) - const_p = initializer_constant_valid_p (value, elt_type) - != NULL_TREE; + const_p + = initializer_constant_valid_p (value, + elt_type, + TYPE_REVERSE_STORAGE_ORDER + (TREE_TYPE (ctor))) + != NULL_TREE; } break; } @@ -5895,6 +5922,7 @@ all_zeros_p (const_tree exp) TARGET, BITSIZE, BITPOS, MODE, EXP are as for store_field. CLEARED is as for store_constructor. ALIAS_SET is the alias set to use for any stores. + If REVERSE is true, the store is to be done in reverse order. This provides a recursive shortcut back to store_constructor when it isn't necessary to go through store_field. This is so that we can pass through @@ -5904,7 +5932,8 @@ all_zeros_p (const_tree exp) static void store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, machine_mode mode, - tree exp, int cleared, alias_set_type alias_set) + tree exp, int cleared, + alias_set_type alias_set, bool reverse) { if (TREE_CODE (exp) == CONSTRUCTOR /* We can only call store_constructor recursively if the size and @@ -5933,10 +5962,12 @@ store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize, set_mem_alias_set (target, alias_set); } - store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT); + store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT, + reverse); } else - store_field (target, bitsize, bitpos, 0, 0, mode, exp, alias_set, false); + store_field (target, bitsize, bitpos, 0, 0, mode, exp, alias_set, false, + reverse); } @@ -5962,10 +5993,12 @@ fields_length (const_tree type) CLEARED is true if TARGET is known to have been zero'd. SIZE is the number of bytes of TARGET we are allowed to modify: this may not be the same as the size of EXP if we are assigning to a field - which has been packed to exclude padding bits. */ + which has been packed to exclude padding bits. + If REVERSE is true, the store is to be done in reverse order. */ static void -store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) +store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size, + bool reverse) { tree type = TREE_TYPE (exp); HOST_WIDE_INT exp_size = int_size_in_bytes (type); @@ -5979,6 +6012,9 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) unsigned HOST_WIDE_INT idx; tree field, value; + /* The storage order is specified for every aggregate type. */ + reverse = TYPE_REVERSE_STORAGE_ORDER (type); + /* If size is zero or the target is already cleared, do nothing. */ if (size == 0 || cleared) cleared = 1; @@ -6122,7 +6158,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) store_constructor_field (to_rtx, bitsize, bitpos, mode, value, cleared, - get_alias_set (TREE_TYPE (field))); + get_alias_set (TREE_TYPE (field)), + reverse); } break; } @@ -6137,6 +6174,9 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) HOST_WIDE_INT minelt = 0; HOST_WIDE_INT maxelt = 0; + /* The storage order is specified for every aggregate type. */ + reverse = TYPE_REVERSE_STORAGE_ORDER (type); + domain = TYPE_DOMAIN (type); const_bounds_p = (TYPE_MIN_VALUE (domain) && TYPE_MAX_VALUE (domain) @@ -6277,7 +6317,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) store_constructor_field (target, bitsize, bitpos, mode, value, cleared, - get_alias_set (elttype)); + get_alias_set (elttype), reverse); } } else @@ -6292,7 +6332,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) VAR_DECL, NULL_TREE, domain); index_r = gen_reg_rtx (promote_decl_mode (index, NULL)); SET_DECL_RTL (index, index_r); - store_expr (lo_index, index_r, 0, false); + store_expr (lo_index, index_r, 0, false, reverse); /* Build the head of the loop. */ do_pending_stack_adjust (); @@ -6317,9 +6357,9 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) xtarget = adjust_address (xtarget, mode, 0); if (TREE_CODE (value) == CONSTRUCTOR) store_constructor (value, xtarget, cleared, - bitsize / BITS_PER_UNIT); + bitsize / BITS_PER_UNIT, reverse); else - store_expr (value, xtarget, 0, false); + store_expr (value, xtarget, 0, false, reverse); /* Generate a conditional jump to exit the loop. */ exit_cond = build2 (LT_EXPR, integer_type_node, @@ -6362,7 +6402,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) expand_normal (position), highest_pow2_factor (position)); xtarget = adjust_address (xtarget, mode, 0); - store_expr (value, xtarget, 0, false); + store_expr (value, xtarget, 0, false, reverse); } else { @@ -6380,7 +6420,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) MEM_KEEP_ALIAS_SET_P (target) = 1; } store_constructor_field (target, bitsize, bitpos, mode, value, - cleared, get_alias_set (elttype)); + cleared, get_alias_set (elttype), + reverse); } } break; @@ -6513,7 +6554,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) : eltmode; bitpos = eltpos * elt_size; store_constructor_field (target, bitsize, bitpos, value_mode, - value, cleared, alias); + value, cleared, alias, reverse); } } @@ -6546,14 +6587,16 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) (in general) be different from that for TARGET, since TARGET is a reference to the containing structure. - If NONTEMPORAL is true, try generating a nontemporal store. */ + If NONTEMPORAL is true, try generating a nontemporal store. + + If REVERSE is true, the store is to be done in reverse order. */ static rtx store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, unsigned HOST_WIDE_INT bitregion_start, unsigned HOST_WIDE_INT bitregion_end, machine_mode mode, tree exp, - alias_set_type alias_set, bool nontemporal) + alias_set_type alias_set, bool nontemporal, bool reverse) { if (TREE_CODE (exp) == ERROR_MARK) return const0_rtx; @@ -6568,7 +6611,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, /* We're storing into a struct containing a single __complex. */ gcc_assert (!bitpos); - return store_expr (exp, target, 0, nontemporal); + return store_expr (exp, target, 0, nontemporal, reverse); } /* If the structure is in a register or if the component @@ -6637,16 +6680,27 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, temp = expand_normal (exp); - /* If BITSIZE is narrower than the size of the type of EXP - we will be narrowing TEMP. Normally, what's wanted are the - low-order bits. However, if EXP's type is a record and this is - big-endian machine, we want the upper BITSIZE bits. */ - if (BYTES_BIG_ENDIAN && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT - && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (temp)) - && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE) - temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp, - GET_MODE_BITSIZE (GET_MODE (temp)) - bitsize, - NULL_RTX, 1); + /* If the value has a record type and an integral mode then, if BITSIZE + is narrower than this mode and this is for big-endian data, we must + first put the value into the low-order bits. Moreover, the field may + be not aligned on a byte boundary; in this case, if it has reverse + storage order, it needs to be accessed as a scalar field with reverse + storage order and we must first put the value into target order. */ + if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE + && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT) + { + HOST_WIDE_INT size = GET_MODE_BITSIZE (GET_MODE (temp)); + + reverse = TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (exp)); + + if (reverse) + temp = flip_storage_order (GET_MODE (temp), temp); + + if (bitsize < size + && reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN) + temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp, + size - bitsize, NULL_RTX, 1); + } /* Unless MODE is VOIDmode or BLKmode, convert TEMP to MODE. */ if (mode != VOIDmode && mode != BLKmode @@ -6706,7 +6760,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, temp_target = gen_reg_rtx (mode); temp_target = extract_bit_field (temp, size * BITS_PER_UNIT, 0, 1, - temp_target, mode, mode); + temp_target, mode, mode, false); temp = temp_target; } } @@ -6714,7 +6768,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, /* Store the value in the bitfield. */ store_bit_field (target, bitsize, bitpos, bitregion_start, bitregion_end, - mode, temp); + mode, temp, reverse); return const0_rtx; } @@ -6734,11 +6788,11 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, if (TREE_CODE (exp) == CONSTRUCTOR && bitsize >= 0) { gcc_assert (bitsize % BITS_PER_UNIT == 0); - store_constructor (exp, to_rtx, 0, bitsize/BITS_PER_UNIT); + store_constructor (exp, to_rtx, 0, bitsize / BITS_PER_UNIT, reverse); return to_rtx; } - return store_expr (exp, to_rtx, 0, nontemporal); + return store_expr (exp, to_rtx, 0, nontemporal, reverse); } } @@ -6747,7 +6801,8 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, codes and find the ultimate containing object, which we return. We set *PBITSIZE to the size in bits that we want, *PBITPOS to the - bit position, and *PUNSIGNEDP to the signedness of the field. + bit position, *PUNSIGNEDP to the signedness and *PREVERSEP to the + storage order of the field. If the position of the field is variable, we store a tree giving the variable offset (in units) in *POFFSET. This offset is in addition to the bit position. @@ -6781,7 +6836,7 @@ tree get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, HOST_WIDE_INT *pbitpos, tree *poffset, machine_mode *pmode, int *punsignedp, - int *pvolatilep, bool keep_aligning) + int *preversep, int *pvolatilep, bool keep_aligning) { tree size_tree = 0; machine_mode mode = VOIDmode; @@ -6789,8 +6844,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, tree offset = size_zero_node; offset_int bit_offset = 0; - /* First get the mode, signedness, and size. We do this from just the - outermost expression. */ + /* First get the mode, signedness, storage order and size. We do this from + just the outermost expression. */ *pbitsize = -1; if (TREE_CODE (exp) == COMPONENT_REF) { @@ -6843,6 +6898,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, *pbitsize = tree_to_uhwi (size_tree); } + *preversep = reverse_storage_order_for_component_p (exp); + /* Compute cumulative bit-offset for nested component-refs and array-refs, and find the ultimate containing object. */ while (1) @@ -7519,7 +7576,7 @@ expand_expr_addr_expr_1 (tree exp, rtx target, machine_mode tmode, rtx result, subtarget; tree inner, offset; HOST_WIDE_INT bitsize, bitpos; - int volatilep, unsignedp; + int unsignedp, reversep, volatilep = 0; machine_mode mode1; /* If we are taking the address of a constant and are at the top level, @@ -7626,8 +7683,8 @@ expand_expr_addr_expr_1 (tree exp, rtx target, machine_mode tmode, handle "aligning nodes" here: we can just bypass them because they won't change the final object whose address will be returned (they actually exist only for that purpose). */ - inner = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode1, &unsignedp, &volatilep, false); + inner = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode1, + &unsignedp, &reversep, &volatilep, false); break; } @@ -7811,7 +7868,7 @@ expand_constructor (tree exp, rtx target, enum expand_modifier modifier, target = assign_temp (type, TREE_ADDRESSABLE (exp), 1); } - store_constructor (exp, target, 0, int_expr_size (exp)); + store_constructor (exp, target, 0, int_expr_size (exp), false); return target; } @@ -8084,11 +8141,12 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode, store_expr (treeop0, adjust_address (target, TYPE_MODE (valtype), 0), modifier == EXPAND_STACK_PARM, - false); + false, TYPE_REVERSE_STORAGE_ORDER (type)); else { - gcc_assert (REG_P (target)); + gcc_assert (REG_P (target) + && !TYPE_REVERSE_STORAGE_ORDER (type)); /* Store this field into a union of the proper type. */ store_field (target, @@ -8096,7 +8154,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode, (treeop0)) * BITS_PER_UNIT), (HOST_WIDE_INT) GET_MODE_BITSIZE (mode)), - 0, 0, 0, TYPE_MODE (valtype), treeop0, 0, false); + 0, 0, 0, TYPE_MODE (valtype), treeop0, 0, + false, false); } /* Return the entire union. */ @@ -9131,7 +9190,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode, int index = BYTES_BIG_ENDIAN ? GET_MODE_NUNITS (vec_mode) - 1 : 0; int bitsize = GET_MODE_UNIT_BITSIZE (vec_mode); temp = extract_bit_field (temp, bitsize, bitsize * index, unsignedp, - target, mode, mode); + target, mode, mode, false); gcc_assert (temp); return temp; } @@ -9287,14 +9346,14 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode, jumpifnot (treeop0, lab0, -1); store_expr (treeop1, temp, modifier == EXPAND_STACK_PARM, - false); + false, false); emit_jump_insn (targetm.gen_jump (lab1)); emit_barrier (); emit_label (lab0); store_expr (treeop2, temp, modifier == EXPAND_STACK_PARM, - false); + false, false); emit_label (lab1); OK_DEFER_POP; @@ -9847,6 +9906,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, case MEM_REF: { + const bool reverse = REF_REVERSE_STORAGE_ORDER (exp); addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)))); machine_mode address_mode; @@ -9861,6 +9921,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, HOST_WIDE_INT offset = mem_ref_offset (exp).to_short_addr (); base = TREE_OPERAND (base, 0); if (offset == 0 + && !reverse && tree_fits_uhwi_p (TYPE_SIZE (type)) && (GET_MODE_BITSIZE (DECL_MODE (base)) == tree_to_uhwi (TYPE_SIZE (type)))) @@ -9870,13 +9931,14 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, { temp = assign_stack_temp (DECL_MODE (base), GET_MODE_SIZE (DECL_MODE (base))); - store_expr (base, temp, 0, false); + store_expr (base, temp, 0, false, false); temp = adjust_address (temp, BLKmode, offset); set_mem_size (temp, int_size_in_bytes (type)); return temp; } exp = build3 (BIT_FIELD_REF, type, base, TYPE_SIZE (type), bitsize_int (offset * BITS_PER_UNIT)); + REF_REVERSE_STORAGE_ORDER (exp) = reverse; return expand_expr (exp, target, tmode, modifier); } address_mode = targetm.addr_space.address_mode (as); @@ -9926,8 +9988,12 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, 0, TYPE_UNSIGNED (TREE_TYPE (exp)), (modifier == EXPAND_STACK_PARM ? NULL_RTX : target), - mode, mode); + mode, mode, false); } + if (reverse + && modifier != EXPAND_MEMORY + && modifier != EXPAND_WRITE) + temp = flip_storage_order (mode, temp); return temp; } @@ -10133,9 +10199,10 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, machine_mode mode1, mode2; HOST_WIDE_INT bitsize, bitpos; tree offset; - int volatilep = 0, must_force_mem; - tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode1, &unsignedp, &volatilep, true); + int reversep, volatilep = 0, must_force_mem; + tree tem + = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode1, + &unsignedp, &reversep, &volatilep, true); rtx orig_op0, memloc; bool clear_mem_expr = false; @@ -10190,7 +10257,11 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, { if (bitpos == 0 && bitsize == GET_MODE_BITSIZE (GET_MODE (op0))) - return op0; + { + if (reversep) + op0 = flip_storage_order (GET_MODE (op0), op0); + return op0; + } if (bitpos == 0 && bitsize == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0))) && bitsize) @@ -10376,20 +10447,38 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, if (MEM_P (op0) && REG_P (XEXP (op0, 0))) mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0)); + /* If the result has a record type and the extraction is done in + an integral mode, then the field may be not aligned on a byte + boundary; in this case, if it has reverse storage order, it + needs to be extracted as a scalar field with reverse storage + order and put back into memory order afterwards. */ + if (TREE_CODE (type) == RECORD_TYPE + && GET_MODE_CLASS (ext_mode) == MODE_INT) + reversep = TYPE_REVERSE_STORAGE_ORDER (type); + op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp, (modifier == EXPAND_STACK_PARM ? NULL_RTX : target), - ext_mode, ext_mode); - - /* If the result is a record type and BITSIZE is narrower than - the mode of OP0, an integral mode, and this is a big endian - machine, we must put the field into the high-order bits. */ - if (TREE_CODE (type) == RECORD_TYPE && BYTES_BIG_ENDIAN - && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT - && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (op0))) - op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0, - GET_MODE_BITSIZE (GET_MODE (op0)) - - bitsize, op0, 1); + ext_mode, ext_mode, reversep); + + /* If the result has a record type and the mode of OP0 is an + integral mode then, if BITSIZE is narrower than this mode + and this is for big-endian data, we must put the field + into the high-order bits. And we must also put it back + into memory order if it has been previously reversed. */ + if (TREE_CODE (type) == RECORD_TYPE + && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT) + { + HOST_WIDE_INT size = GET_MODE_BITSIZE (GET_MODE (op0)); + + if (bitsize < size + && reversep ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN) + op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0, + size - bitsize, op0, 1); + + if (reversep) + op0 = flip_storage_order (GET_MODE (op0), op0); + } /* If the result type is BLKmode, store the data into a temporary of the appropriate type, but with the mode corresponding to the @@ -10435,6 +10524,12 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, set_mem_expr (op0, NULL_TREE); MEM_VOLATILE_P (op0) |= volatilep; + + if (reversep + && modifier != EXPAND_MEMORY + && modifier != EXPAND_WRITE) + op0 = flip_storage_order (mode1, op0); + if (mode == mode1 || mode1 == BLKmode || mode1 == tmode || modifier == EXPAND_CONST_ADDRESS || modifier == EXPAND_INITIALIZER) @@ -10498,17 +10593,16 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, machine_mode mode1; HOST_WIDE_INT bitsize, bitpos; tree offset; - int unsignedp; - int volatilep = 0; + int unsignedp, reversep, volatilep = 0; tree tem - = get_inner_reference (treeop0, &bitsize, &bitpos, - &offset, &mode1, &unsignedp, &volatilep, - true); + = get_inner_reference (treeop0, &bitsize, &bitpos, &offset, &mode1, + &unsignedp, &reversep, &volatilep, true); rtx orig_op0; /* ??? We should work harder and deal with non-zero offsets. */ if (!offset && (bitpos % BITS_PER_UNIT) == 0 + && !reversep && bitsize >= 0 && compare_tree_int (TYPE_SIZE (type), bitsize) == 0) { @@ -10582,7 +10676,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, else if (reduce_bit_field) return extract_bit_field (op0, TYPE_PRECISION (type), 0, TYPE_UNSIGNED (type), NULL_RTX, - mode, mode); + mode, mode, false); /* As a last resort, spill op0 to memory, and reload it in a different mode. */ else if (!MEM_P (op0)) diff --git a/gcc/expr.h b/gcc/expr.h index a2c8e1d1e57..33a35aa6820 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -212,6 +212,7 @@ extern rtx_insn *emit_move_complex_push (machine_mode, rtx, rtx); extern rtx_insn *emit_move_complex_parts (rtx, rtx); extern rtx read_complex_part (rtx, bool); extern void write_complex_part (rtx, rtx, bool); +extern rtx read_complex_part (rtx, bool); extern rtx emit_move_resolve_push (machine_mode, rtx); /* Push a block of length SIZE (perhaps variable) @@ -229,8 +230,8 @@ extern void expand_assignment (tree, tree, bool); and storing the value into TARGET. If SUGGEST_REG is nonzero, copy the value through a register and return that register, if that is possible. */ -extern rtx store_expr_with_bounds (tree, rtx, int, bool, tree); -extern rtx store_expr (tree, rtx, int, bool); +extern rtx store_expr_with_bounds (tree, rtx, int, bool, bool, tree); +extern rtx store_expr (tree, rtx, int, bool, bool); /* Given an rtx that may include add and multiply operations, generate them as insns and return a pseudo-reg containing the value. diff --git a/gcc/flag-types.h b/gcc/flag-types.h index 6301cea4807..88a760c5d4e 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -165,7 +165,6 @@ enum stack_check_type /* Names for the different levels of -Wstrict-overflow=N. The numeric values here correspond to N. */ - enum warn_strict_overflow_code { /* Overflow warning that should be issued with -Wall: a questionable @@ -195,6 +194,13 @@ enum fp_contract_mode { FP_CONTRACT_FAST = 2 }; +/* Scalar storage order kind. */ +enum scalar_storage_order_kind { + SSO_NATIVE = 0, + SSO_BIG_ENDIAN, + SSO_LITTLE_ENDIAN +}; + /* Vectorizer cost-model. */ enum vect_cost_model { VECT_COST_MODEL_UNLIMITED = 0, @@ -203,7 +209,6 @@ enum vect_cost_model { VECT_COST_MODEL_DEFAULT = 3 }; - /* Different instrumentation modes. */ enum sanitize_code { /* AddressSanitizer. */ diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c index 5af2c635313..49793a5ab6f 100644 --- a/gcc/fold-const-call.c +++ b/gcc/fold-const-call.c @@ -24,7 +24,9 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "stor-layout.h" #include "options.h" +#include "fold-const.h" #include "fold-const-call.h" +#include "tm.h" /* For C[LT]Z_DEFINED_AT_ZERO. */ /* Functions that test for certain constant types, abstracting away the decision about whether to check for overflow. */ @@ -47,6 +49,31 @@ complex_cst_p (tree t) return TREE_CODE (t) == COMPLEX_CST; } +/* Return true if ARG is a constant in the range of the host size_t. + Store it in *SIZE_OUT if so. */ + +static inline bool +host_size_t_cst_p (tree t, size_t *size_out) +{ + if (integer_cst_p (t) + && wi::min_precision (t, UNSIGNED) <= sizeof (size_t) * CHAR_BIT) + { + *size_out = tree_to_uhwi (t); + return true; + } + return false; +} + +/* RES is the result of a comparison in which < 0 means "less", 0 means + "equal" and > 0 means "more". Canonicalize it to -1, 0 or 1 and + return it in type TYPE. */ + +static inline tree +build_cmp_result (tree type, int res) +{ + return build_int_cst (type, res < 0 ? -1 : res > 0 ? 1 : 0); +} + /* M is the result of trying to constant-fold an expression (starting with clear MPFR flags) and INEXACT says whether the result in M is exact or inexact. Return true if M can be used as a constant-folded @@ -526,6 +553,20 @@ fold_const_builtin_load_exponent (real_value *result, const real_value *arg0, return real_equal (&initial_result, result); } +/* Fold a call to __builtin_nan or __builtin_nans with argument ARG and + return type TYPE. QUIET is true if a quiet rather than signalling + NaN is required. */ + +static tree +fold_const_builtin_nan (tree type, tree arg, bool quiet) +{ + REAL_VALUE_TYPE real; + const char *str = c_getstr (arg); + if (str && real_nan (&real, str, quiet, TYPE_MODE (type))) + return build_real (type, real); + return NULL_TREE; +} + /* Try to evaluate: *RESULT = FN (*ARG) @@ -736,6 +777,94 @@ fold_const_call_ss (wide_int *result, built_in_function fn, /* Not yet folded to a constant. */ return false; + CASE_FLT_FN (BUILT_IN_FINITE): + case BUILT_IN_FINITED32: + case BUILT_IN_FINITED64: + case BUILT_IN_FINITED128: + case BUILT_IN_ISFINITE: + *result = wi::shwi (real_isfinite (arg) ? 1 : 0, precision); + return true; + + CASE_FLT_FN (BUILT_IN_ISINF): + case BUILT_IN_ISINFD32: + case BUILT_IN_ISINFD64: + case BUILT_IN_ISINFD128: + if (real_isinf (arg)) + *result = wi::shwi (arg->sign ? -1 : 1, precision); + else + *result = wi::shwi (0, precision); + return true; + + CASE_FLT_FN (BUILT_IN_ISNAN): + case BUILT_IN_ISNAND32: + case BUILT_IN_ISNAND64: + case BUILT_IN_ISNAND128: + *result = wi::shwi (real_isnan (arg) ? 1 : 0, precision); + return true; + + default: + return false; + } +} + +/* Try to evaluate: + + *RESULT = FN (ARG) + + where ARG_TYPE is the type of ARG and PRECISION is the number of bits + in the result. Return true on success. */ + +static bool +fold_const_call_ss (wide_int *result, built_in_function fn, + const wide_int_ref &arg, unsigned int precision, + tree arg_type) +{ + switch (fn) + { + CASE_INT_FN (BUILT_IN_FFS): + *result = wi::shwi (wi::ffs (arg), precision); + return true; + + CASE_INT_FN (BUILT_IN_CLZ): + { + int tmp; + if (wi::ne_p (arg, 0)) + tmp = wi::clz (arg); + else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (arg_type), tmp)) + tmp = TYPE_PRECISION (arg_type); + *result = wi::shwi (tmp, precision); + return true; + } + + CASE_INT_FN (BUILT_IN_CTZ): + { + int tmp; + if (wi::ne_p (arg, 0)) + tmp = wi::ctz (arg); + else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (arg_type), tmp)) + tmp = TYPE_PRECISION (arg_type); + *result = wi::shwi (tmp, precision); + return true; + } + + CASE_INT_FN (BUILT_IN_CLRSB): + *result = wi::shwi (wi::clrsb (arg), precision); + return true; + + CASE_INT_FN (BUILT_IN_POPCOUNT): + *result = wi::shwi (wi::popcount (arg), precision); + return true; + + CASE_INT_FN (BUILT_IN_PARITY): + *result = wi::shwi (wi::parity (arg), precision); + return true; + + case BUILT_IN_BSWAP16: + case BUILT_IN_BSWAP32: + case BUILT_IN_BSWAP64: + *result = wide_int::from (arg, precision, TYPE_SIGN (arg_type)).bswap (); + return true; + default: return false; } @@ -882,15 +1011,27 @@ fold_const_call_cc (real_value *result_real, real_value *result_imag, } } -/* Try to fold FN (ARG) to a constant. Return the constant on success, - otherwise return null. TYPE is the type of the return value. */ +/* Subroutine of fold_const_call, with the same interface. Handle cases + where the arguments and result are numerical. */ -tree -fold_const_call (built_in_function fn, tree type, tree arg) +static tree +fold_const_call_1 (built_in_function fn, tree type, tree arg) { machine_mode mode = TYPE_MODE (type); machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg)); + if (integer_cst_p (arg)) + { + if (SCALAR_INT_MODE_P (mode)) + { + wide_int result; + if (fold_const_call_ss (&result, fn, arg, TYPE_PRECISION (type), + TREE_TYPE (arg))) + return wide_int_to_tree (type, result); + } + return NULL_TREE; + } + if (real_cst_p (arg)) { gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode)); @@ -965,6 +1106,33 @@ fold_const_call (built_in_function fn, tree type, tree arg) return NULL_TREE; } +/* Try to fold FN (ARG) to a constant. Return the constant on success, + otherwise return null. TYPE is the type of the return value. */ + +tree +fold_const_call (built_in_function fn, tree type, tree arg) +{ + switch (fn) + { + case BUILT_IN_STRLEN: + if (const char *str = c_getstr (arg)) + return build_int_cst (type, strlen (str)); + return NULL_TREE; + + CASE_FLT_FN (BUILT_IN_NAN): + case BUILT_IN_NAND32: + case BUILT_IN_NAND64: + case BUILT_IN_NAND128: + return fold_const_builtin_nan (type, arg, true); + + CASE_FLT_FN (BUILT_IN_NANS): + return fold_const_builtin_nan (type, arg, false); + + default: + return fold_const_call_1 (fn, type, arg); + } +} + /* Try to evaluate: *RESULT = FN (*ARG0, *ARG1) @@ -1093,11 +1261,11 @@ fold_const_call_ccc (real_value *result_real, real_value *result_imag, } } -/* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success, - otherwise return null. TYPE is the type of the return value. */ +/* Subroutine of fold_const_call, with the same interface. Handle cases + where the arguments and result are numerical. */ -tree -fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1) +static tree +fold_const_call_1 (built_in_function fn, tree type, tree arg0, tree arg1) { machine_mode mode = TYPE_MODE (type); machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0)); @@ -1185,6 +1353,35 @@ fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1) return NULL_TREE; } +/* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success, + otherwise return null. TYPE is the type of the return value. */ + +tree +fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1) +{ + const char *p0, *p1; + switch (fn) + { + case BUILT_IN_STRSPN: + if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1))) + return build_int_cst (type, strspn (p0, p1)); + return NULL_TREE; + + case BUILT_IN_STRCSPN: + if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1))) + return build_int_cst (type, strcspn (p0, p1)); + return NULL_TREE; + + case BUILT_IN_STRCMP: + if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1))) + return build_cmp_result (type, strcmp (p0, p1)); + return NULL_TREE; + + default: + return fold_const_call_1 (fn, type, arg0, arg1); + } +} + /* Try to evaluate: *RESULT = FN (*ARG0, *ARG1, *ARG2) @@ -1206,12 +1403,12 @@ fold_const_call_ssss (real_value *result, built_in_function fn, } } -/* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on - success, otherwise return null. TYPE is the type of the return value. */ +/* Subroutine of fold_const_call, with the same interface. Handle cases + where the arguments and result are numerical. */ -tree -fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1, - tree arg2) +static tree +fold_const_call_1 (built_in_function fn, tree type, tree arg0, tree arg1, + tree arg2) { machine_mode mode = TYPE_MODE (type); machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0)); @@ -1241,6 +1438,39 @@ fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1, return NULL_TREE; } +/* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on + success, otherwise return null. TYPE is the type of the return value. */ + +tree +fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1, + tree arg2) +{ + const char *p0, *p1; + size_t s2; + switch (fn) + { + case BUILT_IN_STRNCMP: + if ((p0 = c_getstr (arg0)) + && (p1 = c_getstr (arg1)) + && host_size_t_cst_p (arg2, &s2)) + return build_int_cst (type, strncmp (p0, p1, s2)); + return NULL_TREE; + + case BUILT_IN_BCMP: + case BUILT_IN_MEMCMP: + if ((p0 = c_getstr (arg0)) + && (p1 = c_getstr (arg1)) + && host_size_t_cst_p (arg2, &s2) + && s2 <= strlen (p0) + && s2 <= strlen (p1)) + return build_cmp_result (type, memcmp (p0, p1, s2)); + return NULL_TREE; + + default: + return fold_const_call_1 (fn, type, arg0, arg1, arg2); + } +} + /* Fold a fma operation with arguments ARG[012]. */ tree diff --git a/gcc/fold-const.c b/gcc/fold-const.c index ee9b34910df..8b437ab8f26 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -114,12 +114,12 @@ static int operand_equal_for_comparison_p (tree, tree, tree); static int twoval_comparison_p (tree, tree *, tree *, int *); static tree eval_subst (location_t, tree, tree, tree, tree, tree); static tree make_bit_field_ref (location_t, tree, tree, - HOST_WIDE_INT, HOST_WIDE_INT, int); + HOST_WIDE_INT, HOST_WIDE_INT, int, int); static tree optimize_bit_field_compare (location_t, enum tree_code, tree, tree, tree); static tree decode_field_reference (location_t, tree, HOST_WIDE_INT *, HOST_WIDE_INT *, - machine_mode *, int *, int *, + machine_mode *, int *, int *, int *, tree *, tree *); static int simple_operand_p (const_tree); static bool simple_operand_p_2 (tree); @@ -1545,7 +1545,11 @@ const_unop (enum tree_code code, tree type, tree arg0) return fold_convert_const (code, type, arg0); case ADDR_SPACE_CONVERT_EXPR: - if (integer_zerop (arg0)) + /* If the source address is 0, and the source address space + cannot have a valid object at 0, fold to dest type null. */ + if (integer_zerop (arg0) + && !(targetm.addr_space.zero_address_valid + (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0)))))) return fold_convert_const (code, type, arg0); break; @@ -2649,8 +2653,7 @@ combine_comparisons (location_t loc, } /* Return nonzero if two operands (typically of the same tree node) - are necessarily equal. If either argument has side-effects this - function returns zero. FLAGS modifies behavior as follows: + are necessarily equal. FLAGS modifies behavior as follows: If OEP_ONLY_CONST is set, only return nonzero for constants. This function tests whether the operands are indistinguishable; @@ -2675,9 +2678,14 @@ combine_comparisons (location_t loc, to ensure that global memory is unchanged in between. If OEP_ADDRESS_OF is set, we are actually comparing addresses of objects, - not values of expressions. OEP_CONSTANT_ADDRESS_OF in addition to - OEP_ADDRESS_OF is used for ADDR_EXPR with TREE_CONSTANT flag set and we - further ignore any side effects on SAVE_EXPRs then. */ + not values of expressions. + + Unless OEP_MATCH_SIDE_EFFECTS is set, the function returns false on + any operand with side effect. This is unnecesarily conservative in the + case we know that arg0 and arg1 are in disjoint code paths (such as in + ?: operator). In addition OEP_MATCH_SIDE_EFFECTS is used when comparing + addresses with TREE_CONSTANT flag set so we know that &var == &var + even if var is volatile. */ int operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) @@ -2693,14 +2701,20 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) if (!TREE_TYPE (arg0) || !TREE_TYPE (arg1)) return 0; + /* We cannot consider pointers to different address space equal. */ + if (POINTER_TYPE_P (TREE_TYPE (arg0)) + && POINTER_TYPE_P (TREE_TYPE (arg1)) + && (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0))) + != TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg1))))) + return 0; + /* Check equality of integer constants before bailing out due to precision differences. */ if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) { /* Address of INTEGER_CST is not defined; check that we did not forget - to drop the OEP_ADDRESS_OF/OEP_CONSTANT_ADDRESS_OF flags. */ - gcc_checking_assert (!(flags - & (OEP_ADDRESS_OF | OEP_CONSTANT_ADDRESS_OF))); + to drop the OEP_ADDRESS_OF flags. */ + gcc_checking_assert (!(flags & OEP_ADDRESS_OF)); return tree_int_cst_equal (arg0, arg1); } @@ -2716,13 +2730,6 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) != POINTER_TYPE_P (TREE_TYPE (arg1))) return 0; - /* We cannot consider pointers to different address space equal. */ - if (POINTER_TYPE_P (TREE_TYPE (arg0)) - && POINTER_TYPE_P (TREE_TYPE (arg1)) - && (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0))) - != TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg1))))) - return 0; - /* If both types don't have the same precision, then it is not safe to strip NOPs. */ if (element_precision (TREE_TYPE (arg0)) @@ -2806,7 +2813,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) they are necessarily equal as well. */ if (arg0 == arg1 && ! (flags & OEP_ONLY_CONST) && (TREE_CODE (arg0) == SAVE_EXPR - || (flags & OEP_CONSTANT_ADDRESS_OF) + || (flags & OEP_MATCH_SIDE_EFFECTS) || (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1)))) return 1; @@ -2865,11 +2872,10 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) TREE_STRING_LENGTH (arg0))); case ADDR_EXPR: - gcc_checking_assert (!(flags - & (OEP_ADDRESS_OF | OEP_CONSTANT_ADDRESS_OF))); + gcc_checking_assert (!(flags & OEP_ADDRESS_OF)); return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), flags | OEP_ADDRESS_OF - | OEP_CONSTANT_ADDRESS_OF); + | OEP_MATCH_SIDE_EFFECTS); case CONSTRUCTOR: /* In GIMPLE empty constructors are allowed in initializers of aggregates. */ @@ -2928,7 +2934,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) /* If either of the pointer (or reference) expressions we are dereferencing contain a side effect, these cannot be equal, but their addresses can be. */ - if ((flags & OEP_CONSTANT_ADDRESS_OF) == 0 + if ((flags & OEP_MATCH_SIDE_EFFECTS) == 0 && (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1))) return 0; @@ -2936,11 +2942,11 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) switch (TREE_CODE (arg0)) { case INDIRECT_REF: - if (!(flags & (OEP_ADDRESS_OF | OEP_CONSTANT_ADDRESS_OF)) + if (!(flags & OEP_ADDRESS_OF) && (TYPE_ALIGN (TREE_TYPE (arg0)) != TYPE_ALIGN (TREE_TYPE (arg1)))) return 0; - flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF); + flags &= ~OEP_ADDRESS_OF; return OP_SAME (0); case REALPART_EXPR: @@ -2950,7 +2956,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) case TARGET_MEM_REF: case MEM_REF: - if (!(flags & (OEP_ADDRESS_OF | OEP_CONSTANT_ADDRESS_OF))) + if (!(flags & OEP_ADDRESS_OF)) { /* Require equal access sizes */ if (TYPE_SIZE (TREE_TYPE (arg0)) != TYPE_SIZE (TREE_TYPE (arg1)) @@ -2975,7 +2981,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) != TYPE_ALIGN (TREE_TYPE (arg1))) return 0; } - flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF); + flags &= ~OEP_ADDRESS_OF; return (OP_SAME (0) && OP_SAME (1) /* TARGET_MEM_REF require equal extra operands. */ && (TREE_CODE (arg0) != TARGET_MEM_REF @@ -2990,7 +2996,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) may have different types but same value here. */ if (!OP_SAME (0)) return 0; - flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF); + flags &= ~OEP_ADDRESS_OF; return ((tree_int_cst_equal (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 1)) || OP_SAME (1)) @@ -3003,13 +3009,13 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) if (!OP_SAME_WITH_NULL (0) || !OP_SAME (1)) return 0; - flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF); + flags &= ~OEP_ADDRESS_OF; return OP_SAME_WITH_NULL (2); case BIT_FIELD_REF: if (!OP_SAME (0)) return 0; - flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF); + flags &= ~OEP_ADDRESS_OF; return OP_SAME (1) && OP_SAME (2); default: @@ -3021,9 +3027,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) { case ADDR_EXPR: /* Be sure we pass right ADDRESS_OF flag. */ - gcc_checking_assert (!(flags - & (OEP_ADDRESS_OF - | OEP_CONSTANT_ADDRESS_OF))); + gcc_checking_assert (!(flags & OEP_ADDRESS_OF)); return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), flags | OEP_ADDRESS_OF); @@ -3089,6 +3093,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) return 0; } + /* FIXME: We could skip this test for OEP_MATCH_SIDE_EFFECTS. */ { unsigned int cef = call_expr_flags (arg0); if (flags & OEP_PURE_SAME) @@ -3687,15 +3692,17 @@ distribute_real_division (location_t loc, enum tree_code code, tree type, } /* Return a BIT_FIELD_REF of type TYPE to refer to BITSIZE bits of INNER - starting at BITPOS. The field is unsigned if UNSIGNEDP is nonzero. */ + starting at BITPOS. The field is unsigned if UNSIGNEDP is nonzero + and uses reverse storage order if REVERSEP is nonzero. */ static tree make_bit_field_ref (location_t loc, tree inner, tree type, - HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, int unsignedp) + HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, + int unsignedp, int reversep) { tree result, bftype; - if (bitpos == 0) + if (bitpos == 0 && !reversep) { tree size = TYPE_SIZE (TREE_TYPE (inner)); if ((INTEGRAL_TYPE_P (TREE_TYPE (inner)) @@ -3712,6 +3719,7 @@ make_bit_field_ref (location_t loc, tree inner, tree type, result = build3_loc (loc, BIT_FIELD_REF, bftype, inner, size_int (bitsize), bitsize_int (bitpos)); + REF_REVERSE_STORAGE_ORDER (result) = reversep; if (bftype != type) result = fold_convert_loc (loc, type, result); @@ -3749,6 +3757,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, int const_p = TREE_CODE (rhs) == INTEGER_CST; machine_mode lmode, rmode, nmode; int lunsignedp, runsignedp; + int lreversep, rreversep; int lvolatilep = 0, rvolatilep = 0; tree linner, rinner = NULL_TREE; tree mask; @@ -3760,20 +3769,23 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, do anything if the inner expression is a PLACEHOLDER_EXPR since we then will no longer be able to replace it. */ linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode, - &lunsignedp, &lvolatilep, false); + &lunsignedp, &lreversep, &lvolatilep, false); if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0 || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR || lvolatilep) return 0; - if (!const_p) + if (const_p) + rreversep = lreversep; + else { /* If this is not a constant, we can only do something if bit positions, - sizes, and signedness are the same. */ - rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode, - &runsignedp, &rvolatilep, false); + sizes, signedness and storage order are the same. */ + rinner + = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode, + &runsignedp, &rreversep, &rvolatilep, false); if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize - || lunsignedp != runsignedp || offset != 0 + || lunsignedp != runsignedp || lreversep != rreversep || offset != 0 || TREE_CODE (rinner) == PLACEHOLDER_EXPR || rvolatilep) return 0; } @@ -3801,7 +3813,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, if (nbitsize == lbitsize) return 0; - if (BYTES_BIG_ENDIAN) + if (lreversep ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN) lbitpos = nbitsize - lbitsize - lbitpos; /* Make the mask to be used against the extracted field. */ @@ -3818,17 +3830,17 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, make_bit_field_ref (loc, linner, unsigned_type, nbitsize, nbitpos, - 1), + 1, lreversep), mask), fold_build2_loc (loc, BIT_AND_EXPR, unsigned_type, make_bit_field_ref (loc, rinner, unsigned_type, nbitsize, nbitpos, - 1), + 1, rreversep), mask)); - /* Otherwise, we are handling the constant case. See if the constant is too - big for the field. Warn and return a tree of for 0 (false) if so. We do + /* Otherwise, we are handling the constant case. See if the constant is too + big for the field. Warn and return a tree for 0 (false) if so. We do this not only for its own sake, but to avoid having to test for this error case below. If we didn't, we might generate wrong code. @@ -3866,7 +3878,8 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, /* Make a new bitfield reference, shift the constant over the appropriate number of bits and mask it with the computed mask (in case this was a signed field). If we changed it, make a new one. */ - lhs = make_bit_field_ref (loc, linner, unsigned_type, nbitsize, nbitpos, 1); + lhs = make_bit_field_ref (loc, linner, unsigned_type, nbitsize, nbitpos, 1, + lreversep); rhs = const_binop (BIT_AND_EXPR, const_binop (LSHIFT_EXPR, @@ -3894,6 +3907,8 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, *PUNSIGNEDP is set to the signedness of the field. + *PREVERSEP is set to the storage order of the field. + *PMASK is set to the mask used. This is either contained in a BIT_AND_EXPR or derived from the width of the field. @@ -3905,7 +3920,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, static tree decode_field_reference (location_t loc, tree exp, HOST_WIDE_INT *pbitsize, HOST_WIDE_INT *pbitpos, machine_mode *pmode, - int *punsignedp, int *pvolatilep, + int *punsignedp, int *preversep, int *pvolatilep, tree *pmask, tree *pand_mask) { tree outer_type = 0; @@ -3938,7 +3953,7 @@ decode_field_reference (location_t loc, tree exp, HOST_WIDE_INT *pbitsize, } inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode, - punsignedp, pvolatilep, false); + punsignedp, preversep, pvolatilep, false); if ((inner == exp && and_mask == 0) || *pbitsize < 0 || offset != 0 || TREE_CODE (inner) == PLACEHOLDER_EXPR) @@ -5440,6 +5455,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type, HOST_WIDE_INT xll_bitpos, xlr_bitpos, xrl_bitpos, xrr_bitpos; HOST_WIDE_INT lnbitsize, lnbitpos, rnbitsize, rnbitpos; int ll_unsignedp, lr_unsignedp, rl_unsignedp, rr_unsignedp; + int ll_reversep, lr_reversep, rl_reversep, rr_reversep; machine_mode ll_mode, lr_mode, rl_mode, rr_mode; machine_mode lnmode, rnmode; tree ll_mask, lr_mask, rl_mask, rr_mask; @@ -5552,33 +5568,39 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type, volatilep = 0; ll_inner = decode_field_reference (loc, ll_arg, &ll_bitsize, &ll_bitpos, &ll_mode, - &ll_unsignedp, &volatilep, &ll_mask, - &ll_and_mask); + &ll_unsignedp, &ll_reversep, &volatilep, + &ll_mask, &ll_and_mask); lr_inner = decode_field_reference (loc, lr_arg, &lr_bitsize, &lr_bitpos, &lr_mode, - &lr_unsignedp, &volatilep, &lr_mask, - &lr_and_mask); + &lr_unsignedp, &lr_reversep, &volatilep, + &lr_mask, &lr_and_mask); rl_inner = decode_field_reference (loc, rl_arg, &rl_bitsize, &rl_bitpos, &rl_mode, - &rl_unsignedp, &volatilep, &rl_mask, - &rl_and_mask); + &rl_unsignedp, &rl_reversep, &volatilep, + &rl_mask, &rl_and_mask); rr_inner = decode_field_reference (loc, rr_arg, &rr_bitsize, &rr_bitpos, &rr_mode, - &rr_unsignedp, &volatilep, &rr_mask, - &rr_and_mask); + &rr_unsignedp, &rr_reversep, &volatilep, + &rr_mask, &rr_and_mask); /* It must be true that the inner operation on the lhs of each comparison must be the same if we are to be able to do anything. Then see if we have constants. If not, the same must be true for the rhs's. */ - if (volatilep || ll_inner == 0 || rl_inner == 0 + if (volatilep + || ll_reversep != rl_reversep + || ll_inner == 0 || rl_inner == 0 || ! operand_equal_p (ll_inner, rl_inner, 0)) return 0; if (TREE_CODE (lr_arg) == INTEGER_CST && TREE_CODE (rr_arg) == INTEGER_CST) - l_const = lr_arg, r_const = rr_arg; - else if (lr_inner == 0 || rr_inner == 0 + { + l_const = lr_arg, r_const = rr_arg; + lr_reversep = ll_reversep; + } + else if (lr_reversep != rr_reversep + || lr_inner == 0 || rr_inner == 0 || ! operand_equal_p (lr_inner, rr_inner, 0)) return 0; else @@ -5631,7 +5653,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type, lntype = lang_hooks.types.type_for_size (lnbitsize, 1); xll_bitpos = ll_bitpos - lnbitpos, xrl_bitpos = rl_bitpos - lnbitpos; - if (BYTES_BIG_ENDIAN) + if (ll_reversep ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN) { xll_bitpos = lnbitsize - xll_bitpos - ll_bitsize; xrl_bitpos = lnbitsize - xrl_bitpos - rl_bitsize; @@ -5696,7 +5718,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type, rntype = lang_hooks.types.type_for_size (rnbitsize, 1); xlr_bitpos = lr_bitpos - rnbitpos, xrr_bitpos = rr_bitpos - rnbitpos; - if (BYTES_BIG_ENDIAN) + if (lr_reversep ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN) { xlr_bitpos = rnbitsize - xlr_bitpos - lr_bitsize; xrr_bitpos = rnbitsize - xrr_bitpos - rr_bitsize; @@ -5719,12 +5741,12 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type, if (lnbitsize == rnbitsize && xll_bitpos == xlr_bitpos) { lhs = make_bit_field_ref (loc, ll_inner, lntype, lnbitsize, lnbitpos, - ll_unsignedp || rl_unsignedp); + ll_unsignedp || rl_unsignedp, ll_reversep); if (! all_ones_mask_p (ll_mask, lnbitsize)) lhs = build2 (BIT_AND_EXPR, lntype, lhs, ll_mask); rhs = make_bit_field_ref (loc, lr_inner, rntype, rnbitsize, rnbitpos, - lr_unsignedp || rr_unsignedp); + lr_unsignedp || rr_unsignedp, lr_reversep); if (! all_ones_mask_p (lr_mask, rnbitsize)) rhs = build2 (BIT_AND_EXPR, rntype, rhs, lr_mask); @@ -5747,10 +5769,12 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type, lhs = make_bit_field_ref (loc, ll_inner, lntype, ll_bitsize + rl_bitsize, - MIN (ll_bitpos, rl_bitpos), ll_unsignedp); + MIN (ll_bitpos, rl_bitpos), + ll_unsignedp, ll_reversep); rhs = make_bit_field_ref (loc, lr_inner, rntype, lr_bitsize + rr_bitsize, - MIN (lr_bitpos, rr_bitpos), lr_unsignedp); + MIN (lr_bitpos, rr_bitpos), + lr_unsignedp, lr_reversep); ll_mask = const_binop (RSHIFT_EXPR, ll_mask, size_int (MIN (xll_bitpos, xrl_bitpos))); @@ -5813,7 +5837,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type, that field, perform the mask operation. Then compare with the merged constant. */ result = make_bit_field_ref (loc, ll_inner, lntype, lnbitsize, lnbitpos, - ll_unsignedp || rl_unsignedp); + ll_unsignedp || rl_unsignedp, ll_reversep); ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask); if (! all_ones_mask_p (ll_mask, lnbitsize)) @@ -7677,10 +7701,11 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) HOST_WIDE_INT bitsize, bitpos; tree offset; machine_mode mode; - int unsignedp, volatilep; - tree base = TREE_OPERAND (op0, 0); - base = get_inner_reference (base, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + int unsignedp, reversep, volatilep; + tree base + = get_inner_reference (TREE_OPERAND (op0, 0), &bitsize, &bitpos, + &offset, &mode, &unsignedp, &reversep, + &volatilep, false); /* If the reference was to a (constant) zero offset, we can use the address of the base if it has the same base type as the result type and the pointer type is unqualified. */ @@ -7816,8 +7841,12 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) case VIEW_CONVERT_EXPR: if (TREE_CODE (op0) == MEM_REF) - return fold_build2_loc (loc, MEM_REF, type, - TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1)); + { + tem = fold_build2_loc (loc, MEM_REF, type, + TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1)); + REF_REVERSE_STORAGE_ORDER (tem) = REF_REVERSE_STORAGE_ORDER (op0); + return tem; + } return NULL_TREE; @@ -8334,7 +8363,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type, tree base0, base1, offset0 = NULL_TREE, offset1 = NULL_TREE; HOST_WIDE_INT bitsize, bitpos0 = 0, bitpos1 = 0; machine_mode mode; - int volatilep, unsignedp; + int volatilep, reversep, unsignedp; bool indirect_base0 = false, indirect_base1 = false; /* Get base and offset for the access. Strip ADDR_EXPR for @@ -8344,9 +8373,10 @@ fold_comparison (location_t loc, enum tree_code code, tree type, base0 = arg0; if (TREE_CODE (arg0) == ADDR_EXPR) { - base0 = get_inner_reference (TREE_OPERAND (arg0, 0), - &bitsize, &bitpos0, &offset0, &mode, - &unsignedp, &volatilep, false); + base0 + = get_inner_reference (TREE_OPERAND (arg0, 0), + &bitsize, &bitpos0, &offset0, &mode, + &unsignedp, &reversep, &volatilep, false); if (TREE_CODE (base0) == INDIRECT_REF) base0 = TREE_OPERAND (base0, 0); else @@ -8378,9 +8408,10 @@ fold_comparison (location_t loc, enum tree_code code, tree type, base1 = arg1; if (TREE_CODE (arg1) == ADDR_EXPR) { - base1 = get_inner_reference (TREE_OPERAND (arg1, 0), - &bitsize, &bitpos1, &offset1, &mode, - &unsignedp, &volatilep, false); + base1 + = get_inner_reference (TREE_OPERAND (arg1, 0), + &bitsize, &bitpos1, &offset1, &mode, + &unsignedp, &reversep, &volatilep, false); if (TREE_CODE (base1) == INDIRECT_REF) base1 = TREE_OPERAND (base1, 0); else @@ -14310,15 +14341,15 @@ split_address_to_core_and_offset (tree exp, { tree core; machine_mode mode; - int unsignedp, volatilep; + int unsignedp, reversep, volatilep; HOST_WIDE_INT bitsize; location_t loc = EXPR_LOCATION (exp); if (TREE_CODE (exp) == ADDR_EXPR) { core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos, - poffset, &mode, &unsignedp, &volatilep, - false); + poffset, &mode, &unsignedp, &reversep, + &volatilep, false); core = build_fold_addr_expr_loc (loc, core); } else @@ -14397,3 +14428,24 @@ fold_build_pointer_plus_hwi_loc (location_t loc, tree ptr, HOST_WIDE_INT off) return fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr, size_int (off)); } + +/* Return a char pointer for a C string if it is a string constant + or sum of string constant and integer constant. */ + +const char * +c_getstr (tree src) +{ + tree offset_node; + + src = string_constant (src, &offset_node); + if (src == 0) + return 0; + + if (offset_node == 0) + return TREE_STRING_POINTER (src); + else if (!tree_fits_uhwi_p (offset_node) + || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0) + return 0; + + return TREE_STRING_POINTER (src) + tree_to_uhwi (offset_node); +} diff --git a/gcc/fold-const.h b/gcc/fold-const.h index 97d18cf0e22..94a21b7652a 100644 --- a/gcc/fold-const.h +++ b/gcc/fold-const.h @@ -180,6 +180,7 @@ extern tree exact_inverse (tree, tree); extern tree const_unop (enum tree_code, tree, tree); extern tree const_binop (enum tree_code, tree, tree, tree); extern bool negate_mathfn_p (enum built_in_function); +extern const char *c_getstr (tree); /* Return OFF converted to a pointer offset type suitable as offset for POINTER_PLUS_EXPR. Use location LOC for this conversion. */ diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index bd3fa7647a5..cd4c94e6764 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,66 @@ +2015-11-08 Steven g. Kargl + + PR fortran/68053 + * decl.c (add_init_expr_to_sym): Try to reduce initialization expression + before testing for a constant value. + +2015-11-08 Andre Vehreschild + + PR fortran/68218 + * trans-array.c (gfc_array_init_size): Add gfc_evaluate_now() when + array spec in allocate is a function call. + +2015-11-08 Steven G. Kargl + + PR fortran/68224 + * array.c (match_array_element_spec): Check of invalid NULL(). + While here, fix nearby comments. + +2015-11-08 Paul Thomas + + PR fortran/68196 + * class.c (has_finalizer_component): Prevent infinite recursion + through this function if the derived type and that of its + component are the same. + * trans-types.c (gfc_get_derived_type): Do the same for proc + pointers by ignoring the explicit interface for the component. + + PR fortran/66465 + * check.c (same_type_check): If either of the expressions is + BT_PROCEDURE, use the typespec from the symbol, rather than the + expression. + +2015-11-07 Steven G. Kargl + + PR fortran/68153 + * check.c (gfc_check_reshape): Improve check for valid SHAPE argument. + +2015-11-07 Steven G. Kargl + + PR fortran/68151 + * match.c (match_case_selector): Check for invalid type. + +2015-11-06 David Malcolm + + * cpp.c (cb_cpp_error): Convert parameter from location_t to + rich_location *. Eliminate the "column_override" parameter. + * error.c (gfc_warning): Update for change in signature of + diagnostic_set_info. + (gfc_format_decoder): Update handling of %C/%L for changes + to struct text_info. + (gfc_diagnostic_starter): Use richloc when determining whether to + print one locus or two. When handling a location that will + involve a call to diagnostic_show_locus, only attempt to print the + locus for the primary location, and don't call into + diagnostic_print_caret_line. + (gfc_warning_now_at): Update for change in signature of + diagnostic_set_info. + (gfc_warning_now): Likewise. + (gfc_error_now): Likewise. + (gfc_fatal_error): Likewise. + (gfc_error): Likewise. + (gfc_internal_error): Likewise. + 2015-11-05 Cesar Philippidis * openmp.c (gfc_match_omp_clauses): Update support for the tile @@ -80,7 +143,7 @@ PR fortran/68154 * decl.c (add_init_expr_to_sym): if the char length in the typespec - is NULL, check for and use a constructor. + is NULL, check for and use a constructor. 2015-10-30 Steven G. Kargl diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c index 2083044774f..0b676af551e 100644 --- a/gcc/fortran/array.c +++ b/gcc/fortran/array.c @@ -147,9 +147,9 @@ matched: } -/* Match an array reference, whether it is the whole array or a - particular elements or a section. If init is set, the reference has - to consist of init expressions. */ +/* Match an array reference, whether it is the whole array or particular + elements or a section. If init is set, the reference has to consist + of init expressions. */ match gfc_match_array_ref (gfc_array_ref *ar, gfc_array_spec *as, int init, @@ -422,6 +422,13 @@ match_array_element_spec (gfc_array_spec *as) if (!gfc_expr_check_typed (*upper, gfc_current_ns, false)) return AS_UNKNOWN; + if ((*upper)->expr_type == EXPR_FUNCTION && (*upper)->ts.type == BT_UNKNOWN + && (*upper)->symtree && strcmp ((*upper)->symtree->name, "null") == 0) + { + gfc_error ("Expecting a scalar INTEGER expression at %C"); + return AS_UNKNOWN; + } + if (gfc_match_char (':') == MATCH_NO) { *lower = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1); @@ -442,13 +449,20 @@ match_array_element_spec (gfc_array_spec *as) if (!gfc_expr_check_typed (*upper, gfc_current_ns, false)) return AS_UNKNOWN; + if ((*upper)->expr_type == EXPR_FUNCTION && (*upper)->ts.type == BT_UNKNOWN + && (*upper)->symtree && strcmp ((*upper)->symtree->name, "null") == 0) + { + gfc_error ("Expecting a scalar INTEGER expression at %C"); + return AS_UNKNOWN; + } + return AS_EXPLICIT; } /* Matches an array specification, incidentally figuring out what sort - it is. Match either a normal array specification, or a coarray spec - or both. Optionally allow [:] for coarrays. */ + it is. Match either a normal array specification, or a coarray spec + or both. Optionally allow [:] for coarrays. */ match gfc_match_array_spec (gfc_array_spec **asp, bool match_dim, bool match_codim) diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c index 6548a017f44..038ee218d94 100644 --- a/gcc/fortran/check.c +++ b/gcc/fortran/check.c @@ -399,7 +399,15 @@ less_than_bitsize2 (const char *arg1, gfc_expr *expr1, const char *arg2, static bool same_type_check (gfc_expr *e, int n, gfc_expr *f, int m) { - if (gfc_compare_types (&e->ts, &f->ts)) + gfc_typespec *ets = &e->ts; + gfc_typespec *fts = &f->ts; + + if (e->ts.type == BT_PROCEDURE && e->symtree->n.sym) + ets = &e->symtree->n.sym->ts; + if (f->ts.type == BT_PROCEDURE && f->symtree->n.sym) + fts = &f->symtree->n.sym->ts; + + if (gfc_compare_types (ets, fts)) return true; gfc_error ("%qs argument of %qs intrinsic at %L must be the same type " @@ -3711,6 +3719,36 @@ gfc_check_reshape (gfc_expr *source, gfc_expr *shape, } } } + else if (shape->expr_type == EXPR_VARIABLE && shape->ref + && shape->ref->u.ar.type == AR_FULL && shape->ref->u.ar.dimen == 1 + && shape->ref->u.ar.as + && shape->ref->u.ar.as->lower[0]->expr_type == EXPR_CONSTANT + && shape->ref->u.ar.as->lower[0]->ts.type == BT_INTEGER + && shape->ref->u.ar.as->upper[0]->expr_type == EXPR_CONSTANT + && shape->ref->u.ar.as->upper[0]->ts.type == BT_INTEGER + && shape->symtree->n.sym->attr.flavor == FL_PARAMETER) + { + int i, extent; + gfc_expr *e, *v; + + v = shape->symtree->n.sym->value; + + for (i = 0; i < shape_size; i++) + { + e = gfc_constructor_lookup_expr (v->value.constructor, i); + if (e == NULL) + break; + + gfc_extract_int (e, &extent); + + if (extent < 0) + { + gfc_error ("Element %d of actual argument of RESHAPE at %L " + "cannot be negative", i + 1, &shape->where); + return false; + } + } + } if (pad != NULL) { diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c index 7a9e2755a0f..8b49ae95a20 100644 --- a/gcc/fortran/class.c +++ b/gcc/fortran/class.c @@ -843,7 +843,11 @@ has_finalizer_component (gfc_symbol *derived) && c->ts.u.derived->f2k_derived->finalizers) return true; + /* Stop infinite recursion through this function by inhibiting + calls when the derived type and that of the component are + the same. */ if (c->ts.type == BT_DERIVED + && !gfc_compare_derived_types (derived, c->ts.u.derived) && !c->attr.pointer && !c->attr.allocatable && has_finalizer_component (c->ts.u.derived)) return true; diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c index 7d296255b42..85a2c79cd70 100644 --- a/gcc/fortran/cpp.c +++ b/gcc/fortran/cpp.c @@ -147,9 +147,9 @@ static void cb_include (cpp_reader *, source_location, const unsigned char *, static void cb_ident (cpp_reader *, source_location, const cpp_string *); static void cb_used_define (cpp_reader *, source_location, cpp_hashnode *); static void cb_used_undef (cpp_reader *, source_location, cpp_hashnode *); -static bool cb_cpp_error (cpp_reader *, int, int, location_t, unsigned int, +static bool cb_cpp_error (cpp_reader *, int, int, rich_location *, const char *, va_list *) - ATTRIBUTE_GCC_DIAG(6,0); + ATTRIBUTE_GCC_DIAG(5,0); void pp_dir_change (cpp_reader *, const char *); static int dump_macro (cpp_reader *, cpp_hashnode *, void *); @@ -1024,13 +1024,12 @@ cb_used_define (cpp_reader *pfile, source_location line ATTRIBUTE_UNUSED, /* Callback from cpp_error for PFILE to print diagnostics from the preprocessor. The diagnostic is of type LEVEL, with REASON set to the reason code if LEVEL is represents a warning, at location - LOCATION, with column number possibly overridden by COLUMN_OVERRIDE - if not zero; MSG is the translated message and AP the arguments. + RICHLOC; MSG is the translated message and AP the arguments. Returns true if a diagnostic was emitted, false otherwise. */ static bool cb_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason, - location_t location, unsigned int column_override, + rich_location *richloc, const char *msg, va_list *ap) { diagnostic_info diagnostic; @@ -1065,9 +1064,7 @@ cb_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason, gcc_unreachable (); } diagnostic_set_info_translated (&diagnostic, msg, ap, - location, dlevel); - if (column_override) - diagnostic_override_column (&diagnostic, column_override); + richloc, dlevel); if (reason == CPP_W_WARNING_DIRECTIVE) diagnostic_override_option_index (&diagnostic, OPT_Wcpp); ret = report_diagnostic (&diagnostic); diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 7178aafe5e1..0c3377f7b08 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -1529,26 +1529,34 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus) for (dim = 0; dim < sym->as->rank; ++dim) { int k; - gfc_expr* lower; - gfc_expr* e; + gfc_expr *e, *lower; lower = sym->as->lower[dim]; - if (lower->expr_type != EXPR_CONSTANT) + + /* If the lower bound is an array element from another + parameterized array, then it is marked with EXPR_VARIABLE and + is an initialization expression. Try to reduce it. */ + if (lower->expr_type == EXPR_VARIABLE) + gfc_reduce_init_expr (lower); + + if (lower->expr_type == EXPR_CONSTANT) + { + /* All dimensions must be without upper bound. */ + gcc_assert (!sym->as->upper[dim]); + + k = lower->ts.kind; + e = gfc_get_constant_expr (BT_INTEGER, k, &sym->declared_at); + mpz_add (e->value.integer, lower->value.integer, + init->shape[dim]); + mpz_sub_ui (e->value.integer, e->value.integer, 1); + sym->as->upper[dim] = e; + } + else { gfc_error ("Non-constant lower bound in implied-shape" " declaration at %L", &lower->where); return false; } - - /* All dimensions must be without upper bound. */ - gcc_assert (!sym->as->upper[dim]); - - k = lower->ts.kind; - e = gfc_get_constant_expr (BT_INTEGER, k, &sym->declared_at); - mpz_add (e->value.integer, - lower->value.integer, init->shape[dim]); - mpz_sub_ui (e->value.integer, e->value.integer, 1); - sym->as->upper[dim] = e; } sym->as->type = AS_EXPLICIT; diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c index 3825751ddd0..4b3d31ce4ba 100644 --- a/gcc/fortran/error.c +++ b/gcc/fortran/error.c @@ -773,6 +773,7 @@ gfc_warning (int opt, const char *gmsgid, va_list ap) va_copy (argp, ap); diagnostic_info diagnostic; + rich_location rich_loc (UNKNOWN_LOCATION); bool fatal_errors = global_dc->fatal_errors; pretty_printer *pp = global_dc->printer; output_buffer *tmp_buffer = pp->buffer; @@ -787,7 +788,7 @@ gfc_warning (int opt, const char *gmsgid, va_list ap) --werrorcount; } - diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION, + diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_WARNING); diagnostic.option_index = opt; bool ret = report_diagnostic (&diagnostic); @@ -938,10 +939,12 @@ gfc_format_decoder (pretty_printer *pp, /* If location[0] != UNKNOWN_LOCATION means that we already processed one of %C/%L. */ int loc_num = text->get_location (0) == UNKNOWN_LOCATION ? 0 : 1; - text->set_location (loc_num, - linemap_position_for_loc_and_offset (line_table, - loc->lb->location, - offset)); + source_range range + = source_range::from_location ( + linemap_position_for_loc_and_offset (line_table, + loc->lb->location, + offset)); + text->set_range (loc_num, range, true); pp_string (pp, result[loc_num]); return true; } @@ -1024,48 +1027,21 @@ gfc_diagnostic_build_locus_prefix (diagnostic_context *context, } /* This function prints the locus (file:line:column), the diagnostic kind - (Error, Warning) and (optionally) the caret line (a source line - with '1' and/or '2' below it). + (Error, Warning) and (optionally) the relevant lines of code with + annotation lines with '1' and/or '2' below them. - With -fdiagnostic-show-caret (the default) and for valid locations, - it prints for one location: + With -fdiagnostic-show-caret (the default) it prints: - [locus]: + [locus of primary range]: some code 1 Error: Some error at (1) - for two locations that fit in the same locus line: + With -fno-diagnostic-show-caret or if the primary range is not + valid, it prints: - [locus]: - - some code and some more code - 1 2 - Error: Some error at (1) and (2) - - and for two locations that do not fit in the same locus line: - - [locus]: - - some code - 1 - [locus2]: - - some other code - 2 - Error: Some error at (1) and (2) - - With -fno-diagnostic-show-caret or if one of the locations is not - valid, it prints for one location (or for two locations that fit in - the same locus line): - - [locus]: Error: Some error at (1) and (2) - - and for two locations that do not fit in the same locus line: - - [name]:[locus]: Error: (1) - [name]:[locus2]: Error: Some error at (1) and (2) + [locus of primary range]: Error: Some error at (1) and (2) */ static void gfc_diagnostic_starter (diagnostic_context *context, @@ -1075,7 +1051,7 @@ gfc_diagnostic_starter (diagnostic_context *context, expanded_location s1 = diagnostic_expand_location (diagnostic); expanded_location s2; - bool one_locus = diagnostic_location (diagnostic, 1) == UNKNOWN_LOCATION; + bool one_locus = diagnostic->richloc->get_num_locations () < 2; bool same_locus = false; if (!one_locus) @@ -1125,35 +1101,6 @@ gfc_diagnostic_starter (diagnostic_context *context, /* If the caret line was shown, the prefix does not contain the locus. */ pp_set_prefix (context->printer, kind_prefix); - - if (one_locus || same_locus) - return; - - locus_prefix = gfc_diagnostic_build_locus_prefix (context, s2); - if (diagnostic_location (diagnostic, 1) <= BUILTINS_LOCATION) - { - /* No caret line for the second location. Override the previous - prefix with [locus2]:[prefix]. */ - pp_set_prefix (context->printer, - concat (locus_prefix, " ", kind_prefix, NULL)); - free (kind_prefix); - free (locus_prefix); - } - else - { - /* We print the caret for the second location. */ - pp_verbatim (context->printer, locus_prefix); - free (locus_prefix); - /* Fortran uses an empty line between locus and caret line. */ - pp_newline (context->printer); - s1.column = 0; /* Print only a caret line for s2. */ - diagnostic_print_caret_line (context, s2, s1, - context->caret_chars[1], '\0'); - pp_newline (context->printer); - /* If the caret line was shown, the prefix does not contain the - locus. */ - pp_set_prefix (context->printer, kind_prefix); - } } } @@ -1173,10 +1120,11 @@ gfc_warning_now_at (location_t loc, int opt, const char *gmsgid, ...) { va_list argp; diagnostic_info diagnostic; + rich_location rich_loc (loc); bool ret; va_start (argp, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &argp, loc, DK_WARNING); + diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_WARNING); diagnostic.option_index = opt; ret = report_diagnostic (&diagnostic); va_end (argp); @@ -1190,10 +1138,11 @@ gfc_warning_now (int opt, const char *gmsgid, ...) { va_list argp; diagnostic_info diagnostic; + rich_location rich_loc (UNKNOWN_LOCATION); bool ret; va_start (argp, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION, + diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_WARNING); diagnostic.option_index = opt; ret = report_diagnostic (&diagnostic); @@ -1209,11 +1158,12 @@ gfc_error_now (const char *gmsgid, ...) { va_list argp; diagnostic_info diagnostic; + rich_location rich_loc (UNKNOWN_LOCATION); error_buffer.flag = true; va_start (argp, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION, DK_ERROR); + diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_ERROR); report_diagnostic (&diagnostic); va_end (argp); } @@ -1226,9 +1176,10 @@ gfc_fatal_error (const char *gmsgid, ...) { va_list argp; diagnostic_info diagnostic; + rich_location rich_loc (UNKNOWN_LOCATION); va_start (argp, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION, DK_FATAL); + diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_FATAL); report_diagnostic (&diagnostic); va_end (argp); @@ -1291,6 +1242,7 @@ gfc_error (const char *gmsgid, va_list ap) } diagnostic_info diagnostic; + rich_location richloc (UNKNOWN_LOCATION); bool fatal_errors = global_dc->fatal_errors; pretty_printer *pp = global_dc->printer; output_buffer *tmp_buffer = pp->buffer; @@ -1306,7 +1258,7 @@ gfc_error (const char *gmsgid, va_list ap) --errorcount; } - diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION, DK_ERROR); + diagnostic_set_info (&diagnostic, gmsgid, &argp, &richloc, DK_ERROR); report_diagnostic (&diagnostic); if (buffered_p) @@ -1336,9 +1288,10 @@ gfc_internal_error (const char *gmsgid, ...) { va_list argp; diagnostic_info diagnostic; + rich_location rich_loc (UNKNOWN_LOCATION); va_start (argp, gmsgid); - diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION, DK_ICE); + diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_ICE); report_diagnostic (&diagnostic); va_end (argp); diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c index 7abb5dee4a9..2844262e0f2 100644 --- a/gcc/fortran/match.c +++ b/gcc/fortran/match.c @@ -5018,7 +5018,9 @@ gfc_free_case_list (gfc_case *p) } -/* Match a single case selector. */ +/* Match a single case selector. Combining the requirements of F08:C830 + and F08:C832 (R838) means that the case-value must have either CHARACTER, + INTEGER, or LOGICAL type. */ static match match_case_selector (gfc_case **cp) @@ -5036,6 +5038,14 @@ match_case_selector (gfc_case **cp) goto need_expr; if (m == MATCH_ERROR) goto cleanup; + + if (c->high->ts.type != BT_LOGICAL && c->high->ts.type != BT_INTEGER + && c->high->ts.type != BT_CHARACTER) + { + gfc_error ("Expression in CASE selector at %L cannot be %s", + &c->high->where, gfc_typename (&c->high->ts)); + goto cleanup; + } } else { @@ -5045,6 +5055,14 @@ match_case_selector (gfc_case **cp) if (m == MATCH_NO) goto need_expr; + if (c->low->ts.type != BT_LOGICAL && c->low->ts.type != BT_INTEGER + && c->low->ts.type != BT_CHARACTER) + { + gfc_error ("Expression in CASE selector at %L cannot be %s", + &c->low->where, gfc_typename (&c->low->ts)); + goto cleanup; + } + /* If we're not looking at a ':' now, make a range out of a single target. Else get the upper bound for the case range. */ if (gfc_match_char (':') != MATCH_YES) diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 6bbf8cc6279..e28a5ce3c0b 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -5150,6 +5150,8 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset, gcc_assert (ubound); gfc_conv_expr_type (&se, ubound, gfc_array_index_type); gfc_add_block_to_block (pblock, &se.pre); + if (ubound->expr_type == EXPR_FUNCTION) + se.expr = gfc_evaluate_now (se.expr, pblock); } gfc_conv_descriptor_ubound_set (descriptor_block, descriptor, gfc_rank_cst[n], se.expr); diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c index 780200e5f5d..ad6cee87606 100644 --- a/gcc/fortran/trans-types.c +++ b/gcc/fortran/trans-types.c @@ -2366,6 +2366,7 @@ gfc_get_derived_type (gfc_symbol * derived) gfc_component *c; gfc_dt_list *dt; gfc_namespace *ns; + tree tmp; if (derived->attr.unlimited_polymorphic || (flag_coarray == GFC_FCOARRAY_LIB @@ -2517,8 +2518,19 @@ gfc_get_derived_type (gfc_symbol * derived) node as DECL_CONTEXT of each FIELD_DECL. */ for (c = derived->components; c; c = c->next) { - if (c->attr.proc_pointer) + /* Prevent infinite recursion, when the procedure pointer type is + the same as derived, by forcing the procedure pointer component to + be built as if the explicit interface does not exist. */ + if (c->attr.proc_pointer + && ((c->ts.type != BT_DERIVED && c->ts.type != BT_CLASS) + || (c->ts.u.derived + && !gfc_compare_derived_types (derived, c->ts.u.derived)))) field_type = gfc_get_ppc_type (c); + else if (c->attr.proc_pointer && derived->backend_decl) + { + tmp = build_function_type_list (derived->backend_decl, NULL_TREE); + field_type = build_pointer_type (tmp); + } else if (c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS) field_type = c->ts.u.derived->backend_decl; else diff --git a/gcc/function.c b/gcc/function.c index 0d7cabc1d4c..a637cb39142 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -2879,6 +2879,7 @@ assign_parm_setup_block (struct assign_parm_data_all *all, rtx entry_parm = data->entry_parm; rtx stack_parm = data->stack_parm; rtx target_reg = NULL_RTX; + bool in_conversion_seq = false; HOST_WIDE_INT size; HOST_WIDE_INT size_stored; @@ -2895,9 +2896,23 @@ assign_parm_setup_block (struct assign_parm_data_all *all, if (GET_CODE (reg) != CONCAT) stack_parm = reg; else - /* This will use or allocate a stack slot that we'd rather - avoid. FIXME: Could we avoid it in more cases? */ - target_reg = reg; + { + target_reg = reg; + /* Avoid allocating a stack slot, if there isn't one + preallocated by the ABI. It might seem like we should + always prefer a pseudo, but converting between + floating-point and integer modes goes through the stack + on various machines, so it's better to use the reserved + stack slot than to risk wasting it and allocating more + for the conversion. */ + if (stack_parm == NULL_RTX) + { + int save = generating_concat_p; + generating_concat_p = 0; + stack_parm = gen_reg_rtx (mode); + generating_concat_p = save; + } + } data->stack_parm = NULL; } @@ -2938,7 +2953,9 @@ assign_parm_setup_block (struct assign_parm_data_all *all, mem = validize_mem (copy_rtx (stack_parm)); /* Handle values in multiple non-contiguous locations. */ - if (GET_CODE (entry_parm) == PARALLEL) + if (GET_CODE (entry_parm) == PARALLEL && !MEM_P (mem)) + emit_group_store (mem, entry_parm, data->passed_type, size); + else if (GET_CODE (entry_parm) == PARALLEL) { push_to_sequence2 (all->first_conversion_insn, all->last_conversion_insn); @@ -2946,6 +2963,7 @@ assign_parm_setup_block (struct assign_parm_data_all *all, all->first_conversion_insn = get_insns (); all->last_conversion_insn = get_last_insn (); end_sequence (); + in_conversion_seq = true; } else if (size == 0) @@ -3025,11 +3043,22 @@ assign_parm_setup_block (struct assign_parm_data_all *all, all->first_conversion_insn = get_insns (); all->last_conversion_insn = get_last_insn (); end_sequence (); + in_conversion_seq = true; } if (target_reg) { - emit_move_insn (target_reg, stack_parm); + if (!in_conversion_seq) + emit_move_insn (target_reg, stack_parm); + else + { + push_to_sequence2 (all->first_conversion_insn, + all->last_conversion_insn); + emit_move_insn (target_reg, stack_parm); + all->first_conversion_insn = get_insns (); + all->last_conversion_insn = get_last_insn (); + end_sequence (); + } stack_parm = target_reg; } diff --git a/gcc/genmatch.c b/gcc/genmatch.c index b5a0fffa714..1eb8c24da7d 100644 --- a/gcc/genmatch.c +++ b/gcc/genmatch.c @@ -53,14 +53,31 @@ unsigned verbose; static struct line_maps *line_table; +/* The rich_location class within libcpp requires a way to expand + source_location instances, and relies on the client code + providing a symbol named + linemap_client_expand_location_to_spelling_point + to do this. + + This is the implementation for genmatch. */ + +expanded_location +linemap_client_expand_location_to_spelling_point (source_location loc) +{ + const struct line_map_ordinary *map; + loc = linemap_resolve_location (line_table, loc, LRK_SPELLING_LOCATION, &map); + return linemap_expand_location (line_table, map, loc); +} + static bool #if GCC_VERSION >= 4001 -__attribute__((format (printf, 6, 0))) +__attribute__((format (printf, 5, 0))) #endif -error_cb (cpp_reader *, int errtype, int, source_location location, - unsigned int, const char *msg, va_list *ap) +error_cb (cpp_reader *, int errtype, int, rich_location *richloc, + const char *msg, va_list *ap) { const line_map_ordinary *map; + source_location location = richloc->get_loc (); linemap_resolve_location (line_table, location, LRK_SPELLING_LOCATION, &map); expanded_location loc = linemap_expand_location (line_table, map, location); fprintf (stderr, "%s:%d:%d %s: ", loc.file, loc.line, loc.column, @@ -102,9 +119,10 @@ __attribute__((format (printf, 2, 3))) #endif fatal_at (const cpp_token *tk, const char *msg, ...) { + rich_location richloc (tk->src_loc); va_list ap; va_start (ap, msg); - error_cb (NULL, CPP_DL_FATAL, 0, tk->src_loc, 0, msg, &ap); + error_cb (NULL, CPP_DL_FATAL, 0, &richloc, msg, &ap); va_end (ap); } @@ -114,9 +132,10 @@ __attribute__((format (printf, 2, 3))) #endif fatal_at (source_location loc, const char *msg, ...) { + rich_location richloc (loc); va_list ap; va_start (ap, msg); - error_cb (NULL, CPP_DL_FATAL, 0, loc, 0, msg, &ap); + error_cb (NULL, CPP_DL_FATAL, 0, &richloc, msg, &ap); va_end (ap); } @@ -126,9 +145,10 @@ __attribute__((format (printf, 2, 3))) #endif warning_at (const cpp_token *tk, const char *msg, ...) { + rich_location richloc (tk->src_loc); va_list ap; va_start (ap, msg); - error_cb (NULL, CPP_DL_WARNING, 0, tk->src_loc, 0, msg, &ap); + error_cb (NULL, CPP_DL_WARNING, 0, &richloc, msg, &ap); va_end (ap); } @@ -138,9 +158,10 @@ __attribute__((format (printf, 2, 3))) #endif warning_at (source_location loc, const char *msg, ...) { + rich_location richloc (loc); va_list ap; va_start (ap, msg); - error_cb (NULL, CPP_DL_WARNING, 0, loc, 0, msg, &ap); + error_cb (NULL, CPP_DL_WARNING, 0, &richloc, msg, &ap); va_end (ap); } @@ -208,7 +229,6 @@ enum built_in_function { #include "builtins.def" END_BUILTINS }; -#undef DEF_BUILTIN /* Return true if CODE represents a commutative tree code. Otherwise return false. */ @@ -4598,7 +4618,6 @@ add_operator (VIEW_CONVERT2, "VIEW_CONVERT2", "tcc_unary", 1); #define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND) \ add_builtin (ENUM, # ENUM); #include "builtins.def" -#undef DEF_BUILTIN /* Parse ahead! */ parser p (r); diff --git a/gcc/gensupport.c b/gcc/gensupport.c index 0480e17fac3..484ead2f3e7 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -2253,7 +2253,7 @@ htab_eq_string (const void *s1, const void *s2) and a permanent heap copy of STR is created. */ static void -add_mnemonic_string (htab_t mnemonic_htab, const char *str, int len) +add_mnemonic_string (htab_t mnemonic_htab, const char *str, size_t len) { char *new_str; void **slot; @@ -2306,7 +2306,7 @@ gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn) for (i = 0; *cp; ) { const char *ep, *sp; - int size = 0; + size_t size = 0; while (ISSPACE (*cp)) cp++; @@ -2333,8 +2333,7 @@ gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn) { /* Don't set a value if there are more than one instruction in the string. */ - obstack_next_free (&string_obstack) = - obstack_next_free (&string_obstack) - size; + obstack_blank_fast (&string_obstack, -size); size = 0; cp = sp; @@ -2346,7 +2345,7 @@ gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn) obstack_1grow (&string_obstack, '*'); else add_mnemonic_string (mnemonic_htab, - obstack_next_free (&string_obstack) - size, + (char *) obstack_next_free (&string_obstack) - size, size); i++; } diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c index dd2550a71c3..e9c631d884d 100644 --- a/gcc/gimple-expr.c +++ b/gcc/gimple-expr.c @@ -152,14 +152,16 @@ useless_type_conversion_p (tree outer_type, tree inner_type) else if (TREE_CODE (inner_type) == ARRAY_TYPE && TREE_CODE (outer_type) == ARRAY_TYPE) { - /* Preserve string attributes. */ + /* Preserve various attributes. */ + if (TYPE_REVERSE_STORAGE_ORDER (inner_type) + != TYPE_REVERSE_STORAGE_ORDER (outer_type)) + return false; if (TYPE_STRING_FLAG (inner_type) != TYPE_STRING_FLAG (outer_type)) return false; /* Conversions from array types with unknown extent to array types with known extent are not useless. */ - if (!TYPE_DOMAIN (inner_type) - && TYPE_DOMAIN (outer_type)) + if (!TYPE_DOMAIN (inner_type) && TYPE_DOMAIN (outer_type)) return false; /* Nor are conversions from array types with non-constant size to diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 45840af22d9..fc095eb5bfc 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -782,13 +782,14 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi, HOST_WIDE_INT src_offset = 0, dest_offset = 0; HOST_WIDE_INT size = -1; HOST_WIDE_INT maxsize = -1; + bool reverse; srcvar = TREE_OPERAND (src, 0); src_base = get_ref_base_and_extent (srcvar, &src_offset, - &size, &maxsize); + &size, &maxsize, &reverse); destvar = TREE_OPERAND (dest, 0); dest_base = get_ref_base_and_extent (destvar, &dest_offset, - &size, &maxsize); + &size, &maxsize, &reverse); if (tree_fits_uhwi_p (len)) maxsize = tree_to_uhwi (len); else @@ -5264,6 +5265,8 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset, tree (*valueize)(tree)) { HOST_WIDE_INT bit_offset2, size, max_size; + bool reverse; + if (TREE_CODE (base) == MEM_REF) { if (!integer_zerop (TREE_OPERAND (base, 1))) @@ -5304,7 +5307,8 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset, case ARRAY_REF: case COMPONENT_REF: - base = get_ref_base_and_extent (base, &bit_offset2, &size, &max_size); + base = get_ref_base_and_extent (base, &bit_offset2, &size, &max_size, + &reverse); if (max_size == -1 || size != max_size) return NULL_TREE; *bit_offset += bit_offset2; @@ -5507,6 +5511,7 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree)) tree ctor, idx, base; HOST_WIDE_INT offset, size, max_size; tree tem; + bool reverse; if (TREE_THIS_VOLATILE (t)) return NULL_TREE; @@ -5577,7 +5582,7 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree)) case BIT_FIELD_REF: case TARGET_MEM_REF: case MEM_REF: - base = get_ref_base_and_extent (t, &offset, &size, &max_size); + base = get_ref_base_and_extent (t, &offset, &size, &max_size, &reverse); ctor = get_base_constructor (base, &offset, valueize); /* Empty constructor. Always fold to 0. */ diff --git a/gcc/gimple-laddress.c b/gcc/gimple-laddress.c index ba9198e921a..c2826dff419 100644 --- a/gcc/gimple-laddress.c +++ b/gcc/gimple-laddress.c @@ -102,10 +102,10 @@ pass_laddress::execute (function *fun) HOST_WIDE_INT bitsize, bitpos; tree base, offset; machine_mode mode; - int volatilep = 0, unsignedp = 0; + int volatilep = 0, reversep, unsignedp = 0; base = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos, &offset, &mode, &unsignedp, - &volatilep, false); + &reversep, &volatilep, false); gcc_assert (base != NULL_TREE && (bitpos % BITS_PER_UNIT) == 0); if (offset != NULL_TREE) { diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c index 0e52a86153f..ce32ad33e94 100644 --- a/gcc/gimple-ssa-strength-reduction.c +++ b/gcc/gimple-ssa-strength-reduction.c @@ -972,7 +972,7 @@ slsr_process_ref (gimple *gs) tree ref_expr, base, offset, type; HOST_WIDE_INT bitsize, bitpos; machine_mode mode; - int unsignedp, volatilep; + int unsignedp, reversep, volatilep; slsr_cand_t c; if (gimple_vdef (gs)) @@ -987,7 +987,9 @@ slsr_process_ref (gimple *gs) return; base = get_inner_reference (ref_expr, &bitsize, &bitpos, &offset, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &reversep, &volatilep, false); + if (reversep) + return; widest_int index = bitpos; if (!restructure_reference (&base, &offset, &index, &type)) diff --git a/gcc/gimple.c b/gcc/gimple.c index 4ce38dadf2f..706b126e5bb 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-iterator.h" #include "gimple-walk.h" #include "gimplify.h" +#include "target.h" /* All the tuples have their operand vector (if present) at the very bottom @@ -2624,9 +2625,15 @@ nonfreeing_call_p (gimple *call) static bool check_loadstore (gimple *, tree op, tree, void *data) { - if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF) - && operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0)) - return true; + if (TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF) + { + /* Some address spaces may legitimately dereference zero. */ + addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (op)); + if (targetm.addr_space.zero_address_valid (as)) + return false; + + return operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0); + } return false; } diff --git a/gcc/gimplify.c b/gcc/gimplify.c index fa348585a24..287e51e2016 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -6613,14 +6613,14 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, tree offset; HOST_WIDE_INT bitsize, bitpos; machine_mode mode; - int unsignedp, volatilep = 0; + int unsignedp, reversep, volatilep = 0; tree base = OMP_CLAUSE_DECL (c); while (TREE_CODE (base) == ARRAY_REF) base = TREE_OPERAND (base, 0); if (TREE_CODE (base) == INDIRECT_REF) base = TREE_OPERAND (base, 0); base = get_inner_reference (base, &bitsize, &bitpos, &offset, - &mode, &unsignedp, + &mode, &unsignedp, &reversep, &volatilep, false); gcc_assert (base == decl && (offset == NULL_TREE @@ -6730,7 +6730,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, base = get_inner_reference (base, &bitsize2, &bitpos2, &offset2, &mode, &unsignedp, - &volatilep, false); + &reversep, &volatilep, + false); if (base != decl) break; if (scp) @@ -9259,9 +9260,9 @@ gimplify_omp_ordered (tree expr, gimple_seq body) || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)) { error_at (OMP_CLAUSE_LOCATION (c), - "% clause must be closely nested " - "inside a loop with % clause with " - "a parameter"); + "% construct with % clause must be " + "closely nested inside a loop with % clause " + "with a parameter"); failures++; } else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND @@ -9734,6 +9735,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, TREE_OPERAND (*expr_p, 1)); if (tmp) { + REF_REVERSE_STORAGE_ORDER (tmp) + = REF_REVERSE_STORAGE_ORDER (*expr_p); *expr_p = tmp; recalculate_side_effects (*expr_p); ret = GS_OK; diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index dc042d91656..f325bb33ecb 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -47f256e1ed527b2eb4041acf90d33e6abc5e1685 +012ab5cb2ef1c26e8023ce90d3a2bba174da7b30 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/graphite-optimize-isl.c b/gcc/graphite-optimize-isl.c index 53355bb57dc..c09264bf093 100644 --- a/gcc/graphite-optimize-isl.c +++ b/gcc/graphite-optimize-isl.c @@ -404,7 +404,7 @@ optimize_isl (scop_p scop) isl_options_set_schedule_maximize_band_depth (scop->isl_context, 1); #ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS /* ISL-0.15 or later. */ - isl_options_set_schedule_serialize_sccs (scop->isl_context, 1); + isl_options_set_schedule_maximize_band_depth (scop->isl_context, 1); #else isl_options_set_schedule_fuse (scop->isl_context, ISL_SCHEDULE_FUSE_MIN); #endif @@ -441,11 +441,23 @@ optimize_isl (scop_p scop) #else isl_union_map *schedule_map = get_schedule_map (schedule); #endif - apply_schedule_map_to_scop (scop, schedule_map); - isl_schedule_free (schedule); - isl_union_map_free (schedule_map); - return true; + if (isl_union_map_is_equal (scop->original_schedule, schedule_map)) + { + if (dump_file && dump_flags) + fprintf (dump_file, "\nISL schedule same as original schedule\n"); + + isl_schedule_free (schedule); + isl_union_map_free (schedule_map); + return false; + } + else + { + apply_schedule_map_to_scop (scop, schedule_map); + isl_schedule_free (schedule); + isl_union_map_free (schedule_map); + return true; + } } #endif /* HAVE_isl */ diff --git a/gcc/graphite-poly.c b/gcc/graphite-poly.c index 2aa40c055d8..36c3061f618 100644 --- a/gcc/graphite-poly.c +++ b/gcc/graphite-poly.c @@ -305,6 +305,7 @@ new_scop (edge entry, edge exit) scop->must_waw_no_source = NULL; scop->may_waw_no_source = NULL; scop_set_region (scop, region); + scop->original_schedule = NULL; scop->pbbs.create (3); scop->poly_scop_p = false; scop->drs.create (3); @@ -341,6 +342,7 @@ free_scop (scop_p scop) isl_union_map_free (scop->may_waw); isl_union_map_free (scop->must_waw_no_source); isl_union_map_free (scop->may_waw_no_source); + isl_union_map_free (scop->original_schedule); XDELETE (scop); } diff --git a/gcc/graphite-poly.h b/gcc/graphite-poly.h index 5298f8547f9..b35431ae59d 100644 --- a/gcc/graphite-poly.h +++ b/gcc/graphite-poly.h @@ -436,6 +436,9 @@ struct scop *must_war, *may_war, *must_war_no_source, *may_war_no_source, *must_waw, *may_waw, *must_waw_no_source, *may_waw_no_source; + /* Original schedule of the SCoP. */ + isl_union_map *original_schedule; + /* True when the scop has been converted to its polyhedral representation. */ bool poly_scop_p; diff --git a/gcc/graphite-scop-detection.c b/gcc/graphite-scop-detection.c index ae8497db79d..9fb82645501 100644 --- a/gcc/graphite-scop-detection.c +++ b/gcc/graphite-scop-detection.c @@ -794,7 +794,8 @@ scop_detection::merge_sese (sese_l first, sese_l second) const get_entry_bb (second)); edge entry = get_nearest_dom_with_single_entry (dom); - if (!entry) + + if (!entry || (entry->flags & EDGE_IRREDUCIBLE_LOOP)) return invalid_sese; basic_block pdom = nearest_common_dominator (CDI_POST_DOMINATORS, @@ -803,7 +804,8 @@ scop_detection::merge_sese (sese_l first, sese_l second) const pdom = nearest_common_dominator (CDI_POST_DOMINATORS, dom, pdom); edge exit = get_nearest_pdom_with_single_exit (pdom); - if (!exit) + + if (!exit || (exit->flags & EDGE_IRREDUCIBLE_LOOP)) return invalid_sese; sese_l combined (entry, exit); @@ -923,6 +925,7 @@ scop_detection::can_represent_loop_1 (loop_p loop, sese_l scop) struct tree_niter_desc niter_desc; return single_exit (loop) + && !(loop_preheader_edge (loop)->flags & EDGE_IRREDUCIBLE_LOOP) && number_of_iterations_exit (loop, single_exit (loop), &niter_desc, false) && niter_desc.control.no_overflow && (niter = number_of_latch_executions (loop)) @@ -956,6 +959,13 @@ scop_detection::loop_is_valid_scop (loop_p loop, sese_l scop) const if (!scop) return false; + if (!optimize_loop_nest_for_speed_p (loop)) + { + DEBUG_PRINT (dp << "[scop-detection-fail] loop_" + << loop->num << " is not on a hot path.\n"); + return false; + } + if (!can_represent_loop (loop, scop)) { DEBUG_PRINT (dp << "[scop-detection-fail] cannot represent loop_" @@ -1053,6 +1063,10 @@ scop_detection::harmful_stmt_in_region (sese_l scop) const if (!dominated_by_p (CDI_POST_DOMINATORS, bb, exit_bb)) continue; + /* The basic block should not be part of an irreducible loop. */ + if (bb->flags & BB_IRREDUCIBLE_LOOP) + return true; + if (harmful_stmt_in_bb (scop, bb)) return true; } diff --git a/gcc/graphite-sese-to-poly.c b/gcc/graphite-sese-to-poly.c index fa33c50a533..ba45199a02a 100644 --- a/gcc/graphite-sese-to-poly.c +++ b/gcc/graphite-sese-to-poly.c @@ -231,51 +231,78 @@ isl_id_for_pbb (scop_p s, poly_bb_p pbb) | 0 0 1 0 0 0 0 0 -5 = 0 */ static void -build_pbb_scattering_polyhedrons (isl_aff *static_sched, - poly_bb_p pbb) +build_pbb_minimal_scattering_polyhedrons (isl_aff *static_sched, poly_bb_p pbb, + int *sequence_dims, + int nb_sequence_dim) { - isl_val *val; + int local_dim = isl_set_dim (pbb->domain, isl_dim_set); + + /* Remove a sequence dimension if irrelevant to domain of current pbb. */ + int actual_nb_dim = 0; + for (int i = 0; i < nb_sequence_dim; i++) + if (sequence_dims[i] <= local_dim) + actual_nb_dim++; + + /* Build an array that combines sequence dimensions and loops dimensions info. + This is used later to compute the static scattering polyhedrons. */ + bool *sequence_and_loop_dims = NULL; + if (local_dim + actual_nb_dim > 0) + { + sequence_and_loop_dims = XNEWVEC (bool, local_dim + actual_nb_dim); - int scattering_dimensions = isl_set_dim (pbb->domain, isl_dim_set) * 2 + 1; + int i = 0, j = 0; + for (; i < local_dim; i++) + { + if (sequence_dims && sequence_dims[j] == i) + { + /* True for sequence dimension. */ + sequence_and_loop_dims[i + j] = true; + j++; + } + /* False for loop dimension. */ + sequence_and_loop_dims[i + j] = false; + } + /* Fake loops make things shifted by one. */ + if (sequence_dims && sequence_dims[j] == i) + sequence_and_loop_dims[i + j] = true; + } + int scattering_dimensions = local_dim + actual_nb_dim; isl_space *dc = isl_set_get_space (pbb->domain); - isl_space *dm = isl_space_add_dims (isl_space_from_domain (dc), - isl_dim_out, scattering_dimensions); + isl_space *dm = isl_space_add_dims (isl_space_from_domain (dc), isl_dim_out, + scattering_dimensions); pbb->schedule = isl_map_universe (dm); + int k = 0; for (int i = 0; i < scattering_dimensions; i++) { - /* Textual order inside this loop. */ - if ((i % 2) == 0) - { - isl_constraint *c = isl_equality_alloc - (isl_local_space_from_space (isl_map_get_space (pbb->schedule))); - - val = isl_aff_get_coefficient_val (static_sched, isl_dim_in, i / 2); - gcc_assert (val && isl_val_is_int (val)); - - val = isl_val_neg (val); - c = isl_constraint_set_constant_val (c, val); - c = isl_constraint_set_coefficient_si (c, isl_dim_out, i, 1); - pbb->schedule = isl_map_add_constraint (pbb->schedule, c); - } - - /* Iterations of this loop. */ - else /* if ((i % 2) == 1) */ + if (!sequence_and_loop_dims[i]) { - int loop = (i - 1) / 2; - pbb->schedule = isl_map_equate (pbb->schedule, isl_dim_in, loop, + /* Iterations of this loop - loop dimension. */ + pbb->schedule = isl_map_equate (pbb->schedule, isl_dim_in, k, isl_dim_out, i); + k++; + continue; } + + /* Textual order inside this loop - sequence dimension. */ + isl_space *s = isl_map_get_space (pbb->schedule); + isl_local_space *ls = isl_local_space_from_space (s); + isl_constraint *c = isl_equality_alloc (ls); + isl_val *val = isl_aff_get_coefficient_val (static_sched, isl_dim_in, k); + gcc_assert (val && isl_val_is_int (val)); + val = isl_val_neg (val); + c = isl_constraint_set_constant_val (c, val); + c = isl_constraint_set_coefficient_si (c, isl_dim_out, i, 1); + pbb->schedule = isl_map_add_constraint (pbb->schedule, c); } + XDELETEVEC (sequence_and_loop_dims); pbb->transformed = isl_map_copy (pbb->schedule); } -/* Build for BB the static schedule. - - The static schedule is a Dewey numbering of the abstract syntax - tree: http://en.wikipedia.org/wiki/Dewey_Decimal_Classification +/* Build the static schedule for BB. This function minimizes the number of + dimensions used for pbb sequences. The following example informally defines the static schedule: @@ -283,40 +310,94 @@ build_pbb_scattering_polyhedrons (isl_aff *static_sched, for (i: ...) { for (j: ...) - { - B - C - } - + { + B + C + } + } + for (i: ...) + { for (k: ...) - { - D - E - } + { + D + E + } } F Static schedules for A to F: - DEPTH - 0 1 2 - A 0 - B 1 0 0 - C 1 0 1 - D 1 1 0 - E 1 1 1 - F 2 + A (0) + B (1 i0 i1 0) + C (1 i0 i1 1) + D (2 i0 i1 2) + E (2 i0 i1 3) + F (3) */ static void -build_scop_scattering (scop_p scop) +build_scop_minimal_scattering (scop_p scop) { gimple_poly_bb_p previous_gbb = NULL; - isl_space *dc = isl_set_get_space (scop->param_context); - isl_aff *static_sched; + int *temp_for_sequence_dims = NULL; + int i; + poly_bb_p pbb; + + /* Go through the pbbs to determine the minimum number of dimensions needed to + build the static schedule. */ + int nb_dims = 0; + FOR_EACH_VEC_ELT (scop->pbbs, i, pbb) + { + int dim = isl_set_dim (pbb->domain, isl_dim_set); + if (dim > nb_dims) + nb_dims = dim; + } + + /* One extra dimension for the outer fake loop. */ + nb_dims++; + temp_for_sequence_dims = XCNEWVEC (int, nb_dims); + + /* Record the number of common loops for each dimension. */ + FOR_EACH_VEC_ELT (scop->pbbs, i, pbb) + { + gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb); + int prefix = 0; + if (previous_gbb) + { + prefix = nb_common_loops (scop->scop_info->region, previous_gbb, gbb); + temp_for_sequence_dims[prefix] += 1; + } + previous_gbb = gbb; + } + + /* Analyze the info in temp_for_sequence_dim and determine the minimal number + of sequence dimensions. A dimension that did not appear as common + dimension should not be considered as a sequence dimension. */ + int nb_sequence_params = 0; + for (i = 0; i < nb_dims; i++) + if (temp_for_sequence_dims[i] > 0) + nb_sequence_params++; + + int *sequence_dims = NULL; + if (nb_sequence_params > 0) + { + int j = 0; + sequence_dims = XNEWVEC (int, nb_sequence_params); + for (i = 0; i < nb_dims; i++) + if (temp_for_sequence_dims[i] > 0) + { + sequence_dims[j] = i; + j++; + } + } + + XDELETEVEC (temp_for_sequence_dims); + + isl_space *dc = isl_set_get_space (scop->param_context); dc = isl_space_add_dims (dc, isl_dim_set, number_of_loops (cfun)); - static_sched = isl_aff_zero_on_domain (isl_local_space_from_space (dc)); + isl_local_space *local_space = isl_local_space_from_space (dc); + isl_aff *static_sched = isl_aff_zero_on_domain (local_space); /* We have to start schedules at 0 on the first component and because we cannot compare_prefix_loops against a previous loop, @@ -324,8 +405,7 @@ build_scop_scattering (scop_p scop) incremented before copying. */ static_sched = isl_aff_add_coefficient_si (static_sched, isl_dim_in, 0, -1); - int i; - poly_bb_p pbb; + previous_gbb = NULL; FOR_EACH_VEC_ELT (scop->pbbs, i, pbb) { gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb); @@ -338,12 +418,63 @@ build_scop_scattering (scop_p scop) static_sched = isl_aff_add_coefficient_si (static_sched, isl_dim_in, prefix, 1); - build_pbb_scattering_polyhedrons (static_sched, pbb); + build_pbb_minimal_scattering_polyhedrons (static_sched, pbb, + sequence_dims, nb_sequence_params); } + XDELETEVEC (sequence_dims); isl_aff_free (static_sched); } +/* Build the original schedule showing the orginal order of execution + of statement instances. + + The following example shows the original schedule: + + for (i: ...) + { + for (j: ...) + { + A + } + B + } + C + for (i: ...) + { + D + } + + Static schedules for A to D expressed in a union map: + + { S_A[i0, i1] -> [i0, i1]; S_B[i0] -> [i0]; S_C[] -> []; S_9[i0] -> [i0] } + +*/ + +static void +build_scop_original_schedule (scop_p scop) +{ + isl_space *space = isl_set_get_space (scop->param_context); + isl_union_map *res = isl_union_map_empty (space); + + int i; + poly_bb_p pbb; + FOR_EACH_VEC_ELT (scop->pbbs, i, pbb) + { + int nb_dimensions = isl_set_dim (pbb->domain, isl_dim_set); + isl_space *dc = isl_set_get_space (pbb->domain); + isl_space *dm = isl_space_add_dims (isl_space_from_domain (dc), + isl_dim_out, nb_dimensions); + isl_map *mp = isl_map_universe (dm); + for (int i = 0; i < nb_dimensions; i++) + mp = isl_map_equate (mp, isl_dim_in, i, isl_dim_out, i); + + res = isl_union_map_add_map (res, mp); + } + scop->original_schedule = res; +} + + static isl_pw_aff *extract_affine (scop_p, tree, __isl_take isl_space *space); /* Extract an affine expression from the chain of recurrence E. */ @@ -1716,7 +1847,8 @@ build_poly_scop (scop_p scop) rewrite_cross_bb_scalar_deps_out_of_ssa (scop); build_scop_drs (scop); - build_scop_scattering (scop); + build_scop_minimal_scattering (scop); + build_scop_original_schedule (scop); /* This SCoP has been translated to the polyhedral representation. */ diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 1c3328324ad..fff62de02a0 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -942,7 +942,7 @@ noce_emit_move_insn (rtx x, rtx y) } gcc_assert (start < (MEM_P (op) ? BITS_PER_UNIT : BITS_PER_WORD)); - store_bit_field (op, size, start, 0, 0, GET_MODE (x), y); + store_bit_field (op, size, start, 0, 0, GET_MODE (x), y, false); return; } @@ -997,7 +997,7 @@ noce_emit_move_insn (rtx x, rtx y) outmode = GET_MODE (outer); bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT; store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos, - 0, 0, outmode, y); + 0, 0, outmode, y, false); } /* Return the CC reg if it is used in COND. */ diff --git a/gcc/input.c b/gcc/input.c index e7302a42589..0f6d448b546 100644 --- a/gcc/input.c +++ b/gcc/input.c @@ -751,6 +751,22 @@ expand_location_to_spelling_point (source_location loc) return expand_location_1 (loc, /*expansion_point_p=*/false); } +/* The rich_location class within libcpp requires a way to expand + source_location instances, and relies on the client code + providing a symbol named + linemap_client_expand_location_to_spelling_point + to do this. + + This is the implementation for libcommon.a (all host binaries), + which simply calls into expand_location_to_spelling_point. */ + +expanded_location +linemap_client_expand_location_to_spelling_point (source_location loc) +{ + return expand_location_to_spelling_point (loc); +} + + /* If LOCATION is in a system header and if it is a virtual location for a token coming from the expansion of a macro, unwind it to the location of the expansion point of the macro. Otherwise, just return @@ -866,6 +882,12 @@ dump_line_table_statistics (void) fprintf (stderr, "Total used maps size: %5ld%c\n", SCALE (total_used_map_size), STAT_LABEL (total_used_map_size)); + fprintf (stderr, "Ad-hoc table size: %5ld%c\n", + SCALE (s.adhoc_table_size), + STAT_LABEL (s.adhoc_table_size)); + fprintf (stderr, "Ad-hoc table entries used: %5ld\n", + s.adhoc_table_entries_used); + fprintf (stderr, "\n"); } diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index 6fac752af61..afbfae815e5 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -43,7 +43,6 @@ along with GCC; see the file COPYING3. If not see const char *const internal_fn_name_array[] = { #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE, #include "internal-fn.def" -#undef DEF_INTERNAL_FN "" }; @@ -51,7 +50,6 @@ const char *const internal_fn_name_array[] = { const int internal_fn_flags_array[] = { #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS, #include "internal-fn.def" -#undef DEF_INTERNAL_FN 0 }; @@ -65,7 +63,6 @@ init_internal_fns () if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \ build_string ((int) sizeof (FNSPEC), FNSPEC ? FNSPEC : ""); #include "internal-fn.def" -#undef DEF_INTERNAL_FN internal_fn_fnspec_array[IFN_LAST] = 0; } @@ -2062,7 +2059,6 @@ expand_GOACC_REDUCTION (gcall *stmt ATTRIBUTE_UNUSED) static void (*const internal_fn_expanders[]) (gcall *) = { #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE, #include "internal-fn.def" -#undef DEF_INTERNAL_FN 0 }; diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index ca06b10d831..d0eb704bd15 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -86,3 +86,5 @@ DEF_INTERNAL_FN (GOACC_LOOP, ECF_PURE | ECF_NOTHROW, NULL) /* OpenACC reduction abstraction. See internal-fn.h for usage. */ DEF_INTERNAL_FN (GOACC_REDUCTION, ECF_NOTHROW | ECF_LEAF, NULL) + +#undef DEF_INTERNAL_FN diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 27104940fd8..6ba2f1493f8 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -1055,7 +1055,7 @@ ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input) { tree t = TREE_OPERAND (input, 0); t = build_ref_for_offset (EXPR_LOCATION (t), t, - ipa_get_jf_ancestor_offset (jfunc), + ipa_get_jf_ancestor_offset (jfunc), false, ptr_type_node, NULL, false); return build_fold_addr_expr (t); } diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index a3cd769a461..c07b0da9007 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -2853,6 +2853,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) inline_summaries->get (node)->self_time = time; inline_summaries->get (node)->self_size = size; nonconstant_names.release (); + fbi.bb_infos.release (); if (opt_for_fn (node->decl, optimize)) { if (!early) diff --git a/gcc/ipa-polymorphic-call.c b/gcc/ipa-polymorphic-call.c index 2f284950d8d..a577ffab68d 100644 --- a/gcc/ipa-polymorphic-call.c +++ b/gcc/ipa-polymorphic-call.c @@ -154,6 +154,8 @@ ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type, && tree_to_shwi (TYPE_SIZE (outer_type)) >= 0 && tree_to_shwi (TYPE_SIZE (outer_type)) <= offset) { + bool der = maybe_derived_type; /* clear_outer_type will reset it. */ + bool dyn = dynamic; clear_outer_type (otr_type); type = otr_type; cur_offset = 0; @@ -162,7 +164,7 @@ ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type, For dynamic types, we really do not have information about size of the memory location. It is possible that completely different type is stored after outer_type. */ - if (!maybe_derived_type && !dynamic) + if (!der && !dyn) { clear_speculation (); invalid = true; @@ -425,8 +427,10 @@ no_useful_type_info: return true; } else - clear_speculation (); - return true; + { + clear_speculation (); + return true; + } } else { @@ -459,15 +463,18 @@ contains_type_p (tree outer_type, HOST_WIDE_INT offset, if (offset < 0) return false; if (TYPE_SIZE (outer_type) && TYPE_SIZE (otr_type) - && TREE_CODE (outer_type) == INTEGER_CST - && TREE_CODE (otr_type) == INTEGER_CST - && wi::ltu_p (wi::to_offset (outer_type), (wi::to_offset (otr_type) + offset))) + && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST + && TREE_CODE (TYPE_SIZE (otr_type)) == INTEGER_CST + && wi::ltu_p (wi::to_offset (TYPE_SIZE (outer_type)), + (wi::to_offset (TYPE_SIZE (otr_type)) + offset))) return false; context.offset = offset; context.outer_type = TYPE_MAIN_VARIANT (outer_type); context.maybe_derived_type = false; - return context.restrict_to_inner_class (otr_type, consider_placement_new, consider_bases); + context.dynamic = false; + return context.restrict_to_inner_class (otr_type, consider_placement_new, + consider_bases); } @@ -742,6 +749,7 @@ ipa_polymorphic_call_context::set_by_invariant (tree cst, HOST_WIDE_INT off) { HOST_WIDE_INT offset2, size, max_size; + bool reverse; tree base; invalid = false; @@ -752,7 +760,7 @@ ipa_polymorphic_call_context::set_by_invariant (tree cst, return false; cst = TREE_OPERAND (cst, 0); - base = get_ref_base_and_extent (cst, &offset2, &size, &max_size); + base = get_ref_base_and_extent (cst, &offset2, &size, &max_size, &reverse); if (!DECL_P (base) || max_size == -1 || max_size != size) return false; @@ -882,8 +890,10 @@ ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl, { HOST_WIDE_INT size, max_size; HOST_WIDE_INT offset2; - tree base = get_ref_base_and_extent (TREE_OPERAND (base_pointer, 0), - &offset2, &size, &max_size); + bool reverse; + tree base + = get_ref_base_and_extent (TREE_OPERAND (base_pointer, 0), + &offset2, &size, &max_size, &reverse); if (max_size != -1 && max_size == size) combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base)), @@ -1151,6 +1161,7 @@ extr_type_from_vtbl_ptr_store (gimple *stmt, struct type_change_info *tci, { HOST_WIDE_INT offset, size, max_size; tree lhs, rhs, base; + bool reverse; if (!gimple_assign_single_p (stmt)) return NULL_TREE; @@ -1169,7 +1180,7 @@ extr_type_from_vtbl_ptr_store (gimple *stmt, struct type_change_info *tci, ; else { - base = get_ref_base_and_extent (lhs, &offset, &size, &max_size); + base = get_ref_base_and_extent (lhs, &offset, &size, &max_size, &reverse); if (DECL_P (tci->instance)) { if (base != tci->instance) @@ -1358,6 +1369,7 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data) tree op = walk_ssa_copies (gimple_call_arg (stmt, 0)); tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn)); HOST_WIDE_INT offset = 0, size, max_size; + bool reverse; if (dump_file) { @@ -1368,8 +1380,8 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data) /* See if THIS parameter seems like instance pointer. */ if (TREE_CODE (op) == ADDR_EXPR) { - op = get_ref_base_and_extent (TREE_OPERAND (op, 0), - &offset, &size, &max_size); + op = get_ref_base_and_extent (TREE_OPERAND (op, 0), &offset, + &size, &max_size, &reverse); if (size != max_size || max_size == -1) { tci->speculative = true; @@ -1527,6 +1539,7 @@ ipa_polymorphic_call_context::get_dynamic_type (tree instance, { tree ref = gimple_call_fn (call); HOST_WIDE_INT offset2, size, max_size; + bool reverse; if (TREE_CODE (ref) == OBJ_TYPE_REF) { @@ -1556,8 +1569,9 @@ ipa_polymorphic_call_context::get_dynamic_type (tree instance, && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref))) { tree ref_exp = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (ref)); - tree base_ref = get_ref_base_and_extent - (ref_exp, &offset2, &size, &max_size); + tree base_ref + = get_ref_base_and_extent (ref_exp, &offset2, &size, + &max_size, &reverse); /* Finally verify that what we found looks like read from OTR_OBJECT or from INSTANCE with offset OFFSET. */ diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 81dc71edf77..d15f0ebed56 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -952,7 +952,9 @@ ipa_load_from_parm_agg (struct ipa_func_body_info *fbi, { int index; HOST_WIDE_INT size, max_size; - tree base = get_ref_base_and_extent (op, offset_p, &size, &max_size); + bool reverse; + tree base + = get_ref_base_and_extent (op, offset_p, &size, &max_size, &reverse); if (max_size == -1 || max_size != size || *offset_p < 0) return false; @@ -1077,6 +1079,7 @@ compute_complex_assign_jump_func (struct ipa_func_body_info *fbi, { HOST_WIDE_INT offset, size, max_size; tree op1, tc_ssa, base, ssa; + bool reverse; int index; op1 = gimple_assign_rhs1 (stmt); @@ -1124,7 +1127,7 @@ compute_complex_assign_jump_func (struct ipa_func_body_info *fbi, op1 = TREE_OPERAND (op1, 0); if (TREE_CODE (TREE_TYPE (op1)) != RECORD_TYPE) return; - base = get_ref_base_and_extent (op1, &offset, &size, &max_size); + base = get_ref_base_and_extent (op1, &offset, &size, &max_size, &reverse); if (TREE_CODE (base) != MEM_REF /* If this is a varying address, punt. */ || max_size == -1 @@ -1160,6 +1163,7 @@ get_ancestor_addr_info (gimple *assign, tree *obj_p, HOST_WIDE_INT *offset) { HOST_WIDE_INT size, max_size; tree expr, parm, obj; + bool reverse; if (!gimple_assign_single_p (assign)) return NULL_TREE; @@ -1169,7 +1173,7 @@ get_ancestor_addr_info (gimple *assign, tree *obj_p, HOST_WIDE_INT *offset) return NULL_TREE; expr = TREE_OPERAND (expr, 0); obj = expr; - expr = get_ref_base_and_extent (expr, offset, &size, &max_size); + expr = get_ref_base_and_extent (expr, offset, &size, &max_size, &reverse); if (TREE_CODE (expr) != MEM_REF /* If this is a varying address, punt. */ @@ -1435,10 +1439,11 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg, else if (TREE_CODE (arg) == ADDR_EXPR) { HOST_WIDE_INT arg_max_size; + bool reverse; arg = TREE_OPERAND (arg, 0); arg_base = get_ref_base_and_extent (arg, &arg_offset, &arg_size, - &arg_max_size); + &arg_max_size, &reverse); if (arg_max_size == -1 || arg_max_size != arg_size || arg_offset < 0) @@ -1457,13 +1462,14 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg, else { HOST_WIDE_INT arg_max_size; + bool reverse; gcc_checking_assert (AGGREGATE_TYPE_P (TREE_TYPE (arg))); by_ref = false; check_ref = false; arg_base = get_ref_base_and_extent (arg, &arg_offset, &arg_size, - &arg_max_size); + &arg_max_size, &reverse); if (arg_max_size == -1 || arg_max_size != arg_size || arg_offset < 0) @@ -1484,6 +1490,7 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg, gimple *stmt = gsi_stmt (gsi); HOST_WIDE_INT lhs_offset, lhs_size, lhs_max_size; tree lhs, rhs, lhs_base; + bool reverse; if (!stmt_may_clobber_ref_p_1 (stmt, &r)) continue; @@ -1498,7 +1505,7 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg, break; lhs_base = get_ref_base_and_extent (lhs, &lhs_offset, &lhs_size, - &lhs_max_size); + &lhs_max_size, &reverse); if (lhs_max_size == -1 || lhs_max_size != lhs_size) break; @@ -3968,6 +3975,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gcall *stmt, base = force_gimple_operand_gsi (&gsi, base, true, NULL, true, GSI_SAME_STMT); expr = fold_build2_loc (loc, MEM_REF, type, base, off); + REF_REVERSE_STORAGE_ORDER (expr) = adj->reverse; /* If expr is not a valid gimple call argument emit a load into a temporary. */ if (is_gimple_reg_type (TREE_TYPE (expr))) @@ -3987,6 +3995,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gcall *stmt, else { expr = fold_build2_loc (loc, MEM_REF, adj->type, base, off); + REF_REVERSE_STORAGE_ORDER (expr) = adj->reverse; expr = build_fold_addr_expr (expr); expr = force_gimple_operand_gsi (&gsi, expr, true, NULL, true, GSI_SAME_STMT); @@ -4091,7 +4100,10 @@ ipa_modify_expr (tree *expr, bool convert, tree src; if (cand->by_ref) - src = build_simple_mem_ref (cand->new_decl); + { + src = build_simple_mem_ref (cand->new_decl); + REF_REVERSE_STORAGE_ORDER (src) = cand->reverse; + } else src = cand->new_decl; @@ -4158,7 +4170,9 @@ ipa_get_adjustment_candidate (tree **expr, bool *convert, } HOST_WIDE_INT offset, size, max_size; - tree base = get_ref_base_and_extent (**expr, &offset, &size, &max_size); + bool reverse; + tree base + = get_ref_base_and_extent (**expr, &offset, &size, &max_size, &reverse); if (!base || size == -1 || max_size == -1) return NULL; diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 35952dce1ca..b69ee8ab745 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -737,6 +737,10 @@ struct ipa_parm_adjustment or one about to be removed. */ enum ipa_parm_op op; + /* Storage order of the original parameter (for the cases when the new + parameter is a component of an original one). */ + unsigned reverse : 1; + /* The parameter is to be passed by reference. */ unsigned by_ref : 1; }; @@ -774,7 +778,7 @@ ipa_parm_adjustment *ipa_get_adjustment_candidate (tree **, bool *, /* From tree-sra.c: */ -tree build_ref_for_offset (location_t, tree, HOST_WIDE_INT, tree, +tree build_ref_for_offset (location_t, tree, HOST_WIDE_INT, bool, tree, gimple_stmt_iterator *, bool); /* In ipa-cp.c */ diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog index 301179bbdc0..5da80441c5c 100644 --- a/gcc/jit/ChangeLog +++ b/gcc/jit/ChangeLog @@ -1,3 +1,7 @@ +2015-11-07 Richard Sandiford + + * jit-builtins.c: Don't undef DEF_BUILTIN. + 2015-10-29 Andrew MacLeod * dummy-frontend.c: Reorder #include's and remove duplicates. diff --git a/gcc/jit/jit-builtins.c b/gcc/jit/jit-builtins.c index b28a5de21f7..63ff5affb55 100644 --- a/gcc/jit/jit-builtins.c +++ b/gcc/jit/jit-builtins.c @@ -62,7 +62,6 @@ static const struct builtin_data builtin_data[] = { #include "builtins.def" }; -#undef DEF_BUILTIN /* Helper function for find_builtin_by_name. */ diff --git a/gcc/lra.c b/gcc/lra.c index 0cd37f02032..0995c54aee4 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -1293,7 +1293,7 @@ init_reg_info (void) lra_reg_info = XNEWVEC (struct lra_reg, reg_info_size); for (i = 0; i < reg_info_size; i++) initialize_lra_reg_info_element (i); - copy_vec.create (100); + copy_vec.truncate (0); } diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index f32f8f894a0..3e087d1e124 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -958,7 +958,8 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map *map, hstate.add_flag (TREE_PRIVATE (t)); if (TYPE_P (t)) { - hstate.add_flag (TYPE_SATURATING (t)); + hstate.add_flag (AGGREGATE_TYPE_P (t) + ? TYPE_REVERSE_STORAGE_ORDER (t) : TYPE_SATURATING (t)); hstate.add_flag (TYPE_ADDR_SPACE (t)); } else if (code == SSA_NAME) diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 332251cd62f..d254bee4685 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,11 @@ +2015-11-08 Eric Botcazou + + * lto.c (compare_tree_sccs_1): Deal with TYPE_REVERSE_STORAGE_ORDER. + +2015-11-07 Richard Sandiford + + * lto-lang.c: Don't undef DEF_BUILTIN. + 2015-10-29 Andrew MacLeod * lto-lang.c: Reorder #include's and remove duplicates. diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c index be317a42fbe..4805c2a69b1 100644 --- a/gcc/lto/lto-lang.c +++ b/gcc/lto/lto-lang.c @@ -731,7 +731,6 @@ lto_define_builtins (tree va_list_ref_type_node ATTRIBUTE_UNUSED, builtin_types[(int) LIBTYPE], BOTH_P, FALLBACK_P, \ NONANSI_P, built_in_attributes[(int) ATTRS], IMPLICIT); #include "builtins.def" -#undef DEF_BUILTIN } static GTY(()) tree registered_builtin_types; diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 8510f6598ba..5dcc4dcd851 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -1021,7 +1021,10 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map) compare_values (TREE_DEPRECATED); if (TYPE_P (t1)) { - compare_values (TYPE_SATURATING); + if (AGGREGATE_TYPE_P (t1)) + compare_values (TYPE_REVERSE_STORAGE_ORDER); + else + compare_values (TYPE_SATURATING); compare_values (TYPE_ADDR_SPACE); } else if (code == SSA_NAME) diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 23721f60005..57b5db48bcb 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,8 @@ +2015-11-09 Alan Modra + + * objc-encoding.c (encode_aggregate_within): Cast obstack_next_free + return value. + 2015-10-29 Andrew MacLeod * objc-lang.c: Reorder #include's and remove duplicates. diff --git a/gcc/objc/objc-encoding.c b/gcc/objc/objc-encoding.c index 48480213534..9c577e93bae 100644 --- a/gcc/objc/objc-encoding.c +++ b/gcc/objc/objc-encoding.c @@ -495,13 +495,14 @@ encode_aggregate_within (tree type, int curtype, int format, int left, if (flag_next_runtime) { - if (ob_size > 0 && *(obstack_next_free (&util_obstack) - 1) == '^') + if (ob_size > 0 + && *((char *) obstack_next_free (&util_obstack) - 1) == '^') pointed_to = true; if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables) && (!pointed_to || ob_size - curtype == 1 || (ob_size - curtype == 2 - && *(obstack_next_free (&util_obstack) - 2) == 'r'))) + && *((char *) obstack_next_free (&util_obstack) - 2) == 'r'))) inline_contents = true; } else @@ -512,9 +513,10 @@ encode_aggregate_within (tree type, int curtype, int format, int left, comment above applies: in that case we should avoid encoding the names of instance variables. */ - char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0; - char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0; + char c0, c1; + c1 = ob_size > 1 ? *((char *) obstack_next_free (&util_obstack) - 2) : 0; + c0 = ob_size > 0 ? *((char *) obstack_next_free (&util_obstack) - 1) : 0; if (c0 == '^' || (c1 == '^' && c0 == 'r')) pointed_to = true; diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 5ffb2765059..45d1927f678 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -3112,9 +3112,9 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) if (!(is_gimple_omp (stmt) && is_gimple_omp_oacc (stmt))) { - for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer) - if (is_gimple_omp (ctx_->stmt) - && is_gimple_omp_oacc (ctx_->stmt) + for (omp_context *octx = ctx; octx != NULL; octx = octx->outer) + if (is_gimple_omp (octx->stmt) + && is_gimple_omp_oacc (octx->stmt) /* Except for atomic codes that we share with OpenMP. */ && ! (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE)) @@ -3134,12 +3134,27 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) if (gimple_code (stmt) == GIMPLE_OMP_ORDERED) { c = gimple_omp_ordered_clauses (as_a (stmt)); - if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD) - return true; + if (find_omp_clause (c, OMP_CLAUSE_SIMD)) + { + if (find_omp_clause (c, OMP_CLAUSE_THREADS) + && (ctx->outer == NULL + || !gimple_omp_for_combined_into_p (ctx->stmt) + || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR + || (gimple_omp_for_kind (ctx->outer->stmt) + != GF_OMP_FOR_KIND_FOR) + || !gimple_omp_for_combined_p (ctx->outer->stmt))) + { + error_at (gimple_location (stmt), + "% must be closely " + "nested inside of % region"); + return false; + } + return true; + } } error_at (gimple_location (stmt), "OpenMP constructs other than %<#pragma omp ordered simd%>" - " may not be nested inside simd region"); + " may not be nested inside % region"); return false; } else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS) @@ -3150,8 +3165,9 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) && gimple_code (stmt) != GIMPLE_OMP_PARALLEL) { error_at (gimple_location (stmt), - "only distribute or parallel constructs are allowed to " - "be closely nested inside teams construct"); + "only % or % regions are " + "allowed to be strictly nested inside % " + "region"); return false; } } @@ -3166,8 +3182,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS) { error_at (gimple_location (stmt), - "distribute construct must be closely nested inside " - "teams construct"); + "% region must be strictly nested " + "inside % construct"); return false; } return true; @@ -3222,13 +3238,15 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) { const char *bad = NULL; const char *kind = NULL; + const char *construct + = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)) + == BUILT_IN_GOMP_CANCEL) + ? "#pragma omp cancel" + : "#pragma omp cancellation point"; if (ctx == NULL) { error_at (gimple_location (stmt), "orphaned %qs construct", - DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)) - == BUILT_IN_GOMP_CANCEL - ? "#pragma omp cancel" - : "#pragma omp cancellation point"); + construct); return false; } switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0)) @@ -3304,7 +3322,33 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK) bad = "#pragma omp task"; else - ctx->cancellable = true; + { + for (omp_context *octx = ctx->outer; + octx; octx = octx->outer) + { + switch (gimple_code (octx->stmt)) + { + case GIMPLE_OMP_TASKGROUP: + break; + case GIMPLE_OMP_TARGET: + if (gimple_omp_target_kind (octx->stmt) + != GF_OMP_TARGET_KIND_REGION) + continue; + /* FALLTHRU */ + case GIMPLE_OMP_PARALLEL: + case GIMPLE_OMP_TEAMS: + error_at (gimple_location (stmt), + "%<%s taskgroup%> construct not closely " + "nested inside of % region", + construct); + return false; + default: + continue; + } + break; + } + ctx->cancellable = true; + } kind = "taskgroup"; break; default: @@ -3315,10 +3359,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) { error_at (gimple_location (stmt), "%<%s %s%> construct not closely nested inside of %qs", - DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)) - == BUILT_IN_GOMP_CANCEL - ? "#pragma omp cancel" - : "#pragma omp cancellation point", kind, bad); + construct, kind, bad); return false; } } @@ -3329,6 +3370,10 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) switch (gimple_code (ctx->stmt)) { case GIMPLE_OMP_FOR: + if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR + && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP) + break; + /* FALLTHRU */ case GIMPLE_OMP_SECTIONS: case GIMPLE_OMP_SINGLE: case GIMPLE_OMP_ORDERED: @@ -3342,17 +3387,24 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) return true; error_at (gimple_location (stmt), "barrier region may not be closely nested inside " - "of work-sharing, critical, ordered, master or " - "explicit task region"); + "of work-sharing, %, %, " + "%, explicit % or % " + "region"); return false; } error_at (gimple_location (stmt), "work-sharing region may not be closely nested inside " - "of work-sharing, critical, ordered, master or explicit " - "task region"); + "of work-sharing, %, %, " + "%, explicit % or % region"); return false; case GIMPLE_OMP_PARALLEL: + case GIMPLE_OMP_TEAMS: return true; + case GIMPLE_OMP_TARGET: + if (gimple_omp_target_kind (ctx->stmt) + == GF_OMP_TARGET_KIND_REGION) + return true; + break; default: break; } @@ -3362,15 +3414,26 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) switch (gimple_code (ctx->stmt)) { case GIMPLE_OMP_FOR: + if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR + && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP) + break; + /* FALLTHRU */ case GIMPLE_OMP_SECTIONS: case GIMPLE_OMP_SINGLE: case GIMPLE_OMP_TASK: error_at (gimple_location (stmt), - "master region may not be closely nested inside " - "of work-sharing or explicit task region"); + "% region may not be closely nested inside " + "of work-sharing, explicit % or % " + "region"); return false; case GIMPLE_OMP_PARALLEL: + case GIMPLE_OMP_TEAMS: return true; + case GIMPLE_OMP_TARGET: + if (gimple_omp_target_kind (ctx->stmt) + == GF_OMP_TARGET_KIND_REGION) + return true; + break; default: break; } @@ -3395,8 +3458,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND) { gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS - || (ctx == NULL - && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD)); + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD); continue; } enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c); @@ -3412,23 +3474,40 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) OMP_CLAUSE_ORDERED)) == NULL_TREE) { error_at (OMP_CLAUSE_LOCATION (c), - "% clause must be closely nested " - "inside an ordered loop"); + "% construct with % clause " + "must be closely nested inside an % " + "loop"); return false; } else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE) { error_at (OMP_CLAUSE_LOCATION (c), - "% clause must be closely nested " - "inside a loop with % clause with " - "a parameter"); + "% construct with % clause " + "must be closely nested inside a loop with " + "% clause with a parameter"); return false; } } else { error_at (OMP_CLAUSE_LOCATION (c), - "invalid depend kind in omp ordered depend"); + "invalid depend kind in omp % %"); + return false; + } + } + c = gimple_omp_ordered_clauses (as_a (stmt)); + if (find_omp_clause (c, OMP_CLAUSE_SIMD)) + { + /* ordered simd must be closely nested inside of simd region, + and simd region must not encounter constructs other than + ordered simd, therefore ordered simd may be either orphaned, + or ctx->stmt must be simd. The latter case is handled already + earlier. */ + if (ctx != NULL) + { + error_at (gimple_location (stmt), + "% % must be closely nested inside " + "% region"); return false; } } @@ -3437,24 +3516,35 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) { case GIMPLE_OMP_CRITICAL: case GIMPLE_OMP_TASK: + case GIMPLE_OMP_ORDERED: + ordered_in_taskloop: error_at (gimple_location (stmt), - "ordered region may not be closely nested inside " - "of critical or explicit task region"); + "% region may not be closely nested inside " + "of %, %, explicit % or " + "% region"); return false; case GIMPLE_OMP_FOR: + if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP) + goto ordered_in_taskloop; if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt), OMP_CLAUSE_ORDERED) == NULL) { error_at (gimple_location (stmt), - "ordered region must be closely nested inside " - "a loop region with an ordered clause"); + "% region must be closely nested inside " + "a loop region with an % clause"); return false; } return true; + case GIMPLE_OMP_TARGET: + if (gimple_omp_target_kind (ctx->stmt) + != GF_OMP_TARGET_KIND_REGION) + break; + /* FALLTHRU */ case GIMPLE_OMP_PARALLEL: + case GIMPLE_OMP_TEAMS: error_at (gimple_location (stmt), - "ordered region must be closely nested inside " - "a loop region with an ordered clause"); + "% region must be closely nested inside " + "a loop region with an % clause"); return false; default: break; @@ -3470,8 +3560,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) if (this_stmt_name == gimple_omp_critical_name (other_crit)) { error_at (gimple_location (stmt), - "critical region may not be nested inside a critical " - "region with the same name"); + "% region may not be nested inside " + "a % region with the same name"); return false; } } @@ -3482,8 +3572,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION) { error_at (gimple_location (stmt), - "teams construct not closely nested inside of target " - "region"); + "% construct not closely nested inside of " + "% construct"); return false; } break; @@ -3549,7 +3639,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) != is_gimple_omp_oacc (ctx->stmt)) { error_at (gimple_location (stmt), - "%s %s construct inside of %s %s region", + "%s %qs construct inside of %s %qs region", (is_gimple_omp_oacc (stmt) ? "OpenACC" : "OpenMP"), stmt_name, (is_gimple_omp_oacc (ctx->stmt) @@ -3562,15 +3652,14 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) if (is_gimple_omp_oacc (ctx->stmt)) { error_at (gimple_location (stmt), - "%s construct inside of %s region", + "%qs construct inside of %qs region", stmt_name, ctx_stmt_name); return false; } else { - gcc_checking_assert (!is_gimple_omp_oacc (stmt)); warning_at (gimple_location (stmt), 0, - "%s construct inside of %s region", + "%qs construct inside of %qs region", stmt_name, ctx_stmt_name); } } diff --git a/gcc/output.h b/gcc/output.h index 4ce6eeaa2b4..f9ff85886db 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -278,10 +278,11 @@ extern section *get_named_text_section (tree, const char *, const char *); #define assemble_aligned_integer(SIZE, VALUE) \ assemble_integer (VALUE, SIZE, (SIZE) * BITS_PER_UNIT, 1) -#ifdef REAL_VALUE_TYPE_SIZE -/* Assemble the floating-point constant D into an object of size MODE. */ -extern void assemble_real (REAL_VALUE_TYPE, machine_mode, unsigned); -#endif +/* Assemble the floating-point constant D into an object of size MODE. ALIGN + is the alignment of the constant in bits. If REVERSE is true, D is output + in reverse storage order. */ +extern void assemble_real (REAL_VALUE_TYPE, machine_mode, unsigned, + bool = false); /* Write the address of the entity given by SYMBOL to SEC. */ extern void assemble_addr_to_section (rtx, section *); diff --git a/gcc/postreload-gcse.c b/gcc/postreload-gcse.c index ea4bba4365e..f8a770e25f2 100644 --- a/gcc/postreload-gcse.c +++ b/gcc/postreload-gcse.c @@ -348,6 +348,8 @@ free_mem (void) BITMAP_FREE (blocks_with_calls); BITMAP_FREE (modify_mem_list_set); free (reg_avail_info); + free (modify_mem_list); + free (canon_modify_mem_list); } diff --git a/gcc/pretty-print.c b/gcc/pretty-print.c index b24402de12d..4a28d3c5fd9 100644 --- a/gcc/pretty-print.c +++ b/gcc/pretty-print.c @@ -31,6 +31,27 @@ along with GCC; see the file COPYING3. If not see #include #endif +/* Overwrite the range within this text_info's rich_location. + For use e.g. when implementing "+" in client format decoders. */ + +void +text_info::set_range (unsigned int idx, source_range range, bool caret_p) +{ + gcc_checking_assert (m_richloc); + m_richloc->set_range (idx, range, caret_p, true); +} + +location_t +text_info::get_location (unsigned int index_of_location) const +{ + gcc_checking_assert (m_richloc); + + if (index_of_location == 0) + return m_richloc->get_loc (); + else + return UNKNOWN_LOCATION; +} + // Default construct an output buffer. output_buffer::output_buffer () diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h index 2654b0fcbec..cdee2535fe0 100644 --- a/gcc/pretty-print.h +++ b/gcc/pretty-print.h @@ -27,11 +27,6 @@ along with GCC; see the file COPYING3. If not see /* Maximum number of format string arguments. */ #define PP_NL_ARGMAX 30 -/* Maximum number of locations associated to each message. If - location 'i' is UNKNOWN_LOCATION, then location 'i+1' is not - valid. */ -#define MAX_LOCATIONS_PER_MESSAGE 2 - /* The type of a text to be formatted according a format specification along with a list of things. */ struct text_info @@ -40,21 +35,17 @@ struct text_info va_list *args_ptr; int err_no; /* for %m */ void **x_data; + rich_location *m_richloc; - inline void set_location (unsigned int index_of_location, location_t loc) + inline void set_location (unsigned int idx, location_t loc, bool caret_p) { - gcc_checking_assert (index_of_location < MAX_LOCATIONS_PER_MESSAGE); - this->locations[index_of_location] = loc; + source_range src_range; + src_range.m_start = loc; + src_range.m_finish = loc; + set_range (idx, src_range, caret_p); } - - inline location_t get_location (unsigned int index_of_location) const - { - gcc_checking_assert (index_of_location < MAX_LOCATIONS_PER_MESSAGE); - return this->locations[index_of_location]; - } - -private: - location_t locations[MAX_LOCATIONS_PER_MESSAGE]; + void set_range (unsigned int idx, source_range range, bool caret_p); + location_t get_location (unsigned int index_of_location) const; }; /* How often diagnostics are prefixed by their locations: diff --git a/gcc/print-tree.c b/gcc/print-tree.c index ad66e2f9c25..1b584b87ea0 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -565,6 +565,13 @@ print_node (FILE *file, const char *prefix, tree node, int indent) if (TYPE_NEEDS_CONSTRUCTING (node)) fputs (" needs-constructing", file); + if ((code == RECORD_TYPE + || code == UNION_TYPE + || code == QUAL_UNION_TYPE + || code == ARRAY_TYPE) + && TYPE_REVERSE_STORAGE_ORDER (node)) + fputs (" reverse-storage-order", file); + /* The transparent-union flag is used for different things in different nodes. */ if ((code == UNION_TYPE || code == RECORD_TYPE) diff --git a/gcc/rtl-error.c b/gcc/rtl-error.c index d461cd4ba33..96da2bd275d 100644 --- a/gcc/rtl-error.c +++ b/gcc/rtl-error.c @@ -67,9 +67,10 @@ diagnostic_for_asm (const rtx_insn *insn, const char *msg, va_list *args_ptr, diagnostic_t kind) { diagnostic_info diagnostic; + rich_location richloc (location_for_asm (insn)); diagnostic_set_info (&diagnostic, msg, args_ptr, - location_for_asm (insn), kind); + &richloc, kind); report_diagnostic (&diagnostic); } diff --git a/gcc/rtl.h b/gcc/rtl.h index fe081ed3085..194ed9ba959 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2086,6 +2086,7 @@ namespace wi inline unsigned int wi::int_traits ::get_precision (const rtx_mode_t &x) { + gcc_checking_assert (x.second != BLKmode && x.second != VOIDmode); return GET_MODE_PRECISION (x.second); } diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c index 220eea461f6..4f64fa9d78d 100644 --- a/gcc/sched-deps.c +++ b/gcc/sched-deps.c @@ -4092,9 +4092,9 @@ void sched_deps_finish (void) { gcc_assert (deps_pools_are_empty_p ()); - dn_pool->release_if_empty (); + delete dn_pool; + delete dl_pool; dn_pool = NULL; - dl_pool->release_if_empty (); dl_pool = NULL; h_d_i_d.release (); diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index b3c98c26e89..17568baa8b0 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -301,10 +301,11 @@ delegitimize_mem_from_attrs (rtx x) { HOST_WIDE_INT bitsize, bitpos; tree toffset; - int unsignedp, volatilep = 0; + int unsignedp, reversep, volatilep = 0; - decl = get_inner_reference (decl, &bitsize, &bitpos, &toffset, - &mode, &unsignedp, &volatilep, false); + decl + = get_inner_reference (decl, &bitsize, &bitpos, &toffset, &mode, + &unsignedp, &reversep, &volatilep, false); if (bitsize != GET_MODE_BITSIZE (mode) || (bitpos % BITS_PER_UNIT) || (toffset && !tree_fits_shwi_p (toffset))) diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 364a0b5454b..fac38951b34 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -2035,11 +2035,16 @@ finish_record_layout (record_layout_info rli, int free_p) /* Compute bitfield representatives. */ finish_bitfield_layout (rli->t); - /* Propagate TYPE_PACKED to variants. With C++ templates, - handle_packed_attribute is too early to do this. */ + /* Propagate TYPE_PACKED and TYPE_REVERSE_STORAGE_ORDER to variants. + With C++ templates, it is too early to do this when the attribute + is being parsed. */ for (variant = TYPE_NEXT_VARIANT (rli->t); variant; variant = TYPE_NEXT_VARIANT (variant)) - TYPE_PACKED (variant) = TYPE_PACKED (rli->t); + { + TYPE_PACKED (variant) = TYPE_PACKED (rli->t); + TYPE_REVERSE_STORAGE_ORDER (variant) + = TYPE_REVERSE_STORAGE_ORDER (rli->t); + } /* Lay out any static members. This is done now because their type may use the record's type. */ diff --git a/gcc/target.def b/gcc/target.def index c7ec2929714..0f7d3e5effb 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -3223,6 +3223,15 @@ converted to pointers to a subset address space via explicit casts.", bool, (addr_space_t subset, addr_space_t superset), default_addr_space_subset_p) +/* True if 0 is a valid address in the address space, or false if + 0 is a NULL in the address space. */ +DEFHOOK +(zero_address_valid, + "Define this to modify the default handling of address 0 for the\n\ +address space. Return true if 0 should be considered a valid address.", + bool, (addr_space_t as), + default_addr_space_zero_address_valid) + /* Function to convert an rtl expression from one address space to another. */ DEFHOOK (convert, @@ -3235,6 +3244,14 @@ as determined by the @code{TARGET_ADDR_SPACE_SUBSET_P} target hook.", rtx, (rtx op, tree from_type, tree to_type), default_addr_space_convert) +/* Function to encode an address space into dwarf. */ +DEFHOOK +(debug, + "Define this to define how the address space is encoded in dwarf.\n\ +The result is the value to be used with @code{DW_AT_address_class}.", + int, (addr_space_t as), + default_addr_space_debug) + HOOK_VECTOR_END (addr_space) #undef HOOK_PREFIX diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 14324b7addc..c810525be92 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -1268,6 +1268,23 @@ default_addr_space_subset_p (addr_space_t subset, addr_space_t superset) return (subset == superset); } +/* The default hook for determining if 0 within a named address + space is a valid address. */ + +bool +default_addr_space_zero_address_valid (addr_space_t as ATTRIBUTE_UNUSED) +{ + return false; +} + +/* The default hook for debugging the address space is to return the + address space number to indicate DW_AT_address_class. */ +int +default_addr_space_debug (addr_space_t as) +{ + return as; +} + /* The default hook for TARGET_ADDR_SPACE_CONVERT. This hook should never be called for targets with only a generic address space. */ diff --git a/gcc/targhooks.h b/gcc/targhooks.h index a8e7ebbd8ca..8747f958535 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -177,6 +177,8 @@ extern bool default_addr_space_legitimate_address_p (machine_mode, rtx, extern rtx default_addr_space_legitimize_address (rtx, rtx, machine_mode, addr_space_t); extern bool default_addr_space_subset_p (addr_space_t, addr_space_t); +extern bool default_addr_space_zero_address_valid (addr_space_t); +extern int default_addr_space_debug (addr_space_t); extern rtx default_addr_space_convert (rtx, tree, tree); extern unsigned int default_case_values_threshold (void); extern bool default_have_conditional_execution (void); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c074e7b55e0..bcca4791eeb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,203 @@ +2015-11-09 Igor Zamyatin + + PR target/66326 + * g++.dg/cilk-plus/CK/pr66326.cc: New test. + +2015-11-09 Richard Henderson + + * gcc.target/i386/addr-space-1.c: New test. + * gcc.target/i386/addr-space-2.c: New test. + * gcc.target/i386/addr-space-3.c: New test. + +2015-11-08 Steven g. Kargl + + PR fortran/68053 + * gfortran.dg/pr68053.f90: New test. + +2015-11-06 Jan Hubicka + + * g++.dg/lto/pr68057_0.C: Fix testcase. + +2015-11-08 Joost VandeVondele + + * gfortran.dg/PR67518.f90: move from here... + * gfortran.dg/graphite/PR67518.f90: to here. + * gfortran.dg/PR53852.f90: move from here... + * gfortran.dg/graphite/PR53852.f90: to here. + +2015-11-08 Eric Botcazou + + * gcc.dg/sso-1.c: New test. + * gcc.dg/sso-2.c: Likewise. + * gcc.dg/sso-3.c: Likewise. + * gcc.dg/sso-4.c: Likewise. + * gcc.dg/sso-5.c: Likewise. + * gcc.dg/sso-6.c: Likewise. + * gcc.dg/sso-7.c: Likewise. + * gcc.dg/sso-8.c: Likewise. + * gcc.dg/sso: New directory. + * gcc.target/i386/movbe-3.c: New test. + * gnat.dg/sso1.adb: Likewise. + * gnat.dg/sso2.ad[sb]: Likewise. + * gnat.dg/sso3.adb: Likewise. + * gnat.dg/sso4.adb: Likewise. + * gnat.dg/sso5.adb: Likewise. + * gnat.dg/sso6.adb: Likewise. + * gnat.dg/sso7.adb: Likewise. + * gnat.dg/specs/sso1.ads: Likewise. + * gnat.dg/specs/sso2.ads: Likewise. + * gnat.dg/sso: New directory. + +2015-11-08 Andre Vehreschild + + PR fortran/68218 + * gfortran.dg/allocate_with_arrayspec_1.f90: New test. + +2015-11-08 Steven G. Kargl + + PR fortran/68224 + * gfortran.dg/pr68224.f90: New test. + +2015-11-08 Paul Thomas + + PR fortran/68196 + * gfortran.dg/proc_ptr_47.f90: New test. + + PR fortran/66465 + * gfortran.dg/pr66465.f90: New test. + +2015-11-07 John David Anglin + + * gcc.dg/Wno-frame-address.c: Skip on hppa*-*-*. + +2015-11-07 Steven G. Kargl + + PR fortran/68153 + * gfortran.dg/pr68153.f90: New test. + +2015-11-07 Steven G. Kargl + + PR fortran/68151 + * gfortran.dg/pr68151.f90: New test. + +2015-11-07 Richard Sandiford + + PR tree-optimization/68235 + * gcc.dg/lto/20110201-1_0.c: Add -fno-math-errno. + +2015-11-06 Jeff Law + + * gcc.dg/tree-ssa/ssa-dom-thread-7.c: Adjust to look for + realized jump threads. + * gcc.dg/tree-ssa-pr66752-3.c: Look in vrp1 dump for jump + threads rather than dom1 dump. + +2015-11-06 Michael Collison + + Revert: + 2015-08-01 Michael Collison + + * gcc.target/arm/mincmp.c: New test. + +2015-11-06 Dominique d'Humieres + + PR fortran/54224 + * gfortran.dg/warn_unused_function_2.f90: Add two new + "defined but not used" subroutines. + +2015-11-06 Jakub Jelinek + + * gcc.dg/gomp/ordered-2.c (f1): Expect an extra error. + * g++.dg/gomp/ordered-2.C (f1): Likewise. + * gfortran.dg/goacc/parallel-kernels-regions.f95: Adjust + expected diagnostics for the addition of quotes. + * gfortran.dg/gomp/target3.f90: Likewise. + * c-c++-common/goacc/nesting-fail-1.c: Likewise. + * c-c++-common/goacc-gomp/nesting-fail-1.c: Likewise. + * c-c++-common/gomp/doacross-1.c: Likewise. + * c-c++-common/gomp/nesting-warn-1.c: Likewise. + * c-c++-common/gomp/cancel-1.c (f2): Add some new tests. + Adjust expected diagnostics wording. + * c-c++-common/gomp/clauses-4.c (foo): Likewise. + Don't expect error on ordered threads simd when in for simd. + * c-c++-common/gomp/nesting-2.c: New test. + * c-c++-common/gomp/ordered-3.c (foo): Add some new tests. + * c-c++-common/gomp/ordered-4.c: New test. + +2015-11-06 Mike Stump + + * gcc.dg/pragma-diag-5.c: Make test cases unique. + +2015-11-06 Aditya Kumar + Sebastian Pop + + * gcc.dg/graphite/fuse-1.c: New. + * gcc.dg/graphite/fuse-2.c: New. + * gcc.dg/graphite/interchange-13.c: Remove bogus check. + +2015-11-06 Christophe Lyon + + * gcc.target/aarch64/advsimd-intrinsics/vqtbX.c: New test. + +2015-11-06 David Malcolm + + * gcc.dg/plugin/diagnostic-test-show-locus-bw.c: New file. + * gcc.dg/plugin/diagnostic-test-show-locus-color.c: New file. + * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c: New file. + * gcc.dg/plugin/plugin.exp (plugin_test_list): Add the above. + * lib/gcc-dg.exp: Load multiline.exp. + +2015-11-06 Ramana Radhakrishnan + + * gcc.target/arm/combine-movs.c: Adjust for unified asm. + * gcc.target/arm/interrupt-1.c: Likewise. + * gcc.target/arm/interrupt-2.c: Likewise. + * gcc.target/arm/unaligned-memcpy-4.c: Likewise. + +2015-11-06 Thomas Schwinge + + * gfortran.dg/goacc/combined_loop.f90: XFAIL. + +2015-11-06 Jan Hubicka + + PR ipa/68057 + PR ipa/68220 + * g++.dg/lto/pr68057_0.C: New testcase. + * g++.dg/lto/pr68057_1.C: New testcase. + * g++.dg/torture/pr68220.C: New testcase. + +2015-11-06 Christophe Lyon + + * gcc.target/aarch64/advsimd-intrinsics/vtbX.c: Fix typos in + comment. + +2015-11-06 Ilya Enkovich + + PR tree-optimization/68145 + * g++.dg/vect/pr68145.cc: New test. + +2015-11-06 Kyrylo Tkachov + + PR target/68088 + * gcc.dg/pr68088_1.c: New test. + +2015-11-06 Richard Biener + + * gcc.dg/vect/bb-slp-38.c: New testcase. + +2015-11-06 Thomas Schwinge + + * gfortran.dg/goacc/private-3.f95: XFAIL. + +2015-11-06 Joost VandeVondele + + PR middle-end/53852 + PR middle-end/67518 + * gfortran.dg/PR67518.f90: New test. + * gfortran.dg/PR53852.f90: New test. + 2015-11-05 Cesar Philippidis Tom de Vries Nathan Sidwell diff --git a/gcc/testsuite/c-c++-common/goacc-gomp/nesting-fail-1.c b/gcc/testsuite/c-c++-common/goacc-gomp/nesting-fail-1.c index e98258c3353..1a4472107c6 100644 --- a/gcc/testsuite/c-c++-common/goacc-gomp/nesting-fail-1.c +++ b/gcc/testsuite/c-c++-common/goacc-gomp/nesting-fail-1.c @@ -151,15 +151,15 @@ f_omp (void) #pragma omp target { -#pragma acc parallel /* { dg-error "OpenACC parallel construct inside of OpenMP target region" } */ +#pragma acc parallel /* { dg-error "OpenACC .parallel. construct inside of OpenMP .target. region" } */ ; -#pragma acc kernels /* { dg-error "OpenACC kernels construct inside of OpenMP target region" } */ +#pragma acc kernels /* { dg-error "OpenACC .kernels. construct inside of OpenMP .target. region" } */ ; -#pragma acc data /* { dg-error "OpenACC data construct inside of OpenMP target region" } */ +#pragma acc data /* { dg-error "OpenACC .data. construct inside of OpenMP .target. region" } */ ; -#pragma acc update host(i) /* { dg-error "OpenACC update construct inside of OpenMP target region" } */ -#pragma acc enter data copyin(i) /* { dg-error "OpenACC enter/exit data construct inside of OpenMP target region" } */ -#pragma acc exit data delete(i) /* { dg-error "OpenACC enter/exit data construct inside of OpenMP target region" } */ +#pragma acc update host(i) /* { dg-error "OpenACC .update. construct inside of OpenMP .target. region" } */ +#pragma acc enter data copyin(i) /* { dg-error "OpenACC .enter/exit data. construct inside of OpenMP .target. region" } */ +#pragma acc exit data delete(i) /* { dg-error "OpenACC .enter/exit data. construct inside of OpenMP .target. region" } */ #pragma acc loop /* { dg-error "loop directive must be associated with an OpenACC compute region" } */ for (i = 0; i < 2; ++i) ; diff --git a/gcc/testsuite/c-c++-common/goacc/nesting-fail-1.c b/gcc/testsuite/c-c++-common/goacc/nesting-fail-1.c index 8af1c8244f0..7a36074ae38 100644 --- a/gcc/testsuite/c-c++-common/goacc/nesting-fail-1.c +++ b/gcc/testsuite/c-c++-common/goacc/nesting-fail-1.c @@ -7,15 +7,15 @@ f_acc_parallel (void) { #pragma acc parallel { -#pragma acc parallel /* { dg-bogus "parallel construct inside of parallel region" "not implemented" { xfail *-*-* } } */ +#pragma acc parallel /* { dg-bogus ".parallel. construct inside of .parallel. region" "not implemented" { xfail *-*-* } } */ ; -#pragma acc kernels /* { dg-bogus "kernels construct inside of parallel region" "not implemented" { xfail *-*-* } } */ +#pragma acc kernels /* { dg-bogus ".kernels. construct inside of .parallel. region" "not implemented" { xfail *-*-* } } */ ; -#pragma acc data /* { dg-error "data construct inside of parallel region" } */ +#pragma acc data /* { dg-error ".data. construct inside of .parallel. region" } */ ; -#pragma acc update host(i) /* { dg-error "update construct inside of parallel region" } */ -#pragma acc enter data copyin(i) /* { dg-error "enter/exit data construct inside of parallel region" } */ -#pragma acc exit data delete(i) /* { dg-error "enter/exit data construct inside of parallel region" } */ +#pragma acc update host(i) /* { dg-error ".update. construct inside of .parallel. region" } */ +#pragma acc enter data copyin(i) /* { dg-error ".enter/exit data. construct inside of .parallel. region" } */ +#pragma acc exit data delete(i) /* { dg-error ".enter/exit data. construct inside of .parallel. region" } */ } } @@ -26,14 +26,14 @@ f_acc_kernels (void) { #pragma acc kernels { -#pragma acc parallel /* { dg-bogus "parallel construct inside of kernels region" "not implemented" { xfail *-*-* } } */ +#pragma acc parallel /* { dg-bogus ".parallel. construct inside of .kernels. region" "not implemented" { xfail *-*-* } } */ ; -#pragma acc kernels /* { dg-bogus "kernels construct inside of kernels region" "not implemented" { xfail *-*-* } } */ +#pragma acc kernels /* { dg-bogus ".kernels. construct inside of .kernels. region" "not implemented" { xfail *-*-* } } */ ; -#pragma acc data /* { dg-error "data construct inside of kernels region" } */ +#pragma acc data /* { dg-error ".data. construct inside of .kernels. region" } */ ; -#pragma acc update host(i) /* { dg-error "update construct inside of kernels region" } */ -#pragma acc enter data copyin(i) /* { dg-error "enter/exit data construct inside of kernels region" } */ -#pragma acc exit data delete(i) /* { dg-error "enter/exit data construct inside of kernels region" } */ +#pragma acc update host(i) /* { dg-error ".update. construct inside of .kernels. region" } */ +#pragma acc enter data copyin(i) /* { dg-error ".enter/exit data. construct inside of .kernels. region" } */ +#pragma acc exit data delete(i) /* { dg-error ".enter/exit data. construct inside of .kernels. region" } */ } } diff --git a/gcc/testsuite/c-c++-common/gomp/cancel-1.c b/gcc/testsuite/c-c++-common/gomp/cancel-1.c index 13de881d049..896a76858bd 100644 --- a/gcc/testsuite/c-c++-common/gomp/cancel-1.c +++ b/gcc/testsuite/c-c++-common/gomp/cancel-1.c @@ -73,6 +73,18 @@ f2 (void) #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */ } #pragma omp task + { + #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */ + #pragma omp cancel for /* { dg-error "not closely nested inside" } */ + #pragma omp cancel sections /* { dg-error "not closely nested inside" } */ + #pragma omp cancel taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */ + #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */ + #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */ + #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */ + #pragma omp cancellation point taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */ + } + #pragma omp taskgroup + #pragma omp task { #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */ #pragma omp cancel for /* { dg-error "not closely nested inside" } */ @@ -83,6 +95,55 @@ f2 (void) #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */ #pragma omp cancellation point taskgroup } + #pragma omp taskgroup + { + #pragma omp task + { + #pragma omp task + { + #pragma omp cancellation point taskgroup + #pragma omp cancel taskgroup + } + } + } + #pragma omp taskgroup + { + #pragma omp parallel + { + #pragma omp task + { + #pragma omp cancel taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */ + #pragma omp cancellation point taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */ + } + } + #pragma omp target + { + #pragma omp task + { + #pragma omp cancel taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */ + #pragma omp cancellation point taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */ + } + } + #pragma omp target + #pragma omp teams + #pragma omp distribute + for (i = 0; i < 10; i++) + { + #pragma omp task + { + #pragma omp cancel taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */ + #pragma omp cancellation point taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */ + } + } + #pragma omp target data map(i) + { + #pragma omp task + { + #pragma omp cancel taskgroup + #pragma omp cancellation point taskgroup + } + } + } #pragma omp for for (i = 0; i < 10; i++) { @@ -179,14 +240,14 @@ f2 (void) } #pragma omp target teams { - #pragma omp cancel parallel /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */ - #pragma omp cancel for /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */ - #pragma omp cancel sections /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */ - #pragma omp cancel taskgroup /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */ - #pragma omp cancellation point parallel /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */ - #pragma omp cancellation point for /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */ - #pragma omp cancellation point sections /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */ - #pragma omp cancellation point taskgroup /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */ + #pragma omp cancel parallel /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ + #pragma omp cancel for /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ + #pragma omp cancel sections /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ + #pragma omp cancel taskgroup /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ + #pragma omp cancellation point parallel /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ + #pragma omp cancellation point for /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ + #pragma omp cancellation point sections /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ + #pragma omp cancellation point taskgroup /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ } #pragma omp target teams distribute for (i = 0; i < 10; i++) diff --git a/gcc/testsuite/c-c++-common/gomp/clauses-4.c b/gcc/testsuite/c-c++-common/gomp/clauses-4.c index 104b129a9aa..11e7634e14b 100644 --- a/gcc/testsuite/c-c++-common/gomp/clauses-4.c +++ b/gcc/testsuite/c-c++-common/gomp/clauses-4.c @@ -57,40 +57,62 @@ foo (int y, short z) #pragma omp distribute parallel for ordered /* { dg-error ".ordered. is not valid for .#pragma omp distribute parallel for." } */ for (x = 0; x < 64; x++) { - #pragma omp ordered /* { dg-error "ordered region must be closely nested inside a loop region with an ordered clause" } */ + #pragma omp ordered /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */ ; } #pragma omp target teams #pragma omp distribute parallel for simd ordered /* { dg-error ".ordered. is not valid for .#pragma omp distribute parallel for simd." } */ for (x = 0; x < 64; x++) { - #pragma omp ordered simd, threads /* { dg-error "OpenMP constructs other than .#pragma omp ordered simd. may not be nested inside simd region" } */ + #pragma omp ordered simd, threads ; } #pragma omp target #pragma omp teams distribute parallel for ordered /* { dg-error ".ordered. is not valid for .#pragma omp teams distribute parallel for." } */ for (x = 0; x < 64; x++) { - #pragma omp ordered /* { dg-error "ordered region must be closely nested inside a loop region with an ordered clause" } */ + #pragma omp ordered /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */ ; } #pragma omp target #pragma omp teams distribute parallel for simd ordered /* { dg-error ".ordered. is not valid for .#pragma omp teams distribute parallel for simd." } */ for (x = 0; x < 64; x++) { - #pragma omp ordered simd, threads /* { dg-error "OpenMP constructs other than .#pragma omp ordered simd. may not be nested inside simd region" } */ + #pragma omp ordered simd, threads ; } #pragma omp target teams distribute parallel for ordered /* { dg-error ".ordered. is not valid for .#pragma omp target teams distribute parallel for." } */ for (x = 0; x < 64; x++) { - #pragma omp ordered /* { dg-error "ordered region must be closely nested inside a loop region with an ordered clause" } */ + #pragma omp ordered /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */ ; } #pragma omp target teams distribute parallel for simd ordered /* { dg-error ".ordered. is not valid for .#pragma omp target teams distribute parallel for simd." } */ for (x = 0; x < 64; x++) { - #pragma omp ordered simd, threads /* { dg-error "OpenMP constructs other than .#pragma omp ordered simd. may not be nested inside simd region" } */ + #pragma omp ordered simd, threads + ; + } + #pragma omp simd + for (x = 0; x < 64; x++) + { + #pragma omp ordered threads simd /* { dg-error ".ordered simd threads. must be closely nested inside of .for simd. region" } */ + ; + } + #pragma omp for + for (x = 0; x < 64; x++) + { + #pragma omp simd + for (y = 0; y < 16; y++) + { + #pragma omp ordered simd threads /* { dg-error ".ordered simd threads. must be closely nested inside of .for simd. region" } */ + ; + } + } + #pragma omp for simd + for (x = 0; x < 64; x++) + { + #pragma omp ordered threads simd ; } } diff --git a/gcc/testsuite/c-c++-common/gomp/doacross-1.c b/gcc/testsuite/c-c++-common/gomp/doacross-1.c index 89c3dd3c7c6..6244ca08d2c 100644 --- a/gcc/testsuite/c-c++-common/gomp/doacross-1.c +++ b/gcc/testsuite/c-c++-common/gomp/doacross-1.c @@ -32,8 +32,8 @@ foo (void) #pragma omp ordered depend (sink: i - 1, j - 2) /* { dg-error "does not match number" } */ #pragma omp ordered depend (source) } - #pragma omp ordered depend (sink: j) /* { dg-error "clause must be closely nested inside an ordered loop" } */ - #pragma omp ordered depend (source) /* { dg-error "clause must be closely nested inside an ordered loop" } */ + #pragma omp ordered depend (sink: j) /* { dg-error "clause must be closely nested inside an .ordered. loop" } */ + #pragma omp ordered depend (source) /* { dg-error "clause must be closely nested inside an .ordered. loop" } */ #pragma omp for ordered (1) for (i = 0; i < 64; i++) { diff --git a/gcc/testsuite/c-c++-common/gomp/nesting-2.c b/gcc/testsuite/c-c++-common/gomp/nesting-2.c new file mode 100644 index 00000000000..7a03430311d --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/nesting-2.c @@ -0,0 +1,154 @@ +void +foo (void) +{ + int i; + #pragma omp taskloop + for (i = 0; i < 64; i++) + { + int j; + #pragma omp for /* { dg-error "region may not be closely nested inside of" } */ + for (j = 0; j < 10; j++) + ; + #pragma omp single /* { dg-error "region may not be closely nested inside of" } */ + ; + #pragma omp sections /* { dg-error "region may not be closely nested inside of" } */ + { + #pragma omp section + ; + } + #pragma omp barrier /* { dg-error "region may not be closely nested inside of" } */ + #pragma omp master /* { dg-error "region may not be closely nested inside of" } */ + ; + #pragma omp ordered /* { dg-error "region may not be closely nested inside of" } */ + ; + #pragma omp ordered threads /* { dg-error "region may not be closely nested inside of" } */ + ; + #pragma omp ordered simd threads /* { dg-error ".ordered. .simd. must be closely nested inside .simd. region" } */ + ; + #pragma omp simd + for (j = 0; j < 10; j++) + #pragma omp ordered simd + ; + #pragma omp critical + { + #pragma omp simd + for (j = 0; j < 10; j++) + #pragma omp ordered simd + ; + } + } + #pragma omp taskloop + for (i = 0; i < 64; i++) + #pragma omp parallel + { + int j; + #pragma omp for + for (j = 0; j < 10; j++) + ; + #pragma omp single + ; + #pragma omp sections + { + #pragma omp section + ; + } + #pragma omp barrier + #pragma omp master + ; + #pragma omp ordered /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */ + ; + #pragma omp ordered threads /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */ + ; + #pragma omp simd + for (j = 0; j < 10; j++) + #pragma omp ordered simd + ; + #pragma omp critical + { + #pragma omp simd + for (j = 0; j < 10; j++) + #pragma omp ordered simd + ; + } + } + #pragma omp taskloop + for (i = 0; i < 64; i++) + #pragma omp target + { + int j; + #pragma omp for + for (j = 0; j < 10; j++) + ; + #pragma omp single + ; + #pragma omp sections + { + #pragma omp section + ; + } + #pragma omp barrier + #pragma omp master + ; + #pragma omp ordered /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */ + ; + #pragma omp ordered threads /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */ + ; + #pragma omp simd + for (j = 0; j < 10; j++) + #pragma omp ordered simd + ; + #pragma omp critical + { + #pragma omp simd + for (j = 0; j < 10; j++) + #pragma omp ordered simd + ; + } + } + #pragma omp ordered + { + #pragma omp ordered /* { dg-error "region may not be closely nested inside of" } */ + ; + } + #pragma omp ordered threads + { + #pragma omp ordered /* { dg-error "region may not be closely nested inside of" } */ + ; + } + #pragma omp ordered + { + #pragma omp ordered threads /* { dg-error "region may not be closely nested inside of" } */ + ; + } + #pragma omp ordered threads + { + #pragma omp ordered threads /* { dg-error "region may not be closely nested inside of" } */ + ; + } + #pragma omp critical + { + #pragma omp ordered simd /* { dg-error ".ordered. .simd. must be closely nested inside .simd. region" } */ + ; + } + #pragma omp for ordered + for (i = 0; i < 64; i++) + #pragma omp parallel + { + #pragma omp ordered threads /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */ + ; + } + #pragma omp for ordered + for (i = 0; i < 64; i++) + #pragma omp parallel + { + #pragma omp ordered /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */ + ; + } + #pragma omp for ordered(1) + for (i = 0; i < 64; i++) + #pragma omp parallel + { + #pragma omp ordered depend(source) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + #pragma omp ordered depend(sink: i - 1) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/nesting-warn-1.c b/gcc/testsuite/c-c++-common/gomp/nesting-warn-1.c index 92ced709907..800ad532108 100644 --- a/gcc/testsuite/c-c++-common/gomp/nesting-warn-1.c +++ b/gcc/testsuite/c-c++-common/gomp/nesting-warn-1.c @@ -5,19 +5,19 @@ f_omp_target (void) { #pragma omp target { -#pragma omp target /* { dg-warning "target construct inside of target region" } */ +#pragma omp target /* { dg-warning ".target. construct inside of .target. region" } */ ; -#pragma omp target data map(i) /* { dg-warning "target data construct inside of target region" } */ +#pragma omp target data map(i) /* { dg-warning ".target data. construct inside of .target. region" } */ ; -#pragma omp target update to(i) /* { dg-warning "target update construct inside of target region" } */ +#pragma omp target update to(i) /* { dg-warning ".target update. construct inside of .target. region" } */ #pragma omp parallel { -#pragma omp target /* { dg-warning "target construct inside of target region" } */ +#pragma omp target /* { dg-warning ".target. construct inside of .target. region" } */ ; -#pragma omp target data map(i) /* { dg-warning "target data construct inside of target region" } */ +#pragma omp target data map(i) /* { dg-warning ".target data. construct inside of .target. region" } */ ; -#pragma omp target update to(i) /* { dg-warning "target update construct inside of target region" } */ +#pragma omp target update to(i) /* { dg-warning ".target update. construct inside of .target. region" } */ } } } diff --git a/gcc/testsuite/c-c++-common/gomp/ordered-3.c b/gcc/testsuite/c-c++-common/gomp/ordered-3.c index 1d7ff80f743..3c107232c0d 100644 --- a/gcc/testsuite/c-c++-common/gomp/ordered-3.c +++ b/gcc/testsuite/c-c++-common/gomp/ordered-3.c @@ -59,6 +59,18 @@ foo (void) #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ } + #pragma omp parallel for ordered + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + } + #pragma omp parallel for + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + } } void diff --git a/gcc/testsuite/c-c++-common/gomp/ordered-4.c b/gcc/testsuite/c-c++-common/gomp/ordered-4.c new file mode 100644 index 00000000000..b56843c0bb1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/ordered-4.c @@ -0,0 +1,54 @@ +void +f1 (void) +{ + int i, j; + #pragma omp critical + { + #pragma omp simd + for (i = 0; i < 64; i++) + { + #pragma omp ordered simd + ; + } + } + #pragma omp ordered threads + { + #pragma omp simd + for (i = 0; i < 64; i++) + { + #pragma omp ordered simd + ; + } + } + #pragma omp task + { + #pragma omp simd + for (i = 0; i < 64; i++) + { + #pragma omp ordered simd + ; + } + } + #pragma omp taskloop + for (j = 0; j < 64; j++) + #pragma omp simd + for (i = 0; i < 64; i++) + { + #pragma omp ordered simd + ; + } +} + +void +f2 (void) +{ + #pragma omp ordered simd + ; +} + +void +f3 (void) +{ + #pragma omp ordered threads , simd + ; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc new file mode 100644 index 00000000000..1114ebdda82 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc @@ -0,0 +1,33 @@ +/* { dg-options "-fcilkplus" } */ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +#include +#include +#include + +template +void do_not_optimize_away(T&& x) { + asm volatile("" : "+r"(x)); +} + +const int N = 1'000'000; + +auto compute() { + std::vector v(N); + auto rng = std::mt19937{std::random_device{}()}; + std::uniform_real_distribution dist(0, 1); + for (int i = 0; i < N; ++i) v[i] = std::log(std::sqrt(dist(rng))); + return v; +} + +int main() { + std::vector v1, v2, v3; + cilk_spawn [&] { v1 = compute(); }(); + cilk_spawn [&] { v2 = compute(); }(); + v3 = compute(); + do_not_optimize_away(v1.data()); + do_not_optimize_away(v2.data()); + do_not_optimize_away(v3.data()); + return 0; +} diff --git a/gcc/testsuite/g++.dg/concepts/generic-fn-err.C b/gcc/testsuite/g++.dg/concepts/generic-fn-err.C index c6b74571954..1e975108257 100644 --- a/gcc/testsuite/g++.dg/concepts/generic-fn-err.C +++ b/gcc/testsuite/g++.dg/concepts/generic-fn-err.C @@ -11,8 +11,8 @@ template class X> struct S { }; -void f1(Int) { } // { dg-error "invalid" } -void f2(Template) { } // { dg-error "invalid" } +void f1(Int) { } // { dg-error "" } +void f2(Template) { } // { dg-error "" } struct S1 { void f1(auto x) { } diff --git a/gcc/testsuite/g++.dg/concepts/placeholder6.C b/gcc/testsuite/g++.dg/concepts/placeholder6.C new file mode 100644 index 00000000000..7f2e67a9192 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/placeholder6.C @@ -0,0 +1,10 @@ +// { dg-options -std=c++1z } + +template struct B { static const int i = I; }; +template concept bool Few = I < 10; + +constexpr int g(B b) { return b.i; } + +#define SA(X) static_assert((X),#X) +SA(g(B<2>{}) == 2); +SA(g(B<10>{}) == 10); // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/gomp/ordered-2.C b/gcc/testsuite/g++.dg/gomp/ordered-2.C index 6c2b4329c64..7ec6333527a 100644 --- a/gcc/testsuite/g++.dg/gomp/ordered-2.C +++ b/gcc/testsuite/g++.dg/gomp/ordered-2.C @@ -3,5 +3,5 @@ void f1(void) { #pragma omp ordered asdf /* { dg-error "expected" } */ - #pragma omp ordered + #pragma omp ordered /* { dg-error "region may not be closely nested inside of" } */ } /* { dg-error "expected" } */ diff --git a/gcc/testsuite/g++.dg/lto/pr68057_0.C b/gcc/testsuite/g++.dg/lto/pr68057_0.C new file mode 100644 index 00000000000..4e124d7f5e8 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/pr68057_0.C @@ -0,0 +1,23 @@ +// { dg-lto-do link } +/* { dg-extra-ld-options { -O2 -Wno-odr -r -nostdlib } } */ +struct SPxPricer; +struct SoPlex { + virtual void setPricer(SPxPricer *); +}; +struct SPxPricer { + virtual void load(SoPlex *); +}; +struct SLUFactor { + SLUFactor(); + virtual ~SLUFactor(); +}; +struct SPxSolver : SoPlex { + SPxPricer pr; + SLUFactor slu; + SPxSolver(); +}; +struct A : SPxSolver {}; +A a; + +void SoPlex::setPricer(SPxPricer *p1) { p1->load(this); } + diff --git a/gcc/testsuite/g++.dg/lto/pr68057_1.C b/gcc/testsuite/g++.dg/lto/pr68057_1.C new file mode 100644 index 00000000000..f45a81ec88b --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/pr68057_1.C @@ -0,0 +1,17 @@ +struct SPxPricer; +struct SoPlex { + virtual void setPricer(SPxPricer *); +}; +struct SPxPricer { + virtual void load(SoPlex *); +}; +struct SLUFactor { + SLUFactor(); + virtual ~SLUFactor(); +}; +struct SPxSolver : SoPlex { + SPxPricer pr; + SLUFactor slu; + SPxSolver(); +}; +SPxSolver::SPxSolver() { setPricer(&pr); } diff --git a/gcc/testsuite/g++.dg/torture/pr68220.C b/gcc/testsuite/g++.dg/torture/pr68220.C new file mode 100644 index 00000000000..3b27653219c --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr68220.C @@ -0,0 +1,238 @@ +// { dg-do compile } +namespace mpl { +template struct lambda; +template struct if_ { typedef T3 type; }; +template struct arg { + template struct apply { typedef U1 type; }; +}; +template struct begin_impl; +template struct begin { + typedef typename Sequence::tag tag_; + typedef typename begin_impl::template apply::type type; +}; +template struct O1_size_impl; +} +template struct long_ { static const long value = N; }; +namespace mpl { +template +struct O1_size + : O1_size_impl::template apply {}; +typedef arg<1> _1; +template struct protect : T {}; +template struct apply_wrap1 : F::template apply {}; +template +struct apply_wrap2 : F::template apply {}; +template struct apply_wrap5 : F::template apply {}; +template +struct resolve_bind_arg; +template struct replace_unnamed_arg { typedef T type; }; +template struct bind1 { + template struct apply { + typedef typename apply_wrap1::type type; + }; +}; +template +struct resolve_bind_arg, U1, U2, U3, U4, U5> { + typedef typename apply_wrap5>::type type; +}; +template struct bind2 { + template struct apply { + typedef resolve_bind_arg>::type, U1, + U2, int, int, int> t2; + typedef typename apply_wrap2::type + type; + }; +}; +template struct quote_impl { typedef T type; }; +template