Bug 56541 - vectorizaton fails in conditional assignment of a constant
Summary: vectorizaton fails in conditional assignment of a constant
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: ---
Assignee: bin cheng
Keywords: missed-optimization
Depends on:
Blocks: vectorizer
  Show dependency treegraph
Reported: 2013-03-05 16:44 UTC by vincenzo Innocente
Modified: 2017-02-24 10:35 UTC (History)
0 users

See Also:
Known to work:
Known to fail:
Last reconfirmed: 2013-03-06 00:00:00


Note You need to log in before you can comment on or make changes to this bug.
Description vincenzo Innocente 2013-03-05 16:44:14 UTC
this loop does not vectorize

float a,b,c,d;

float z[1024]; bool ok[1024];
constexpr float rBig = 150.;

void foo() {
  for (int i=0;i!=1024;++i) {
    float rR = a*z[i];
    float rL = b*z[i];
    float rMin = (rR<rL) ? rR : rL;  
    float rMax = (rR<rL) ? rL : rR;  
    //rMin = (rMax>0) ? rMin : rBig+std::abs(z[i]); // this vectorize (sic...)
    rMin = (rMax>0) ? rMin : rBig; // comment to vectorize
    rMin = (rMin>0) ? rMin : rMax; 
    ok[i] = rMin-c<rMax+d;


c++ -std=c++11 -Ofast -march=corei7 -c range.cc -ftree-vectorizer-verbose=1

Analyzing loop at range.cc:8
range.cc:7: note: vectorized 0 loops in function.
range.cc:16: note: vect_recog_bool_pattern: detected: 
range.cc:16: note: pattern recognized: VIEW_CONVERT_EXPR<unsigned char>(ok[i_22]) = patt_15;
range.cc:16: note: additional pattern stmt: patt_13 = _14 < _16 ? 1 : 0;

adding to "rBig" std::abs(z[i]) it does
c++ -std=c++11 -Ofast -march=corei7 -c range.cc -ftree-vectorizer-verbose=1

Analyzing loop at range.cc:8

range.cc:8: note: vect_recog_bool_pattern: detected: 
range.cc:8: note: pattern recognized: VIEW_CONVERT_EXPR<unsigned char>(ok[i_24]) = patt_16;

range.cc:8: note: additional pattern stmt: patt_14 = _15 < _17 ? 1 : 0;

Vectorizing loop at range.cc:8

range.cc:8: note: LOOP VECTORIZED.
range.cc:7: note: vectorized 1 loops in function.
Comment 1 Richard Biener 2013-03-06 09:13:29 UTC
if-conversion is confused by the three-argument PHI node:

  <bb 6>:
  # rMin_3 = PHI <rMin_11(5), rMin_12(4), 1.5e+2(3)>

that occurs because of the forwarder block (which isn't one in the
case the addition appears).  DOM produces this by threading

  if (rMin_12 > 0.0)
    goto <bb 4>;
    goto <bb 5>;

  <bb 4>:

  <bb 5>:
  # rMin_2 = PHI <rMin_11(4), 1.5e+2(3)>
  if (rMin_2 > 0.0)
    goto <bb 7>;
    goto <bb 6>;
  <bb 7>:
  # rMin_3 = PHI <rMin_2(5), rMin_12(6)>

for rMin_2 == 1.5e+2.  That's a good optimization.
Comment 2 Alan Lawrence 2015-06-11 15:29:59 UTC
If-conversion will handle the three-arg phi node, if aggressive_if_conv is true, i.e. if loop->force_vectorize. I believe it's possible to set this using a #pragma (?), but I haven't managed yet. A question might be whether it's safe to deal with three-arg phi-nodes when !aggressive_if_conv...
Comment 3 bin cheng 2016-05-03 09:05:18 UTC
Author: amker
Date: Tue May  3 09:04:46 2016
New Revision: 235808

URL: https://gcc.gnu.org/viewcvs?rev=235808&root=gcc&view=rev
	PR tree-optimization/56541
	* doc/invoke.texi (@item max-tree-if-conversion-phi-args): New item.
	* params.def (PARAM_MAX_TREE_IF_CONVERSION_PHI_ARGS): new param.
	* tree-if-conv.c (MAX_PHI_ARG_NUM): new macro.
	(any_complicated_phi): new static variable.
	(aggressive_if_conv): delete.
	(if_convertible_phi_p): support phis with more than two arguments.
	(if_convertible_bb_p): remvoe check on aggressive_if_conv and
	critical pred edges.
	(ifcvt_split_critical_edges): support phis with more than two
	arguments by checking new parameter.  only split critical edges
	if needed.
	(tree_if_conversion): handle simd pragma marked loop using new
	local variable aggressive_if_conv.  check any_complicated_phi.

	PR tree-optimization/56541
	* gcc.dg/tree-ssa/ifc-pr56541.c: new test.
	* gcc.dg/vect/pr56541.c: new test.

Comment 4 bin cheng 2017-02-24 10:35:07 UTC
Fixed on trunk.