This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR33627, invalid COND_EXPR_COND with ifcombine


This fixes ifcombine to canonicalize folded conditions appropriately
for COND_EXPR_COND (it somehow sucks that fold and verify_stmts don't
agree what is canonical here).  Fortunately we went through this before
and so I split out a common function to do the work.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to mainline.

Richard.

2007-10-02  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/33627
	* tree-gimple.h (canonicalize_cond_expr_cond): Declare.
	* tree-gimple.c (canonicalize_cond_expr_cond): New function,
	split out from ...
	* tree-ssa-forwprop.c (combine_cond_expr_cond): ... here.
	* tree-ssa-ifcombine.c (ifcombine_iforif): Use it.

	* g++.dg/torture/pr33627.C: New testcase.

Index: gcc/tree-gimple.h
===================================================================
*** gcc/tree-gimple.h	(revision 128957)
--- gcc/tree-gimple.h	(working copy)
*************** extern enum gimplify_status gimplify_va_
*** 133,138 ****
--- 133,139 ----
  struct gimplify_omp_ctx;
  extern void omp_firstprivatize_variable (struct gimplify_omp_ctx *, tree);
  extern tree gimple_boolify (tree);
+ extern tree canonicalize_cond_expr_cond (tree);
  
  /* In omp-low.c.  */
  extern void diagnose_omp_structured_block_errors (tree);
Index: gcc/tree-gimple.c
===================================================================
*** gcc/tree-gimple.c	(revision 128957)
--- gcc/tree-gimple.c	(working copy)
*************** recalculate_side_effects (tree t)
*** 521,523 ****
--- 521,567 ----
        gcc_unreachable ();
     }
  }
+ 
+ /* Canonicalize a tree T for use in a COND_EXPR as conditional.  Returns
+    a canonicalized tree that is valid for a COND_EXPR or NULL_TREE, if
+    we failed to create one.  */
+ 
+ tree
+ canonicalize_cond_expr_cond (tree t)
+ {
+   /* For (bool)x use x != 0.  */
+   if (TREE_CODE (t) == NOP_EXPR
+       && TREE_TYPE (t) == boolean_type_node)
+     {
+       tree top0 = TREE_OPERAND (t, 0);
+       t = build2 (NE_EXPR, TREE_TYPE (t),
+ 		  top0, build_int_cst (TREE_TYPE (top0), 0));
+     }
+   /* For !x use x == 0.  */
+   else if (TREE_CODE (t) == TRUTH_NOT_EXPR)
+     {
+       tree top0 = TREE_OPERAND (t, 0);
+       t = build2 (EQ_EXPR, TREE_TYPE (t),
+ 		  top0, build_int_cst (TREE_TYPE (top0), 0));
+     }
+   /* For cmp ? 1 : 0 use cmp.  */
+   else if (TREE_CODE (t) == COND_EXPR
+ 	   && COMPARISON_CLASS_P (TREE_OPERAND (t, 0))
+ 	   && integer_onep (TREE_OPERAND (t, 1))
+ 	   && integer_zerop (TREE_OPERAND (t, 2)))
+     {
+       tree top0 = TREE_OPERAND (t, 0);
+       t = build2 (TREE_CODE (top0), TREE_TYPE (t),
+ 		  TREE_OPERAND (top0, 0), TREE_OPERAND (top0, 1));
+     }
+ 
+   /* A valid conditional for a COND_EXPR is either a gimple value
+      or a comparison with two gimple value operands.  */
+   if (is_gimple_val (t)
+       || (COMPARISON_CLASS_P (t)
+ 	  && is_gimple_val (TREE_OPERAND (t, 0))
+ 	  && is_gimple_val (TREE_OPERAND (t, 1))))
+     return t;
+ 
+   return NULL_TREE;
+ }
Index: gcc/tree-ssa-forwprop.c
===================================================================
*** gcc/tree-ssa-forwprop.c	(revision 128957)
--- gcc/tree-ssa-forwprop.c	(working copy)
*************** combine_cond_expr_cond (enum tree_code c
*** 326,371 ****
    /* Require that we got a boolean type out if we put one in.  */
    gcc_assert (TREE_CODE (TREE_TYPE (t)) == TREE_CODE (type));
  
!   /* For (bool)x use x != 0.  */
!   if (TREE_CODE (t) == NOP_EXPR
!       && TREE_TYPE (t) == boolean_type_node)
!     {
!       tree top0 = TREE_OPERAND (t, 0);
!       t = build2 (NE_EXPR, type,
! 		  top0, build_int_cst (TREE_TYPE (top0), 0));
!     }
!   /* For !x use x == 0.  */
!   else if (TREE_CODE (t) == TRUTH_NOT_EXPR)
!     {
!       tree top0 = TREE_OPERAND (t, 0);
!       t = build2 (EQ_EXPR, type,
! 		  top0, build_int_cst (TREE_TYPE (top0), 0));
!     }
!   /* For cmp ? 1 : 0 use cmp.  */
!   else if (TREE_CODE (t) == COND_EXPR
! 	   && COMPARISON_CLASS_P (TREE_OPERAND (t, 0))
! 	   && integer_onep (TREE_OPERAND (t, 1))
! 	   && integer_zerop (TREE_OPERAND (t, 2)))
!     {
!       tree top0 = TREE_OPERAND (t, 0);
!       t = build2 (TREE_CODE (top0), type,
! 		  TREE_OPERAND (top0, 0), TREE_OPERAND (top0, 1));
!     }
  
    /* Bail out if we required an invariant but didn't get one.  */
!   if (invariant_only
!       && !is_gimple_min_invariant (t))
      return NULL_TREE;
  
!   /* A valid conditional for a COND_EXPR is either a gimple value
!      or a comparison with two gimple value operands.  */
!   if (is_gimple_val (t)
!       || (COMPARISON_CLASS_P (t)
! 	  && is_gimple_val (TREE_OPERAND (t, 0))
! 	  && is_gimple_val (TREE_OPERAND (t, 1))))
!     return t;
! 
!   return NULL_TREE;
  }
  
  /* Propagate from the ssa name definition statements of COND_EXPR
--- 326,341 ----
    /* Require that we got a boolean type out if we put one in.  */
    gcc_assert (TREE_CODE (TREE_TYPE (t)) == TREE_CODE (type));
  
