This fixes an error wherein a nontrivial expression oassed to an Altivec built-in results in an ICE, following Joseph Myers's suggested approach in the bugzilla.
Bootstrapped and tested with no new regressions on powerpc64-unknown-linux-gnu. Ok for trunk? Thanks, Bill gcc: 2012-04-24 Bill Schmidt <wschm...@linux.vnet.ibm.com> PR target/47197 * config/rs6000/rs6000-c.c (fully_fold_convert): New function. (altivec_build_resolved_builtin): Call fully_fold_convert. gcc/testsuite: 2012-04-24 Bill Schmidt <wschm...@linux.vnet.ibm.com> PR target/47197 * gcc.target/powerpc/pr47197.c: New test. Index: gcc/testsuite/gcc.target/powerpc/pr47197.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr47197.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr47197.c (revision 0) @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-maltivec" } */ + +/* Compile-only test to ensure that expressions can be passed to + Altivec builtins without error. */ + +#include <altivec.h> + +void func(unsigned char *buf, unsigned len) +{ + vec_dst(buf, (len >= 256 ? 0 : len) | 512, 2); +} Index: gcc/config/rs6000/rs6000-c.c =================================================================== --- gcc/config/rs6000/rs6000-c.c (revision 186761) +++ gcc/config/rs6000/rs6000-c.c (working copy) @@ -3421,6 +3421,22 @@ rs6000_builtin_type_compatible (tree t, int id) } +/* In addition to calling fold_convert for EXPR of type TYPE, also + call c_fully_fold to remove any C_MAYBE_CONST_EXPRs that could be + hiding there (PR47197). */ + +static tree +fully_fold_convert (tree type, tree expr) +{ + tree result = fold_convert (type, expr); + bool maybe_const = true; + + if (!c_dialect_cxx ()) + result = c_fully_fold (result, false, &maybe_const); + + return result; +} + /* Build a tree for a function call to an Altivec non-overloaded builtin. The overloaded builtin that matched the types and args is described by DESC. The N arguments are given in ARGS, respectively. @@ -3470,18 +3486,18 @@ altivec_build_resolved_builtin (tree *args, int n, break; case 1: call = build_call_expr (impl_fndecl, 1, - fold_convert (arg_type[0], args[0])); + fully_fold_convert (arg_type[0], args[0])); break; case 2: call = build_call_expr (impl_fndecl, 2, - fold_convert (arg_type[0], args[0]), - fold_convert (arg_type[1], args[1])); + fully_fold_convert (arg_type[0], args[0]), + fully_fold_convert (arg_type[1], args[1])); break; case 3: call = build_call_expr (impl_fndecl, 3, - fold_convert (arg_type[0], args[0]), - fold_convert (arg_type[1], args[1]), - fold_convert (arg_type[2], args[2])); + fully_fold_convert (arg_type[0], args[0]), + fully_fold_convert (arg_type[1], args[1]), + fully_fold_convert (arg_type[2], args[2])); break; default: gcc_unreachable ();