When compiling the following code with -O0 -maltivec: typedef union { int i[4]; __attribute__((altivec(vector__))) int v; } vec_int4;
int main (void) { vec_int4 i1; i1.v = (__attribute__((altivec(vector__))) int){31, 31, 31, 31}; printf ("%d\n", i1.i[0]); return 0; } the output printed is 30, not 31. The load of the vector constant is done by the following pair of instructions: vspltisw 0,15 vadduwm 0,0,0 which are generated by this splitter in altivec.md: (define_split [(set (match_operand:VI 0 "altivec_register_operand" "") (match_operand:VI 1 "easy_vector_constant_add_self" ""))] "TARGET_ALTIVEC && reload_completed" [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (plus:VI (match_dup 0) (match_dup 0)))] { rtx dup = gen_easy_altivec_constant (operands[1]); rtx const_vec; /* Divide the operand of the resulting VEC_DUPLICATE, and use simplify_rtx to make a CONST_VECTOR. */ XEXP (dup, 0) = simplify_const_binary_operation (ASHIFTRT, QImode, XEXP (dup, 0), const1_rtx); const_vec = simplify_rtx (dup); if (GET_MODE (const_vec) == <MODE>mode) operands[3] = const_vec; else operands[3] = gen_lowpart (<MODE>mode, const_vec); }) Now, easy_vector_constand_add_self accepts all constants between 16 and 31, where I think it should really only be accepting *even* constants. The test is really implemented in rs6000.h: #define EASY_VECTOR_15_ADD_SELF(n) (!EASY_VECTOR_15((n)) \ && EASY_VECTOR_15((n) >> 1)) and adding a condition ((n) & 1) == 0 here fixes the problem. Is this the proper solution? -- Summary: Invalid altivec constant loading code Product: gcc Version: 4.2.0 Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: target AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: uweigand at gcc dot gnu dot org GCC target triplet: powerpc-*-linux* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27006