diff options
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr41775.C | 284 | ||||
-rw-r--r-- | gcc/tree-sra.c | 22 |
4 files changed, 312 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bbc792c..7e51dc6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2009-10-29 Martin Jambor <mjambor@suse.cz> + + PR tree-optimization/41775 + * tree-sra.c (build_ref_for_offset): Unshare *expr if not NULL. + (generate_subtree_copies): Do not unshare agg. + (load_assign_lhs_subreplacements): Do not unshare rhs. + (sra_modify_assign): Do not unshare exprs. + (propagate_subacesses_accross_link): Renamed to + propagate_subaccesses_across_link. + 2009-10-29 Richard Earnshaw <rearnsha@arm.com> * arm.c (count_insns_for_constant): Rework to support counting for diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b156846..895feaa 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-10-29 Martin Jambor <mjambor@suse.cz> + + PR tree-optimization/41775 + * testsuite/g++.dg/torture/pr41775.C: New testcase. + 2009-10-28 Jason Merrill <jason@redhat.com> * g++.dg/cpp0x/inline-ns1.C: New. diff --git a/gcc/testsuite/g++.dg/torture/pr41775.C b/gcc/testsuite/g++.dg/torture/pr41775.C new file mode 100644 index 0000000..3d8548e --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr41775.C @@ -0,0 +1,284 @@ +/* { dg-do compile } */ +/* { dg-require-visibility "" } */ + +typedef unsigned int size_t; +namespace std __attribute__ ((__visibility__ ("default"))) +{ + template < typename _Iterator > struct iterator_traits + { + }; + template < typename _Tp > struct iterator_traits <_Tp * > + { + typedef _Tp & reference; + }; +} + +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) +{ + using std::iterator_traits; + template < typename _Iterator, typename _Container > class __normal_iterator + { + public:typedef _Iterator iterator_type; + typedef typename iterator_traits < _Iterator >::reference reference; + reference operator* () const + { + } + __normal_iterator operator++ (int) + { + } + }; + template < typename _IteratorL, typename _IteratorR, + typename _Container > inline bool operator!= (const __normal_iterator < + _IteratorL, + _Container > &__lhs, + const __normal_iterator < + _IteratorR, + _Container > &__rhs) + { + } +} + +extern "C" +{ + extern "C" + { + __extension__ typedef __SIZE_TYPE__ __intptr_t; + } +} +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) +{ + template < typename _Tp > class new_allocator + { + public:typedef size_t size_type; + typedef _Tp *pointer; + template < typename _Tp1 > struct rebind + { + typedef new_allocator < _Tp1 > other; + }; + }; +} + +namespace std __attribute__ ((__visibility__ ("default"))) +{ +template < typename _Tp > class allocator:public __gnu_cxx::new_allocator < + _Tp > + { + }; +} + +extern "C" +{ + typedef __intptr_t intptr_t; +} +namespace llvm +{ + template < typename NodeTy > class ilist_half_node + { + }; +template < typename NodeTy > class ilist_node:private ilist_half_node < + NodeTy > + { + }; + class MachineBasicBlock; + class MachineOperand + { + public:enum MachineOperandType + { + } + Contents; + unsigned getReg () const + { + } + }; + class TargetRegisterInfo; +} + +namespace std __attribute__ ((__visibility__ ("default"))) +{ + template < typename _Tp, typename _Alloc > struct _Vector_base + { + typedef typename _Alloc::template rebind < _Tp >::other _Tp_alloc_type; + }; +template < typename _Tp, typename _Alloc = std::allocator < _Tp > >class vector:protected _Vector_base < _Tp, + _Alloc + > + { + typedef _Vector_base < _Tp, _Alloc > _Base; + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; + public:typedef _Tp value_type; + typedef typename _Tp_alloc_type::pointer pointer; + typedef __gnu_cxx::__normal_iterator < pointer, vector > iterator; + iterator begin () + { + } + iterator end () + { + } + }; +} + +namespace llvm +{ + class MachineFunction; + class MachineInstr:public ilist_node < MachineInstr > + { + public:const MachineBasicBlock *getParent () const + { + } + const MachineOperand & getOperand (unsigned i) const + { + } + bool registerDefIsDead (unsigned Reg, const TargetRegisterInfo * TRI = + __null) const + { + } + }; + class AnalysisResolver; + class Pass + { + AnalysisResolver *Resolver; + intptr_t PassID; + public: explicit Pass (intptr_t pid):Resolver (0), PassID (pid) + { + } + explicit Pass (const void *pid):Resolver (0), PassID ((intptr_t) pid) + { + } + template < typename AnalysisType > AnalysisType & getAnalysis () const; + }; + class FunctionPass:public Pass + { + public:explicit FunctionPass (intptr_t pid):Pass (pid) + { + } + explicit FunctionPass (const void *pid):Pass (pid) + { + } + }; + class PassInfo + { + public:typedef Pass *(*NormalCtor_t) (); + private:const char *const PassName; + const char *const PassArgument; + const intptr_t PassID; + const bool IsCFGOnlyPass; + const bool IsAnalysis; + const bool IsAnalysisGroup; + NormalCtor_t NormalCtor; + public: PassInfo (const char *name, const char *arg, intptr_t pi, NormalCtor_t normal = 0, bool isCFGOnly = false, bool is_analysis = false):PassName (name), PassArgument (arg), PassID (pi), + IsCFGOnlyPass (isCFGOnly), IsAnalysis (is_analysis), + IsAnalysisGroup (false), NormalCtor (normal) + { + } + }; + template < typename PassName > Pass * callDefaultCtor () + { + return new PassName (); + } + template < typename passName > struct RegisterPass:public PassInfo + { + RegisterPass (const char *PassArg, const char *Name, bool CFGOnly = false, bool is_analysis = false):PassInfo (Name, PassArg, intptr_t (&passName::ID), + PassInfo::NormalCtor_t (callDefaultCtor < passName >), CFGOnly, + is_analysis) + { + } + }; + template < typename T > class SmallVectorImpl + { + }; + template < typename T, + unsigned N > class SmallVector:public SmallVectorImpl < T > + { + }; + class MachineFunctionPass:public FunctionPass + { + protected:explicit MachineFunctionPass (intptr_t ID):FunctionPass (ID) + { + } + explicit MachineFunctionPass (void *ID):FunctionPass (ID) + { + } + virtual bool runOnMachineFunction (MachineFunction & MF) = 0; + }; + class LiveIndex + { + private:unsigned index; + }; + class VNInfo + { + }; + struct LiveRange + { + LiveIndex start; + LiveIndex end; + VNInfo *valno; + }; + class LiveInterval + { + public:typedef SmallVector < LiveRange, 4 > Ranges; + bool containsOneValue () const + { + } + LiveRange *getLiveRangeContaining (LiveIndex Idx) + { + } + void removeRange (LiveIndex Start, LiveIndex End, bool RemoveDeadValNo = + false); + void removeRange (LiveRange LR, bool RemoveDeadValNo = false) + { + removeRange (LR.start, LR.end, RemoveDeadValNo); + } + }; + class LiveIntervals:public MachineFunctionPass + { + public:static char ID; + LiveIndex getDefIndex (LiveIndex index) + { + } + LiveInterval & getInterval (unsigned reg) + { + } + LiveIndex getInstructionIndex (const MachineInstr * instr) const + { + } + }; +} + +using namespace llvm; +namespace +{ +struct __attribute__ ((visibility ("hidden"))) StrongPHIElimination:public + MachineFunctionPass + { + static char ID; + StrongPHIElimination ():MachineFunctionPass (&ID) + { + } + bool runOnMachineFunction (MachineFunction & Fn); + }; +} + +static RegisterPass < StrongPHIElimination > X ("strong-phi-node-elimination", + "Eliminate PHI nodes for register allocation, intelligently"); +bool +StrongPHIElimination::runOnMachineFunction (MachineFunction & Fn) +{ + LiveIntervals & LI = getAnalysis < LiveIntervals > (); + std::vector < MachineInstr * >phis; + for (std::vector < MachineInstr * >::iterator I = phis.begin (), E = + phis.end (); I != E;) + { + MachineInstr *PInstr = *(I++); + unsigned DestReg = PInstr->getOperand (0).getReg (); + LiveInterval & PI = LI.getInterval (DestReg); + if (PInstr->registerDefIsDead (DestReg)) + { + if (PI.containsOneValue ()) + { + LiveIndex idx = + LI.getDefIndex (LI.getInstructionIndex (PInstr)); + PI.removeRange (*PI.getLiveRangeContaining (idx), true); + } + } + } +} diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 8624668..a86a441 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -1304,7 +1304,8 @@ build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset, /* Construct an expression that would reference a part of aggregate *EXPR of type TYPE at the given OFFSET of the type EXP_TYPE. If EXPR is NULL, the function only determines whether it can build such a reference without - actually doing it. + actually doing it, otherwise, the tree it points to is unshared first and + then used as a base for furhter sub-references. FIXME: Eventually this should be replaced with maybe_fold_offset_to_reference() from tree-ssa-ccp.c but that requires a @@ -1317,6 +1318,9 @@ build_ref_for_offset (tree *expr, tree type, HOST_WIDE_INT offset, { location_t loc = expr ? EXPR_LOCATION (*expr) : UNKNOWN_LOCATION; + if (expr) + *expr = unshare_expr (*expr); + if (allow_ptr && POINTER_TYPE_P (type)) { type = TREE_TYPE (type); @@ -1759,7 +1763,7 @@ create_artificial_child_access (struct access *parent, struct access *model, access but LACC is not, change the type of the latter, if possible. */ static bool -propagate_subacesses_accross_link (struct access *lacc, struct access *racc) +propagate_subaccesses_across_link (struct access *lacc, struct access *racc) { struct access *rchild; HOST_WIDE_INT norm_delta = lacc->offset - racc->offset; @@ -1800,7 +1804,7 @@ propagate_subacesses_accross_link (struct access *lacc, struct access *racc) rchild->grp_hint = 1; new_acc->grp_hint |= new_acc->grp_read; if (rchild->first_child) - ret |= propagate_subacesses_accross_link (new_acc, rchild); + ret |= propagate_subaccesses_across_link (new_acc, rchild); } continue; } @@ -1818,7 +1822,7 @@ propagate_subacesses_accross_link (struct access *lacc, struct access *racc) { ret = true; if (racc->first_child) - propagate_subacesses_accross_link (new_acc, rchild); + propagate_subaccesses_across_link (new_acc, rchild); } } @@ -1844,7 +1848,7 @@ propagate_all_subaccesses (void) if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base))) continue; lacc = lacc->group_representative; - if (propagate_subacesses_accross_link (lacc, racc) + if (propagate_subaccesses_across_link (lacc, racc) && lacc->first_link) add_access_to_work_queue (lacc); } @@ -1960,7 +1964,7 @@ generate_subtree_copies (struct access *access, tree agg, { do { - tree expr = unshare_expr (agg); + tree expr = agg; if (chunk_size && access->offset >= start_offset + chunk_size) return; @@ -2235,7 +2239,7 @@ load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc, rhs = unshare_expr (lacc->expr); else { - rhs = unshare_expr (top_racc->base); + rhs = top_racc->base; repl_found = build_ref_for_offset (&rhs, TREE_TYPE (top_racc->base), offset, lacc->type, false); @@ -2372,7 +2376,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi, if (AGGREGATE_TYPE_P (TREE_TYPE (lhs)) && !access_has_children_p (lacc)) { - tree expr = unshare_expr (lhs); + tree expr = lhs; if (build_ref_for_offset (&expr, TREE_TYPE (lhs), 0, TREE_TYPE (rhs), false)) { @@ -2383,7 +2387,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi, else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs)) && !access_has_children_p (racc)) { - tree expr = unshare_expr (rhs); + tree expr = rhs; if (build_ref_for_offset (&expr, TREE_TYPE (rhs), 0, TREE_TYPE (lhs), false)) rhs = expr; |