On Mon, Aug 22, 2011 at 2:05 PM, Artem Shinkarov <artyom.shinkar...@gmail.com> wrote: > On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther > <richard.guent...@gmail.com> wrote: >> On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov >> <artyom.shinkar...@gmail.com> wrote: >>> Richard >>> >>> I formalized an approach a little-bit, now it works without target >>> hooks, but some polishing is still required. I want you to comment on >>> the several important approaches that I use in the patch. >>> >>> So how does it work. >>> 1) All the vector comparisons at the level of type-checker are >>> introduced using VEC_COND_EXPR with constant selection operands being >>> {-1} and {0}. For example v0 > v1 is transformed into VEC_COND_EXPR<v0 >>>> v1, {-1}, {0}>. >>> >>> 2) When optabs expand VEC_COND_EXPR, two cases are considered: >>> 2.a) first operand of VEC_COND_EXPR is comparison, in that case nothing >>> changes. >>> 2.b) first operand is something else, in that case, we specially mark >>> this case, recognize it in the backend, and do not create a >>> comparison, but use the mask as it was a result of some comparison. >>> >>> 3) In order to make sure that mask in VEC_COND_EXPR<mask, v0, v1> is a >>> vector comparison we use is_vector_comparison function, if it returns >>> false, then we replace mask with mask != {0}. >>> >>> So we end-up with the following functionality: >>> VEC_COND_EXPR<mask, v0,v1> -- if we know that mask is a result of >>> comparison of two vectors, we leave it as it is, otherwise change with >>> mask != {0}. >>> >>> Plain vector comparison a <op> b is represented with VEC_COND_EXPR, >>> which correctly expands, without creating useless masking. >>> >>> >>> Basically for me there are two questions: >>> 1) Can we perform information passing in optabs in a nicer way? >>> 2) How is_vector_comparison could be improved? I have several ideas, >>> like checking if constant vector all consists of 0 and -1, and so on. >>> But first is it conceptually fine. >>> >>> P.S. I tired to put the functionality of is_vector_comparison in >>> tree-ssa-forwprop, but the thing is that it is called only with -On, >>> which I find inappropriate, and the functionality gets more >>> complicated. >> >> Why is it inappropriate to not optimize it at -O0? If the user >> separates comparison and ?: expression it's his own fault. > > Well, because all the information is there, and I perfectly envision > the case when user expressed comparison separately, just to avoid code > duplication. > > Like: > mask = a > b; > res1 = mask ? v0 : v1; > res2 = mask ? v2 : v3; > > Which in this case would be different from > res1 = a > b ? v0 : v1; > res2 = a > b ? v2 : v3; > >> Btw, the new hook is still in the patch. >> >> I would simply always create != 0 if it isn't and let optimizers >> (tree-ssa-forwprop.c) optimize this. You still have to deal with >> non-comparison operands during expansion though, but if >> you always forced a != 0 from the start you can then simply >> interpret it as a proper comparison result (in which case I'd >> modify the backends to have an alternate pattern or directly >> expand to masking operations - using the fake comparison >> RTX is too much of a hack). > > Richard, I think you didn't get the problem. > I really need the way, to pass the information, that the expression > that is in the first operand of vcond is an appropriate mask. I though > for quite a while and this hack is the only answer I found, is there a > better way to do that. I could for example introduce another > tree-node, but it would be overkill as well. > > Now why do I need it so much: > I want to implement the comparison in a way that {1, 5, 0, -1} is > actually {-1,-1,-1,-1}. So whenever I am not sure that mask of > VEC_COND_EXPR is a real comparison I transform it to mask != {0} (not > always). To check the stuff, I use is_vector_comparison in > tree-vect-generic. > > So I really have the difference between mask ? x : y and mask != {0} ? > x : y, otherwise I could treat mask != {0} in the backend as just > mask. > > If this link between optabs and backend breaks, then the patch falls > apart. Because every time the comparison is taken out VEC_COND_EXPR, I > will have to put != {0}. Keep in mind, that I cannot always put the > comparison inside the VEC_COND_EXPR, what if it is defined in a > function-comparison, or somehow else? > > So what would be an appropriate way to connect optabs and the backend?
Well, there is no problem in having the only valid mask operand for VEC_COND_EXPRs being either a comparison or a {-1,...} / {0,....} mask. Just the C parser has to transform mask ? vec1 : vec2 to mask != 0 ? vec1 : vec2. This comparison can be eliminated by optimization passes that either replace it by the real comparison computing the mask or just propagating the information this mask is already {-1,...} / {0,....} by simply dropping the comparison against zero. For the backends I'd have vcond patterns for both an embedded comparison and for a mask. (Now we can rewind the discussion a bit and allow arbitrary masks and define a vcond with a mask operand to do bitwise selection - what matters is the C frontend semantics which we need to translate to what the middle-end thinks of a VEC_COND_EXPR, they do not have to agree). If the mask is computed by a function you are of course out of luck, but I don't see how you'd manage to infer knowledge from nowhere either. Richard. > > Thanks, > Artem. > > All the rest would be adjusted later. > >> tree >> constant_boolean_node (int value, tree type) >> { >> - if (type == integer_type_node) >> + if (TREE_CODE (type) == VECTOR_TYPE) >> + { >> + tree tval; >> + >> + gcc_assert (TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE); >> + tval = build_int_cst (TREE_TYPE (type), value); >> + return build_vector_from_val (type, tval); >> >> as value is either 0 or 1 that won't work. Oh, I see you pass -1 >> for true in the callers. But I think we should simply decide that true (1) >> means -1 for a vector boolean node (and the value parameter should >> be a bool instead). Thus, >> >> + if (TREE_CODE (type) == VECTOR_TYPE) >> + { >> + tree tval; >> + >> + gcc_assert (TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE); >> + tval = build_int_cst (TREE_TYPE (type), value ? -1 : 0); >> + return build_vector_from_val (type, tval); >> >> instead. >> >> @@ -9073,26 +9082,29 @@ fold_comparison (location_t loc, enum tr >> floating-point, we can only do some of these simplifications.) */ >> if (operand_equal_p (arg0, arg1, 0)) >> { >> + int true_val = TREE_CODE (type) == VECTOR_TYPE ? -1 : 0; >> + tree arg0_type = TREE_TYPE (arg0); >> + >> >> as I said this is not necessary - the FLOAT_TYPE_P and HONOR_NANS >> macros work perfectly fine on vector types. >> >> Richard. >> >>> >>> Thanks, >>> Artem. >>> >> >