!   /* Canonicalize the combined condition for use in a COND_EXPR.  */
!   t = canonicalize_cond_expr_cond (t);
  
    /* Bail out if we required an invariant but didn't get one.  */
!   if (!t
!       || (invariant_only
! 	  && !is_gimple_min_invariant (t)))
      return NULL_TREE;
  
!   return t;
  }
  
  /* Propagate from the ssa name definition statements of COND_EXPR
Index: gcc/tree-ssa-ifcombine.c
===================================================================
*** gcc/tree-ssa-ifcombine.c	(revision 128957)
--- gcc/tree-ssa-ifcombine.c	(working copy)
*************** ifcombine_iforif (basic_block inner_cond
*** 483,488 ****
--- 483,491 ----
        /* Do it.  */
        t = fold_build2 (code, boolean_type_node,
  		       TREE_OPERAND (ccond2, 0), TREE_OPERAND (ccond2, 1));
+       t = canonicalize_cond_expr_cond (t);
+       if (!t)
+ 	return false;
        COND_EXPR_COND (inner_cond) = t;
        update_stmt (inner_cond);
  
Index: gcc/testsuite/g++.dg/torture/pr33627.C
===================================================================
*** gcc/testsuite/g++.dg/torture/pr33627.C	(revision 0)
--- gcc/testsuite/g++.dg/torture/pr33627.C	(revision 0)
***************
*** 0 ****
--- 1,55 ----
+ typedef unsigned int UT_uint32;
+ typedef UT_uint32 PT_DocPosition;
+ typedef UT_uint32 PT_BlockOffset;
+ typedef enum _PTStruxType { PTX_Block } PTStruxType;
+ typedef UT_uint32 PL_ListenerId;
+ typedef const void * PL_StruxFmtHandle;
+ class PX_ChangeRecord;
+ class pf_Frag {
+   public:
+    typedef enum _PFType { PFT_Object } PFType;
+    inline PFType getType(void) const { }
+    inline pf_Frag * getNext(void) const { }
+    PT_DocPosition getPos(void) const { }
+ };
+ class pf_Fragments {
+   public:
+    pf_Frag * getFirst() const;
+ };
+ class pt_PieceTable {
+    bool getStruxOfTypeFromPosition(PL_ListenerId listenerId, PT_DocPosition docPos, PTStruxType pts, PL_StruxFmtHandle * psfh) const;
+    bool _tellAndMaybeAddListener(PL_ListenerId listenerId, bool bAdd);
+    pf_Fragments m_fragments;
+ };
+ class pf_Frag_Object : public pf_Frag
+ {
+   public:
+    virtual bool createSpecialChangeRecord(PX_ChangeRecord ** ppcr, PT_DocPosition dpos, PT_BlockOffset blockOffset) const;
+ };
+ bool pt_PieceTable::_tellAndMaybeAddListener(PL_ListenerId listenerId, bool bAdd) 
+ {
+   PL_StruxFmtHandle sfh = 0;
+   PT_DocPosition sum = 0;
+   UT_uint32 blockOffset = 0;
+   for (pf_Frag * pf = m_fragments.getFirst(); (pf); pf=pf->getNext())
+   {
+       pf_Frag_Object * pfo = static_cast<pf_Frag_Object *> (pf);
+       PX_ChangeRecord * pcr = __null;
+       bool bStatus1 = false;
+       if(sfh != __null)     {
+        bStatus1 = pfo->createSpecialChangeRecord(&pcr,sum,blockOffset);
+        if (!(bStatus1))
+ 	 return (false);
+       }
+       else
+       {
+        PT_DocPosition pos = pf->getPos();
+        getStruxOfTypeFromPosition(listenerId,pos,PTX_Block,&sfh);
+        bStatus1 = pfo->createSpecialChangeRecord(&pcr,pos,blockOffset);
+        if (!(bStatus1))
+ 	 return (false); 
+       }
+       if (!(bStatus1))
+ 	return (false);
+   }
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]