On Tue, 23 Jul 2024, Jakub Jelinek wrote: > On Tue, Jul 23, 2024 at 08:42:24AM +0200, Richard Biener wrote: > > On Tue, 23 Jul 2024, Jakub Jelinek wrote: > > > The folding into REALPART_EXPR is correct, used only when the mem_offset > > > is zero, but for IMAGPART_EXPR it didn't check the exact offset value > > > (just > > > that it is not 0). > > > The following patch fixes that by using IMAGPART_EXPR only if the offset > > > is right and using BITFIELD_REF or whatever else otherwise. > > > > > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk, 14.2 > > > and other release branches? > > > > I think this is not enough - what kind of GIMPLE does this result in? > > If it is > __builtin_memmove (&g, 2 + (char *) &c, 2); > then > _1 = &c + 2; > _3 = MEM <unsigned short> [(char * {ref-all})_1]; > is optimized to > _3 = IMAGPART_EXPR <c_6(D)>; > as before. If it is > __builtin_memmove (&g, 1 + (char *) &c, 2); > from the testcase, then > _1 = &c + 1; > _3 = MEM <unsigned short> [(char * {ref-all})_1]; > is optimized to > _3 = BIT_FIELD_REF <c_6(D), 16, 8>; > and that is expanded correctly. > > > You should amend the checking in non_rewritable_mem_ref_base as well, > > it should fail when the corresponding rewrite doesn't work. > > That is already the case I believe. > non_rewritable_mem_ref_base rejects it in the VECTOR_TYPE/COMPLEX_TYPE > case (so doesn't return NULL), but then falls through the > /* For integral typed extracts we can use a BIT_FIELD_REF. */ > check and returns NULL_TREE there. > But then maybe_rewrite_mem_ref_base triggers already on the COMPLEX_TYPE > case. > > > I suspect it falls through to the BIT_FIELD_REF code? > > > > That said, can you match up the offset check with that of > > non_rewritable_mem_ref_base then, particularly > > > > if ((VECTOR_TYPE_P (TREE_TYPE (decl)) > > || TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE) > > && useless_type_conversion_p (TREE_TYPE (base), > > TREE_TYPE (TREE_TYPE (decl))) > > && known_ge (mem_ref_offset (base), 0) > > && known_gt (wi::to_poly_offset (TYPE_SIZE_UNIT (TREE_TYPE > > (decl))), > > mem_ref_offset (base)) > > && multiple_p (mem_ref_offset (base), > > wi::to_poly_offset (TYPE_SIZE_UNIT (TREE_TYPE > > (base))))) > > > > I suppose this check should be adjusted to use the three arg multiple_p > > and check the factor against 0/1 for COMPLEX_TYPE.
Ah, reading the above again it should alreeady ensure the offset is for the real or imag part only - I was thinking it might allow larger aligned offsets. Thus your original patch is OK. I think an improvement would really be to merge the two functions. Thanks, Richard. > Isn't that just too complex/expensive for something as simple as > mem_ref_offset (base) is 0 or TYPE_SIZE_UNIT? > That > integer_zerop () || tree_int_cst_equal looked much cheaper. > Sure, it could be done on poly_int_cst instead if that looks better: > && (known_eq (mem_ref_offset (base), 0) > || known_eq (mem_ref_offset (base), > wi::to_poly_offset (TYPE_SIZE_UNIT (TREE_TYPE (decl)))) > And shouldn't we cache those mem_ref_offset (base) and > wi::to_poly_offset (TYPE_SIZE_UNIT (TREE_TYPE (decl))) > which are used in multiple spots? > > Anyway, yet another option because non_rewritable_mem_ref_base has > the VECTOR/COMPLEX types cases together would be to have them together > in maybe_rewrite_mem_ref_base too, so do: > if ((VECTOR_TYPE_P (TREE_TYPE (sym)) > || TREE_CODE (TREE_TYPE (sym)) == COMPLEX_TYPE) > && useless_type_conversion_p (TREE_TYPE (*tp), > TREE_TYPE (TREE_TYPE (sym))) > && multiple_p (mem_ref_offset (*tp), > wi::to_poly_offset (TYPE_SIZE_UNIT (TREE_TYPE > (*tp))))) > { > if (VECTOR_TYPE_P (TREE_TYPE (sym))) > *tp = build3 (BIT_FIELD_REF, TREE_TYPE (*tp), sym, > TYPE_SIZE (TREE_TYPE (*tp)), > int_const_binop (MULT_EXPR, > bitsize_int (BITS_PER_UNIT), > TREE_OPERAND (*tp, 1))); > else > *tp = build1 (integer_zerop (TREE_OPERAND (*tp, 1)) > ? REALPART_EXPR : IMAGPART_EXPR, > TREE_TYPE (*tp), sym); > } > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)