diff options
author | Bernd Schmidt <bernd.schmidt@analog.com> | 2006-01-11 17:40:46 +0000 |
---|---|---|
committer | Bernd Schmidt <bernd.schmidt@analog.com> | 2006-01-11 17:40:46 +0000 |
commit | 337db89251de80f8ff7a00b2d71bc333c630b6e4 (patch) | |
tree | d3188ec1672ccdf9f1225cc766a1dc386c4f0d32 /gcc/combine.c | |
parent | efb5461014d0abdd5751d82ad1b4d0c61685dbdd (diff) |
Merged revisions 96681,96683-96686,96689-96692,96698-96701,96705,96708,96710,96712,96714-96715,96719-96720,96725,96730,96733,96735-96737,96739-96740,96743,96745,96748,96753,96755,96759-96762,96764-96765,96768,96770-96771,96774,96776-96778,96782,96784-96785,96788,96790,96795-96803,96808,96812-96814,96816-96832,96834,96836-96837,96844,96847,96849-96853,96855,96862,96867,96870,96872,96879-96881,96883-96884,96889,96891-96895,96899,96902-96905,96908,96911,96913,96915-96917,96919-96921,96923-96924,96926-96927,96931-96935,96937-96939,96941,96944,96947-96948,96951,96953-96954,96957-96958,96960,96963,96966-96968,96980-96985,96988-96990,96995-96996,96998,97000,97003-97005,97013-97016,97018-97019,97024,97026,97028-97029,97031-97034,97036,97038-97039,97041,97044,97046-97048,97050,97054,97057-97063,97065,97070,97074,97076-97077,97079,97081-97086,97089,97091,97109,97111-97116,97120,97122-97123,97125-97130,97132-97136,97139,97143,97146-97148,97150-97153,97156-97157,97160-97161,97164-97192,97194-97197,97199-97200,97202,97204,97207-97212,97217,97220-97223,97229,97233,97236-97243,97249-97253,97255,97258,97263-97264,97267,97270,97273,97276-97278,97281-97285,97287,97289-97290,97292,97295,97298-97299,97301,97303,97308,97312-97314,97317-97319,97321-97322,97325-97326,97330-97334,97336-97344,97347-97349,97351-97352,97358,97360-97364,97367,97369-97370,97372-97373,97376-97381,97383,97385-97397,97399-97400,97402-97403,97406,97409,97411-97412,97414,97416-97417,97422,97424,97428-97430,97434-97438,97440-97441,97444,97446,97449,97452-97453,97455-97458,97461,97470,97472-97473,97475-97476,97478-97479,97481,97484-97486,97489-97493,97495-97496,97498,97511,97522,97525-97527,97529,97532-97533,97536-97538,97540-97551,97554-97555,97557-97558,97560-97561,97565,97567,97569-97572,97574-97578,97580-97582,97587,97589,97593-97599,97601-97602,97604-97605,97607,97609,97611,97613,97617,97620,97622,97624,97627,97631,97633,97635-97636,97640-97641,97643-97646,97648,97650,97652-97656,97659-97663,97666,97668,97671,97673-97674,97676-97678,97681,97685-97686,97691,97694,97696,97699-97702,97705,97708-97713,97719,97722-97723,97726,97728,97730-97731,97733,97737-97740,97742,97746-97747,97749,97751,97756,97759-97760,97763,97765,97770,97772-97773,97775,97778-97779,97781-97782,97784,97787-97788,97790,97792-97793,97795-97797,97804-97805,97807-97810,97813,97815-97819,97822,97825-97828,97830,97832,97836-97842,97846,97849,97851,97854,97857,97860-97862,97866,97868-97873,97880,97884-97887,97890,97894-97895,97897,97902-97908,97910-97912,97916,97919-97924,97928-97932,97935,97937-97941,97943-97951,97955,97958,97961,97964-97966,97968,97971-97974,97976-97983,97986-97988,97991,97994,97999-98001,98003,98009-98010,98012,98017-98023,98026-98029,98031-98032,98034,98039-98040,98044,98047-98048,98051-98053,98058,98061-98068,98070-98073,98076-98080,98082-98095,98097,98099,98101-98107,98110-98111,98118,98121,98127-98128,98131-98137,98140-98144,98146,98148-98149,98152,98154-98156,98159,98161-98162,98165-98168,98173-98174,98179,98183-98184,98186-98187,98189-98193,98195-98196,98199-98200,98202-98203,98206,98208-98210,98213,98216,98218,98220-98223,98225,98227,98232-98234,98236-98239,98242,98244-98245,98247,98252,98257-98260,98262,98265-98266,98269,98271,98273,98278,98283,98285-98288,98295,98297,98303,98307,98309-98313,98315-98316,98318-98321,98323-98324,98326-98335,98338-98343,98345-98350,98352,98355,98357,98362,98365-98379,98381,98384-98400,98402-98403,98405-98408,98412-98414,98416-98421,98425,98428-98430,98432-98451,98453,98456-98458,98460-98462,98464,98466,98468-98469,98471-98473,98476,98478,98482,98486,98493-98504,98507-98508,98510-98511,98513-98519,98522-98523,98527-98528,98530,98534,98540,98542-98544,98548-98551,98555,98559-98562,98567,98569-98570,98573-98574,98578-98583,98585-98587,98589,98594,98596-98603,98605-98607,98610-98611,98613-98622,98624,98631-98637,98640,98643-98644,98649-98650,98654,98658-98660,98663-98665,98668-98669,98673-98674,98676,98678-98679,98681,98684-98686,98691,98693-98695,98699,98708,98711-98712,98714-98715,98717,98723-98724,98726,98728,98730-98735,98737-98738,98740,98744-98746,98749,98752-98753,98755-98756,98762-98771,98774-98776,98778-98780,98782-98783,98785-98786,98788-98789,98791-98793,98795-98798,98800,98805,98808,98813-98814,98816-98818,98828-98829,98831-98832,98835-98837,98840,98843-98845,98848,98850-98854,98861-98862,98866-98868,98871-98875,98877-98886,98890,98893,98896,98898,98900-98901,98906-98908,98910-98916,98919,98922,98924,98928-98929,98932,98934-98936,98938-98942,98944,98947,98949-98950,98952,98955,98958,98961-98962,98966,98968,98975-98981,98983-98989,98991-98994,98998-99000,99006,99008,99010-99013,99016,99018-99021,99028,99032-99033,99035,99037-99038,99041,99043,99046-99047,99052,99054,99059,99064,99067-99068,99071-99072,99076,99080,99082-99083,99085-99086,99089,99091,99093-99096,99099-99100,99103-99105,99109,99111,99113-99115,99118,99121-99123,99125-99126,99131,99133,99135,99144,99152,99155-99158,99160-99164,99167-99175,99177,99179-99180,99182-99183,99185-99188,99196-99197,99200,99203-99211,99216-99225,99227,99230,99232,99234-99236,99238,99244,99247,99250-99257,99261-99262,99264-99265,99268-99269,99272-99275,99277,99279,99281-99282,99284,99287-99291,99296,99300-99306,99309,99314-99317,99319,99322,99324-99326,99329-99332,99334,99336-99337,99341,99343-99352,99355-99360,99362-99363,99365-99366,99370,99373,99375-99384,99386,99388,99391,99393-99395,99398-99399,99405-99408,99410-99411,99413,99415,99419,99421-99422,99424-99425,99429,99431-99433,99435,99441-99444,99446-99464,99466-99467,99470-99478,99483,99485,99487,99492-99493,99495-99499,99503,99505-99506,99508-99510,99513-99514,99516-99521,99523-99529,99535-99541,99544-99548,99553,99556,99558-99560,99563,99566,99568-99570,99573-99574,99577-99586,99588,99591-99592,99596-99597,99602,99604-99610,99613,99615,99617,99619,99621,99623,99625-99627,99631-99633,99635-99637,99640,99642-99643,99646-99648,99650,99652,99654-99660,99662-99664,99666,99668-99670,99672-99676,99679-99680,99684,99687,99691-99705,99708,99710-99711,99714-99716,99719-99724,99726,99728-99729,99731-99733,99735-99742,99745-99750,99755,99757,99759-99760,99765,99767,99769,99773-99775,99777-99779,99782-99783,99785,99787,99789,99791-99792,99794,99796,99799-99801,99803,99806,99810-99817,99823-99835,99837-99840,99842-99844,99846-99862,99871,99877-99882,99884-99885,99889-99890,99892-99893,99896-99897,99899-99901,99903-99904,99906,99908,99910,99916,99919-99920,99922-99928,99930,99933,99935-99936,99939,99941-99946,99948-99953,99957,99960,99966-99967,99971-99972,99974,99976-99978,99981-99982,99984,99986,99988,99993,99996-99997,99999 via svnmerge from
svn+ssh://gcc.gnu.org/svn/gcc/trunk
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/reload-branch@109594 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/combine.c')
-rw-r--r-- | gcc/combine.c | 737 |
1 files changed, 340 insertions, 397 deletions
diff --git a/gcc/combine.c b/gcc/combine.c index f97d6c04a4a..251c1eeafb8 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -386,6 +386,7 @@ static rtx known_cond (rtx, enum rtx_code, rtx, rtx); static int rtx_equal_for_field_assignment_p (rtx, rtx); static rtx make_field_assignment (rtx); static rtx apply_distributive_law (rtx); +static rtx distribute_and_simplify_rtx (rtx, int); static rtx simplify_and_const_int (rtx, enum machine_mode, rtx, unsigned HOST_WIDE_INT); static int merge_outer_ops (enum rtx_code *, HOST_WIDE_INT *, enum rtx_code, @@ -394,7 +395,6 @@ static rtx simplify_shift_const (rtx, enum rtx_code, enum machine_mode, rtx, int); static int recog_for_combine (rtx *, rtx, rtx *); static rtx gen_lowpart_for_combine (enum machine_mode, rtx); -static rtx gen_binary (enum rtx_code, enum machine_mode, rtx, rtx); static enum rtx_code simplify_comparison (enum rtx_code, rtx *, rtx *); static void update_table_tick (rtx); static void record_value_for_reg (rtx, rtx, rtx); @@ -413,8 +413,6 @@ static void distribute_links (rtx); static void mark_used_regs_combine (rtx); static int insn_cuid (rtx); static void record_promoted_value (rtx, rtx); -static rtx reversed_comparison (rtx, enum machine_mode, rtx, rtx); -static enum rtx_code combine_reversed_comparison_code (rtx); static int unmentioned_reg_p_1 (rtx *, void *); static bool unmentioned_reg_p (rtx, rtx); @@ -424,6 +422,10 @@ static bool unmentioned_reg_p (rtx, rtx); #undef RTL_HOOKS_GEN_LOWPART #define RTL_HOOKS_GEN_LOWPART gen_lowpart_for_combine +/* Our implementation of gen_lowpart never emits a new pseudo. */ +#undef RTL_HOOKS_GEN_LOWPART_NO_EMIT +#define RTL_HOOKS_GEN_LOWPART_NO_EMIT gen_lowpart_for_combine + #undef RTL_HOOKS_REG_NONZERO_REG_BITS #define RTL_HOOKS_REG_NONZERO_REG_BITS reg_nonzero_bits_for_combine @@ -884,7 +886,7 @@ combine_instructions (rtx f, unsigned int nregs) EXECUTE_IF_SET_IN_SBITMAP (refresh_blocks, 0, i, BASIC_BLOCK (i)->flags |= BB_DIRTY); - new_direct_jump_p |= purge_all_dead_edges (0); + new_direct_jump_p |= purge_all_dead_edges (); delete_noop_moves (); update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES, @@ -1316,9 +1318,9 @@ can_combine_p (rtx insn, rtx i3, rtx pred ATTRIBUTE_UNUSED, rtx succ, if (INSN_P (p) && p != succ && volatile_insn_p (PATTERN (p))) return 0; - /* If INSN or I2 contains an autoincrement or autodecrement, - make sure that register is not used between there and I3, - and not already used in I3 either. + /* If INSN contains an autoincrement or autodecrement, make sure that + register is not used between there and I3, and not already used in + I3 either. Neither must it be used in PRED or SUCC, if they exist. Also insist that I3 not be a jump; if it were one and the incremented register were spilled, we would lose. */ @@ -1327,6 +1329,10 @@ can_combine_p (rtx insn, rtx i3, rtx pred ATTRIBUTE_UNUSED, rtx succ, if (REG_NOTE_KIND (link) == REG_INC && (JUMP_P (i3) || reg_used_between_p (XEXP (link, 0), insn, i3) + || (pred != NULL_RTX + && reg_overlap_mentioned_p (XEXP (link, 0), PATTERN (pred))) + || (succ != NULL_RTX + && reg_overlap_mentioned_p (XEXP (link, 0), PATTERN (succ))) || reg_overlap_mentioned_p (XEXP (link, 0), PATTERN (i3)))) return 0; #endif @@ -1521,7 +1527,7 @@ cant_combine_insn_p (rtx insn) /* Never combine loads and stores involving hard regs that are likely to be spilled. The register allocator can usually handle such reg-reg moves by tying. If we allow the combiner to make - substitutions of likely-spilled regs, we may abort in reload. + substitutions of likely-spilled regs, reload might die. As an exception, we allow combinations involving fixed regs; these are not available to the register allocator so there's no risk involved. */ @@ -2090,8 +2096,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) || (i1 != 0 && FIND_REG_INC_NOTE (i1, NULL_RTX) != 0 && (n_occurrences + added_sets_1 + (added_sets_2 && ! i1_feeds_i3) > 1)) - /* Fail if we tried to make a new register (we used to abort, but there's - really no reason to). */ + /* Fail if we tried to make a new register. */ || max_reg_num () != maxreg /* Fail if we couldn't do something and have a CLOBBER. */ || GET_CODE (newpat) == CLOBBER @@ -2373,11 +2378,17 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) && REG_P (i2dest) #endif /* We need I2DEST in the proper mode. If it is a hard register - or the only use of a pseudo, we can change its mode. */ + or the only use of a pseudo, we can change its mode. + Make sure we don't change a hard register to have a mode that + isn't valid for it, or change the number of registers. */ && (GET_MODE (*split) == GET_MODE (i2dest) || GET_MODE (*split) == VOIDmode - || REGNO (i2dest) < FIRST_PSEUDO_REGISTER - || (REG_N_SETS (REGNO (i2dest)) == 1 && ! added_sets_2 + || (REGNO (i2dest) < FIRST_PSEUDO_REGISTER + && HARD_REGNO_MODE_OK (REGNO (i2dest), GET_MODE (*split)) + && (HARD_REGNO_NREGS (REGNO (i2dest), GET_MODE (i2dest)) + == HARD_REGNO_NREGS (REGNO (i2dest), GET_MODE (*split)))) + || (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER + && REG_N_SETS (REGNO (i2dest)) == 1 && ! added_sets_2 && ! REG_USERVAR_P (i2dest))) && (next_real_insn (i2) == i3 || ! use_crosses_set_p (*split, INSN_CUID (i2))) @@ -3211,14 +3222,16 @@ find_split_point (rtx *loc, rtx insn) if (src == mask) SUBST (SET_SRC (x), - gen_binary (IOR, mode, dest, GEN_INT (src << pos))); + simplify_gen_binary (IOR, mode, dest, GEN_INT (src << pos))); else - SUBST (SET_SRC (x), - gen_binary (IOR, mode, - gen_binary (AND, mode, dest, - gen_int_mode (~(mask << pos), - mode)), - GEN_INT (src << pos))); + { + rtx negmask = gen_int_mode (~(mask << pos), mode); + SUBST (SET_SRC (x), + simplify_gen_binary (IOR, mode, + simplify_gen_binary (AND, mode, + dest, negmask), + GEN_INT (src << pos))); + } SUBST (SET_DEST (x), dest); @@ -3754,47 +3767,6 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) SUBST (XEXP (x, 1), temp); } - /* If this is a PLUS, MINUS, or MULT, and the first operand is the - sign extension of a PLUS with a constant, reverse the order of the sign - extension and the addition. Note that this not the same as the original - code, but overflow is undefined for signed values. Also note that the - PLUS will have been partially moved "inside" the sign-extension, so that - the first operand of X will really look like: - (ashiftrt (plus (ashift A C4) C5) C4). - We convert this to - (plus (ashiftrt (ashift A C4) C2) C4) - and replace the first operand of X with that expression. Later parts - of this function may simplify the expression further. - - For example, if we start with (mult (sign_extend (plus A C1)) C2), - we swap the SIGN_EXTEND and PLUS. Later code will apply the - distributive law to produce (plus (mult (sign_extend X) C1) C3). - - We do this to simplify address expressions. */ - - if ((code == PLUS || code == MINUS || code == MULT) - && GET_CODE (XEXP (x, 0)) == ASHIFTRT - && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS - && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ASHIFT - && GET_CODE (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 1)) == CONST_INT - && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT - && XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 1) == XEXP (XEXP (x, 0), 1) - && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT - && (temp = simplify_binary_operation (ASHIFTRT, mode, - XEXP (XEXP (XEXP (x, 0), 0), 1), - XEXP (XEXP (x, 0), 1))) != 0) - { - rtx new - = simplify_shift_const (NULL_RTX, ASHIFT, mode, - XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 0), - INTVAL (XEXP (XEXP (x, 0), 1))); - - new = simplify_shift_const (NULL_RTX, ASHIFTRT, mode, new, - INTVAL (XEXP (XEXP (x, 0), 1))); - - SUBST (XEXP (x, 0), gen_binary (PLUS, mode, new, temp)); - } - /* If this is a simple operation applied to an IF_THEN_ELSE, try applying it to the arms of the IF_THEN_ELSE. This often simplifies things. Check for cases where both arms are testing the same @@ -3849,12 +3821,14 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) /* If the result values are STORE_FLAG_VALUE and zero, we can just make the comparison operation. */ if (true_rtx == const_true_rtx && false_rtx == const0_rtx) - x = gen_binary (cond_code, mode, cond, cop1); + x = simplify_gen_relational (cond_code, mode, VOIDmode, + cond, cop1); else if (true_rtx == const0_rtx && false_rtx == const_true_rtx && ((reversed = reversed_comparison_code_parts (cond_code, cond, cop1, NULL)) != UNKNOWN)) - x = gen_binary (reversed, mode, cond, cop1); + x = simplify_gen_relational (reversed, mode, VOIDmode, + cond, cop1); /* Likewise, we can make the negate of a comparison operation if the result values are - STORE_FLAG_VALUE and zero. */ @@ -3862,8 +3836,9 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) && INTVAL (true_rtx) == - STORE_FLAG_VALUE && false_rtx == const0_rtx) x = simplify_gen_unary (NEG, mode, - gen_binary (cond_code, mode, cond, - cop1), + simplify_gen_relational (cond_code, + mode, VOIDmode, + cond, cop1), mode); else if (GET_CODE (false_rtx) == CONST_INT && INTVAL (false_rtx) == - STORE_FLAG_VALUE @@ -3872,13 +3847,17 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) (cond_code, cond, cop1, NULL)) != UNKNOWN)) x = simplify_gen_unary (NEG, mode, - gen_binary (reversed, mode, - cond, cop1), + simplify_gen_relational (reversed, + mode, VOIDmode, + cond, cop1), mode); else return gen_rtx_IF_THEN_ELSE (mode, - gen_binary (cond_code, VOIDmode, - cond, cop1), + simplify_gen_relational (cond_code, + mode, + VOIDmode, + cond, + cop1), true_rtx, false_rtx); code = GET_CODE (x); @@ -3981,7 +3960,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) } if (inner) - return gen_binary (code, mode, other, inner); + return simplify_gen_binary (code, mode, other, inner); } } @@ -4083,7 +4062,8 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) if (GET_CODE (XEXP (x, 0)) == XOR && XEXP (XEXP (x, 0), 1) == const1_rtx && nonzero_bits (XEXP (XEXP (x, 0), 0), mode) == 1) - return gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0), constm1_rtx); + return simplify_gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0), + constm1_rtx); temp = expand_compound_operation (XEXP (x, 0)); @@ -4311,8 +4291,9 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) in1 = XEXP (XEXP (XEXP (x, 0), 0), 0); in2 = XEXP (XEXP (x, 0), 1); - return gen_binary (MINUS, mode, XEXP (x, 1), - gen_binary (MULT, mode, in1, in2)); + return simplify_gen_binary (MINUS, mode, XEXP (x, 1), + simplify_gen_binary (MULT, mode, + in1, in2)); } /* If we have (plus (plus (A const) B)), associate it so that CONST is @@ -4321,10 +4302,11 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) they are now checked elsewhere. */ if (GET_CODE (XEXP (x, 0)) == PLUS && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1))) - return gen_binary (PLUS, mode, - gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0), - XEXP (x, 1)), - XEXP (XEXP (x, 0), 1)); + return simplify_gen_binary (PLUS, mode, + simplify_gen_binary (PLUS, mode, + XEXP (XEXP (x, 0), 0), + XEXP (x, 1)), + XEXP (XEXP (x, 0), 1)); /* (plus (xor (and <foo> (const_int pow2 - 1)) <c>) <-c>) when c is (const_int (pow2 + 1) / 2) is a sign extension of a @@ -4359,9 +4341,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) if (COMPARISON_P (XEXP (x, 0)) && ((STORE_FLAG_VALUE == -1 && XEXP (x, 1) == const1_rtx) || (STORE_FLAG_VALUE == 1 && XEXP (x, 1) == constm1_rtx)) - && (reversed = reversed_comparison (XEXP (x, 0), mode, - XEXP (XEXP (x, 0), 0), - XEXP (XEXP (x, 0), 1)))) + && (reversed = reversed_comparison (XEXP (x, 0), mode))) return simplify_gen_unary (NEG, mode, reversed, mode); @@ -4390,7 +4370,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) & nonzero_bits (XEXP (x, 1), mode)) == 0) { /* Try to simplify the expression further. */ - rtx tor = gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1)); + rtx tor = simplify_gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1)); temp = combine_simplify_rtx (tor, mode, in_dest); /* If we could, great. If not, do not go ahead with the IOR @@ -4407,9 +4387,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) if (STORE_FLAG_VALUE == 1 && XEXP (x, 0) == const1_rtx && COMPARISON_P (XEXP (x, 1)) - && (reversed = reversed_comparison (XEXP (x, 1), mode, - XEXP (XEXP (x, 1), 0), - XEXP (XEXP (x, 1), 1)))) + && (reversed = reversed_comparison (XEXP (x, 1), mode))) return reversed; /* (minus <foo> (and <foo> (const_int -pow2))) becomes @@ -4430,8 +4408,10 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) in1 = XEXP (XEXP (XEXP (x, 1), 0), 0); in2 = XEXP (XEXP (x, 1), 1); - return gen_binary (PLUS, mode, gen_binary (MULT, mode, in1, in2), - XEXP (x, 0)); + return simplify_gen_binary (PLUS, mode, + simplify_gen_binary (MULT, mode, + in1, in2), + XEXP (x, 0)); } /* Canonicalize (minus (neg A) (mult B C)) to @@ -4443,17 +4423,20 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) in1 = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 1), 0), mode); in2 = XEXP (XEXP (x, 1), 1); - return gen_binary (MINUS, mode, gen_binary (MULT, mode, in1, in2), - XEXP (XEXP (x, 0), 0)); + return simplify_gen_binary (MINUS, mode, + simplify_gen_binary (MULT, mode, + in1, in2), + XEXP (XEXP (x, 0), 0)); } /* Canonicalize (minus A (plus B C)) to (minus (minus A B) C) for integers. */ if (GET_CODE (XEXP (x, 1)) == PLUS && INTEGRAL_MODE_P (mode)) - return gen_binary (MINUS, mode, - gen_binary (MINUS, mode, XEXP (x, 0), - XEXP (XEXP (x, 1), 0)), - XEXP (XEXP (x, 1), 1)); + return simplify_gen_binary (MINUS, mode, + simplify_gen_binary (MINUS, mode, + XEXP (x, 0), + XEXP (XEXP (x, 1), 0)), + XEXP (XEXP (x, 1), 1)); break; case MULT: @@ -4463,17 +4446,11 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) if (GET_CODE (XEXP (x, 0)) == PLUS) { - x = apply_distributive_law - (gen_binary (PLUS, mode, - gen_binary (MULT, mode, - XEXP (XEXP (x, 0), 0), XEXP (x, 1)), - gen_binary (MULT, mode, - XEXP (XEXP (x, 0), 1), - copy_rtx (XEXP (x, 1))))); - - if (GET_CODE (x) != MULT) - return x; + rtx result = distribute_and_simplify_rtx (x, 0); + if (result) + return result; } + /* Try simplify a*(b/c) as (a*b)/c. */ if (FLOAT_MODE_P (mode) && flag_unsafe_math_optimizations && GET_CODE (XEXP (x, 0)) == DIV) @@ -4482,7 +4459,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) XEXP (XEXP (x, 0), 0), XEXP (x, 1)); if (tem) - return gen_binary (DIV, mode, tem, XEXP (XEXP (x, 0), 1)); + return simplify_gen_binary (DIV, mode, tem, XEXP (XEXP (x, 0), 1)); } break; @@ -4562,9 +4539,9 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) && nonzero_bits (op0, mode) == 1) { op0 = expand_compound_operation (op0); - return gen_binary (XOR, mode, - gen_lowpart (mode, op0), - const1_rtx); + return simplify_gen_binary (XOR, mode, + gen_lowpart (mode, op0), + const1_rtx); } else if (STORE_FLAG_VALUE == 1 @@ -4765,7 +4742,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest) if (GET_CODE (op0) == VEC_CONCAT) { HOST_WIDE_INT op0_size = GET_MODE_SIZE (GET_MODE (XEXP (op0, 0))); - if (op0_size < offset) + if (offset < op0_size) op0 = XEXP (op0, 0); else { @@ -4806,13 +4783,13 @@ simplify_if_then_else (rtx x) /* Simplify storing of the truth value. */ if (comparison_p && true_rtx == const_true_rtx && false_rtx == const0_rtx) - return gen_binary (true_code, mode, XEXP (cond, 0), XEXP (cond, 1)); + return simplify_gen_relational (true_code, mode, VOIDmode, + XEXP (cond, 0), XEXP (cond, 1)); /* Also when the truth value has to be reversed. */ if (comparison_p && true_rtx == const0_rtx && false_rtx == const_true_rtx - && (reversed = reversed_comparison (cond, mode, XEXP (cond, 0), - XEXP (cond, 1)))) + && (reversed = reversed_comparison (cond, mode))) return reversed; /* Sometimes we can simplify the arm of an IF_THEN_ELSE if a register used @@ -4820,7 +4797,7 @@ simplify_if_then_else (rtx x) comparisons and see if that says anything about the value of each arm. */ if (comparison_p - && ((false_code = combine_reversed_comparison_code (cond)) + && ((false_code = reversed_comparison_code (cond, NULL)) != UNKNOWN) && REG_P (XEXP (cond, 0))) { @@ -4878,7 +4855,7 @@ simplify_if_then_else (rtx x) the false arm is more complicated than the true arm. */ if (comparison_p - && combine_reversed_comparison_code (cond) != UNKNOWN + && reversed_comparison_code (cond, NULL) != UNKNOWN && (true_rtx == pc_rtx || (CONSTANT_P (true_rtx) && GET_CODE (false_rtx) != CONST_INT && false_rtx != pc_rtx) @@ -4890,10 +4867,7 @@ simplify_if_then_else (rtx x) || rtx_equal_p (false_rtx, XEXP (cond, 0)))) { true_code = reversed_comparison_code (cond, NULL); - SUBST (XEXP (x, 0), - reversed_comparison (cond, GET_MODE (cond), XEXP (cond, 0), - XEXP (cond, 1))); - + SUBST (XEXP (x, 0), reversed_comparison (cond, GET_MODE (cond))); SUBST (XEXP (x, 1), false_rtx); SUBST (XEXP (x, 2), true_rtx); @@ -4956,16 +4930,16 @@ simplify_if_then_else (rtx x) { case GE: case GT: - return gen_binary (SMAX, mode, true_rtx, false_rtx); + return simplify_gen_binary (SMAX, mode, true_rtx, false_rtx); case LE: case LT: - return gen_binary (SMIN, mode, true_rtx, false_rtx); + return simplify_gen_binary (SMIN, mode, true_rtx, false_rtx); case GEU: case GTU: - return gen_binary (UMAX, mode, true_rtx, false_rtx); + return simplify_gen_binary (UMAX, mode, true_rtx, false_rtx); case LEU: case LTU: - return gen_binary (UMIN, mode, true_rtx, false_rtx); + return simplify_gen_binary (UMIN, mode, true_rtx, false_rtx); default: break; } @@ -5078,12 +5052,14 @@ simplify_if_then_else (rtx x) if (z) { - temp = subst (gen_binary (true_code, m, cond_op0, cond_op1), + temp = subst (simplify_gen_relational (true_code, m, VOIDmode, + cond_op0, cond_op1), pc_rtx, pc_rtx, 0, 0); - temp = gen_binary (MULT, m, temp, - gen_binary (MULT, m, c1, const_true_rtx)); + temp = simplify_gen_binary (MULT, m, temp, + simplify_gen_binary (MULT, m, c1, + const_true_rtx)); temp = subst (temp, pc_rtx, pc_rtx, 0, 0); - temp = gen_binary (op, m, gen_lowpart (m, z), temp); + temp = simplify_gen_binary (op, m, gen_lowpart (m, z), temp); if (extend_op != UNKNOWN) temp = simplify_gen_unary (extend_op, mode, temp, m); @@ -5268,7 +5244,8 @@ simplify_set (rtx x) PUT_CODE (*cc_use, old_code); other_changed = 0; - op0 = gen_binary (XOR, GET_MODE (op0), op0, GEN_INT (mask)); + op0 = simplify_gen_binary (XOR, GET_MODE (op0), + op0, GEN_INT (mask)); } } } @@ -5432,18 +5409,19 @@ simplify_set (rtx x) && rtx_equal_p (XEXP (false_rtx, 1), true_rtx)) term1 = true_rtx, false_rtx = XEXP (false_rtx, 0), true_rtx = const0_rtx; - term2 = gen_binary (AND, GET_MODE (src), - XEXP (XEXP (src, 0), 0), true_rtx); - term3 = gen_binary (AND, GET_MODE (src), - simplify_gen_unary (NOT, GET_MODE (src), - XEXP (XEXP (src, 0), 0), - GET_MODE (src)), - false_rtx); + term2 = simplify_gen_binary (AND, GET_MODE (src), + XEXP (XEXP (src, 0), 0), true_rtx); + term3 = simplify_gen_binary (AND, GET_MODE (src), + simplify_gen_unary (NOT, GET_MODE (src), + XEXP (XEXP (src, 0), 0), + GET_MODE (src)), + false_rtx); SUBST (SET_SRC (x), - gen_binary (IOR, GET_MODE (src), - gen_binary (IOR, GET_MODE (src), term1, term2), - term3)); + simplify_gen_binary (IOR, GET_MODE (src), + simplify_gen_binary (IOR, GET_MODE (src), + term1, term2), + term3)); src = SET_SRC (x); } @@ -5478,29 +5456,31 @@ simplify_logical (rtx x) if (GET_CODE (op0) == XOR && rtx_equal_p (XEXP (op0, 0), op1) && ! side_effects_p (op1)) - x = gen_binary (AND, mode, - simplify_gen_unary (NOT, mode, XEXP (op0, 1), mode), - op1); + x = simplify_gen_binary (AND, mode, + simplify_gen_unary (NOT, mode, + XEXP (op0, 1), mode), + op1); if (GET_CODE (op0) == XOR && rtx_equal_p (XEXP (op0, 1), op1) && ! side_effects_p (op1)) - x = gen_binary (AND, mode, - simplify_gen_unary (NOT, mode, XEXP (op0, 0), mode), - op1); + x = simplify_gen_binary (AND, mode, + simplify_gen_unary (NOT, mode, + XEXP (op0, 0), mode), + op1); /* Similarly for (~(A ^ B)) & A. */ if (GET_CODE (op0) == NOT && GET_CODE (XEXP (op0, 0)) == XOR && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1) && ! side_effects_p (op1)) - x = gen_binary (AND, mode, XEXP (XEXP (op0, 0), 1), op1); + x = simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 1), op1); if (GET_CODE (op0) == NOT && GET_CODE (XEXP (op0, 0)) == XOR && rtx_equal_p (XEXP (XEXP (op0, 0), 1), op1) && ! side_effects_p (op1)) - x = gen_binary (AND, mode, XEXP (XEXP (op0, 0), 0), op1); + x = simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 0), op1); /* We can call simplify_and_const_int only if we don't lose any (sign) bits when converting INTVAL (op1) to @@ -5520,8 +5500,9 @@ simplify_logical (rtx x) && GET_CODE (XEXP (op0, 1)) == CONST_INT && GET_CODE (op1) == CONST_INT && (INTVAL (XEXP (op0, 1)) & INTVAL (op1)) != 0) - return gen_binary (IOR, mode, - gen_binary (AND, mode, XEXP (op0, 0), + return simplify_gen_binary (IOR, mode, + simplify_gen_binary + (AND, mode, XEXP (op0, 0), GEN_INT (INTVAL (XEXP (op0, 1)) & ~INTVAL (op1))), op1); @@ -5540,54 +5521,21 @@ simplify_logical (rtx x) && ! side_effects_p (XEXP (op0, 1))) return op1; - /* In the following group of tests (and those in case IOR below), - we start with some combination of logical operations and apply - the distributive law followed by the inverse distributive law. - Most of the time, this results in no change. However, if some of - the operands are the same or inverses of each other, simplifications - will result. - - For example, (and (ior A B) (not B)) can occur as the result of - expanding a bit field assignment. When we apply the distributive - law to this, we get (ior (and (A (not B))) (and (B (not B)))), - which then simplifies to (and (A (not B))). - - If we have (and (ior A B) C), apply the distributive law and then - the inverse distributive law to see if things simplify. */ - + /* If we have any of (and (ior A B) C) or (and (xor A B) C), + apply the distributive law and then the inverse distributive + law to see if things simplify. */ if (GET_CODE (op0) == IOR || GET_CODE (op0) == XOR) { - x = apply_distributive_law - (gen_binary (GET_CODE (op0), mode, - gen_binary (AND, mode, XEXP (op0, 0), op1), - gen_binary (AND, mode, XEXP (op0, 1), - copy_rtx (op1)))); - if (GET_CODE (x) != AND) - return x; + rtx result = distribute_and_simplify_rtx (x, 0); + if (result) + return result; } - if (GET_CODE (op1) == IOR || GET_CODE (op1) == XOR) - return apply_distributive_law - (gen_binary (GET_CODE (op1), mode, - gen_binary (AND, mode, XEXP (op1, 0), op0), - gen_binary (AND, mode, XEXP (op1, 1), - copy_rtx (op0)))); - - /* Similarly, taking advantage of the fact that - (and (not A) (xor B C)) == (xor (ior A B) (ior A C)) */ - - if (GET_CODE (op0) == NOT && GET_CODE (op1) == XOR) - return apply_distributive_law - (gen_binary (XOR, mode, - gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 0)), - gen_binary (IOR, mode, copy_rtx (XEXP (op0, 0)), - XEXP (op1, 1)))); - - else if (GET_CODE (op1) == NOT && GET_CODE (op0) == XOR) - return apply_distributive_law - (gen_binary (XOR, mode, - gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 0)), - gen_binary (IOR, mode, copy_rtx (XEXP (op1, 0)), XEXP (op0, 1)))); + { + rtx result = distribute_and_simplify_rtx (x, 1); + if (result) + return result; + } break; case IOR: @@ -5610,28 +5558,16 @@ simplify_logical (rtx x) if (GET_CODE (op0) == AND) { - rtx tmp = apply_distributive_law - (gen_binary (AND, mode, - gen_binary (IOR, mode, XEXP (op0, 0), op1), - gen_binary (IOR, mode, XEXP (op0, 1), - copy_rtx (op1)))); - - if (GET_CODE (tmp) != IOR - && rtx_cost (tmp, SET) < rtx_cost (x, SET)) - return tmp; + rtx result = distribute_and_simplify_rtx (x, 0); + if (result) + return result; } if (GET_CODE (op1) == AND) { - rtx tmp = apply_distributive_law - (gen_binary (AND, mode, - gen_binary (IOR, mode, XEXP (op1, 0), op0), - gen_binary (IOR, mode, XEXP (op1, 1), - copy_rtx (op0)))); - - if (GET_CODE (tmp) != IOR - && rtx_cost (tmp, SET) < rtx_cost (x, SET)) - return tmp; + rtx result = distribute_and_simplify_rtx (x, 1); + if (result) + return result; } /* Convert (ior (ashift A CX) (lshiftrt A CY)) where CX+CY equals the @@ -5680,7 +5616,7 @@ simplify_logical (rtx x) if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT && (nonzero_bits (op0, mode) & nonzero_bits (op1, mode)) == 0) - return (gen_binary (IOR, mode, op0, op1)); + return (simplify_gen_binary (IOR, mode, op0, op1)); /* Convert (XOR (NOT x) (NOT y)) to (XOR x y). Also convert (XOR (NOT x) y) to (NOT (XOR x y)), similarly for @@ -5700,7 +5636,8 @@ simplify_logical (rtx x) } else if (num_negated == 1) return - simplify_gen_unary (NOT, mode, gen_binary (XOR, mode, op0, op1), + simplify_gen_unary (NOT, mode, + simplify_gen_binary (XOR, mode, op0, op1), mode); } @@ -5711,24 +5648,25 @@ simplify_logical (rtx x) if (GET_CODE (op0) == AND && rtx_equal_p (XEXP (op0, 1), op1) && ! side_effects_p (op1)) - return gen_binary (AND, mode, - simplify_gen_unary (NOT, mode, XEXP (op0, 0), mode), - op1); + return simplify_gen_binary (AND, mode, + simplify_gen_unary (NOT, mode, + XEXP (op0, 0), mode), + op1); else if (GET_CODE (op0) == AND && rtx_equal_p (XEXP (op0, 0), op1) && ! side_effects_p (op1)) - return gen_binary (AND, mode, - simplify_gen_unary (NOT, mode, XEXP (op0, 1), mode), - op1); + return simplify_gen_binary (AND, mode, + simplify_gen_unary (NOT, mode, + XEXP (op0, 1), mode), + op1); /* (xor (comparison foo bar) (const_int 1)) can become the reversed comparison if STORE_FLAG_VALUE is 1. */ if (STORE_FLAG_VALUE == 1 && op1 == const1_rtx && COMPARISON_P (op0) - && (reversed = reversed_comparison (op0, mode, XEXP (op0, 0), - XEXP (op0, 1)))) + && (reversed = reversed_comparison (op0, mode))) return reversed; /* (lshiftrt foo C) where C is the number of bits in FOO minus 1 @@ -5749,8 +5687,7 @@ simplify_logical (rtx x) == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)) && op1 == const_true_rtx && COMPARISON_P (op0) - && (reversed = reversed_comparison (op0, mode, XEXP (op0, 0), - XEXP (op0, 1)))) + && (reversed = reversed_comparison (op0, mode))) return reversed; break; @@ -5992,7 +5929,7 @@ expand_field_assignment (rtx x) rtx inner; rtx pos; /* Always counts from low bit. */ int len; - rtx mask; + rtx mask, cleared, masked; enum machine_mode compute_mode; /* Loop until we find something we can't simplify. */ @@ -6030,10 +5967,11 @@ expand_field_assignment (rtx x) /* If position is ADJUST - X, new position is X. */ pos = XEXP (pos, 0); else - pos = gen_binary (MINUS, GET_MODE (pos), - GEN_INT (GET_MODE_BITSIZE (GET_MODE (inner)) - - len), - pos); + pos = simplify_gen_binary (MINUS, GET_MODE (pos), + GEN_INT (GET_MODE_BITSIZE ( + GET_MODE (inner)) + - len), + pos); } } @@ -6080,30 +6018,30 @@ expand_field_assignment (rtx x) } /* Compute a mask of LEN bits, if we can do this on the host machine. */ - if (len < HOST_BITS_PER_WIDE_INT) - mask = GEN_INT (((HOST_WIDE_INT) 1 << len) - 1); - else + if (len >= HOST_BITS_PER_WIDE_INT) break; /* Now compute the equivalent expression. Make a copy of INNER for the SET_DEST in case it is a MEM into which we will substitute; we don't want shared RTL in that case. */ - x = gen_rtx_SET - (VOIDmode, copy_rtx (inner), - gen_binary (IOR, compute_mode, - gen_binary (AND, compute_mode, - simplify_gen_unary (NOT, compute_mode, - gen_binary (ASHIFT, - compute_mode, - mask, pos), - compute_mode), - inner), - gen_binary (ASHIFT, compute_mode, - gen_binary (AND, compute_mode, - gen_lowpart - (compute_mode, SET_SRC (x)), - mask), - pos))); + mask = GEN_INT (((HOST_WIDE_INT) 1 << len) - 1); + cleared = simplify_gen_binary (AND, compute_mode, + simplify_gen_unary (NOT, compute_mode, + simplify_gen_binary (ASHIFT, + compute_mode, + mask, pos), + compute_mode), + inner); + masked = simplify_gen_binary (ASHIFT, compute_mode, + simplify_gen_binary ( + AND, compute_mode, + gen_lowpart (compute_mode, SET_SRC (x)), + mask), + pos); + + x = gen_rtx_SET (VOIDmode, copy_rtx (inner), + simplify_gen_binary (IOR, compute_mode, + cleared, masked)); } return x; @@ -6559,8 +6497,8 @@ extract_left_shift (rtx x, int count) if (GET_CODE (XEXP (x, 1)) == CONST_INT && (INTVAL (XEXP (x, 1)) & ((((HOST_WIDE_INT) 1 << count)) - 1)) == 0 && (tem = extract_left_shift (XEXP (x, 0), count)) != 0) - return gen_binary (code, mode, tem, - GEN_INT (INTVAL (XEXP (x, 1)) >> count)); + return simplify_gen_binary (code, mode, tem, + GEN_INT (INTVAL (XEXP (x, 1)) >> count)); break; @@ -7046,7 +6984,8 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, && (cval & ((HOST_WIDE_INT) 1 << (width - 1))) != 0) cval |= (HOST_WIDE_INT) -1 << width; - y = gen_binary (AND, GET_MODE (x), XEXP (x, 0), GEN_INT (cval)); + y = simplify_gen_binary (AND, GET_MODE (x), + XEXP (x, 0), GEN_INT (cval)); if (rtx_cost (y, SET) < rtx_cost (x, SET)) x = y; } @@ -7138,10 +7077,10 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, { temp = GEN_INT ((INTVAL (XEXP (x, 1)) & mask) << INTVAL (XEXP (XEXP (x, 0), 1))); - temp = gen_binary (GET_CODE (x), GET_MODE (x), - XEXP (XEXP (x, 0), 0), temp); - x = gen_binary (LSHIFTRT, GET_MODE (x), temp, - XEXP (XEXP (x, 0), 1)); + temp = simplify_gen_binary (GET_CODE (x), GET_MODE (x), + XEXP (XEXP (x, 0), 0), temp); + x = simplify_gen_binary (LSHIFTRT, GET_MODE (x), temp, + XEXP (XEXP (x, 0), 1)); return force_to_mode (x, mode, mask, reg, next_select); } @@ -7157,7 +7096,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, reg, next_select)); if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0) || op1 != XEXP (x, 1)) - x = gen_binary (code, op_mode, op0, op1); + x = simplify_gen_binary (code, op_mode, op0, op1); break; case ASHIFT: @@ -7191,7 +7130,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, mask, reg, next_select)); if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0)) - x = gen_binary (code, op_mode, op0, XEXP (x, 1)); + x = simplify_gen_binary (code, op_mode, op0, XEXP (x, 1)); break; case LSHIFTRT: @@ -7218,7 +7157,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, inner = force_to_mode (inner, op_mode, inner_mask, reg, next_select); if (GET_MODE (x) != op_mode || inner != XEXP (x, 0)) - x = gen_binary (LSHIFTRT, op_mode, inner, XEXP (x, 1)); + x = simplify_gen_binary (LSHIFTRT, op_mode, inner, XEXP (x, 1)); } /* If we have (and (lshiftrt FOO C1) C2) where the combination of the @@ -7240,9 +7179,9 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, /* Must be more sign bit copies than the mask needs. */ && ((int) num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0))) >= exact_log2 (mask + 1))) - x = gen_binary (LSHIFTRT, GET_MODE (x), XEXP (x, 0), - GEN_INT (GET_MODE_BITSIZE (GET_MODE (x)) - - exact_log2 (mask + 1))); + x = simplify_gen_binary (LSHIFTRT, GET_MODE (x), XEXP (x, 0), + GEN_INT (GET_MODE_BITSIZE (GET_MODE (x)) + - exact_log2 (mask + 1))); goto shiftrt; @@ -7307,7 +7246,8 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, /* If MASK is 1, convert this to an LSHIFTRT. This can be done even if the shift count isn't a constant. */ if (mask == 1) - x = gen_binary (LSHIFTRT, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)); + x = simplify_gen_binary (LSHIFTRT, GET_MODE (x), + XEXP (x, 0), XEXP (x, 1)); shiftrt: @@ -7372,8 +7312,10 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask, { temp = gen_int_mode (mask << INTVAL (XEXP (XEXP (x, 0), 1)), GET_MODE (x)); - temp = gen_binary (XOR, GET_MODE (x), XEXP (XEXP (x, 0), 0), temp); - x = gen_binary (LSHIFTRT, GET_MODE (x), temp, XEXP (XEXP (x, 0), 1)); + temp = simplify_gen_binary (XOR, GET_MODE (x), + XEXP (XEXP (x, 0), 0), temp); + x = simplify_gen_binary (LSHIFTRT, GET_MODE (x), + temp, XEXP (XEXP (x, 0), 1)); return force_to_mode (x, mode, mask, reg, next_select); } @@ -7484,8 +7426,19 @@ if_then_else_cond (rtx x, rtx *ptrue, rtx *pfalse) else if (cond1 == 0) true1 = copy_rtx (true1); - *ptrue = gen_binary (code, mode, true0, true1); - *pfalse = gen_binary (code, mode, false0, false1); + if (COMPARISON_P (x)) + { + *ptrue = simplify_gen_relational (code, mode, VOIDmode, + true0, true1); + *pfalse = simplify_gen_relational (code, mode, VOIDmode, + false0, false1); + } + else + { + *ptrue = simplify_gen_binary (code, mode, true0, true1); + *pfalse = simplify_gen_binary (code, mode, false0, false1); + } + return cond0 ? cond0 : cond1; } @@ -7506,22 +7459,22 @@ if_then_else_cond (rtx x, rtx *ptrue, rtx *pfalse) if (COMPARISON_P (cond0) && COMPARISON_P (cond1) - && ((GET_CODE (cond0) == combine_reversed_comparison_code (cond1) + && ((GET_CODE (cond0) == reversed_comparison_code (cond1, NULL) && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0)) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1))) || ((swap_condition (GET_CODE (cond0)) - == combine_reversed_comparison_code (cond1)) + == reversed_comparison_code (cond1, NULL)) && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 1)) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0)))) && ! side_effects_p (x)) { - *ptrue = gen_binary (MULT, mode, op0, const_true_rtx); - *pfalse = gen_binary (MULT, mode, - (code == MINUS - ? simplify_gen_unary (NEG, mode, op1, - mode) - : op1), - const_true_rtx); + *ptrue = simplify_gen_binary (MULT, mode, op0, const_true_rtx); + *pfalse = simplify_gen_binary (MULT, mode, + (code == MINUS + ? simplify_gen_unary (NEG, mode, + op1, mode) + : op1), + const_true_rtx); return cond0; } } @@ -7537,11 +7490,11 @@ if_then_else_cond (rtx x, rtx *ptrue, rtx *pfalse) if (COMPARISON_P (cond0) && COMPARISON_P (cond1) - && ((GET_CODE (cond0) == combine_reversed_comparison_code (cond1) + && ((GET_CODE (cond0) == reversed_comparison_code (cond1, NULL) && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0)) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1))) || ((swap_condition (GET_CODE (cond0)) - == combine_reversed_comparison_code (cond1)) + == reversed_comparison_code (cond1, NULL)) && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 1)) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0)))) && ! side_effects_p (x)) @@ -7686,7 +7639,7 @@ known_cond (rtx x, enum rtx_code cond, rtx reg, rtx val) if (comparison_dominates_p (cond, code)) return const_true_rtx; - code = combine_reversed_comparison_code (x); + code = reversed_comparison_code (x, NULL); if (code != UNKNOWN && comparison_dominates_p (cond, code)) return const0_rtx; @@ -8056,8 +8009,8 @@ apply_distributive_law (rtx x) || GET_MODE_SIZE (GET_MODE (SUBREG_REG (lhs))) > UNITS_PER_WORD) return x; - tem = gen_binary (code, GET_MODE (SUBREG_REG (lhs)), - SUBREG_REG (lhs), SUBREG_REG (rhs)); + tem = simplify_gen_binary (code, GET_MODE (SUBREG_REG (lhs)), + SUBREG_REG (lhs), SUBREG_REG (rhs)); return gen_lowpart (GET_MODE (x), tem); default: @@ -8083,7 +8036,7 @@ apply_distributive_law (rtx x) return x; /* Form the new inner operation, seeing if it simplifies first. */ - tem = gen_binary (code, GET_MODE (x), lhs, rhs); + tem = simplify_gen_binary (code, GET_MODE (x), lhs, rhs); /* There is one exception to the general way of distributing: (a | c) ^ (b | c) -> (a ^ b) & ~c */ @@ -8096,8 +8049,76 @@ apply_distributive_law (rtx x) /* We may be able to continuing distributing the result, so call ourselves recursively on the inner operation before forming the outer operation, which we return. */ - return gen_binary (inner_code, GET_MODE (x), - apply_distributive_law (tem), other); + return simplify_gen_binary (inner_code, GET_MODE (x), + apply_distributive_law (tem), other); +} + +/* See if X is of the form (* (+ A B) C), and if so convert to + (+ (* A C) (* B C)) and try to simplify. + + Most of the time, this results in no change. However, if some of + the operands are the same or inverses of each other, simplifications + will result. + + For example, (and (ior A B) (not B)) can occur as the result of + expanding a bit field assignment. When we apply the distributive + law to this, we get (ior (and (A (not B))) (and (B (not B)))), + which then simplifies to (and (A (not B))). + + Note that no checks happen on the validity of applying the inverse + distributive law. This is pointless since we can do it in the + few places where this routine is called. + + N is the index of the term that is decomposed (the arithmetic operation, + i.e. (+ A B) in the first example above). !N is the index of the term that + is distributed, i.e. of C in the first example above. */ +static rtx +distribute_and_simplify_rtx (rtx x, int n) +{ + enum machine_mode mode; + enum rtx_code outer_code, inner_code; + rtx decomposed, distributed, inner_op0, inner_op1, new_op0, new_op1, tmp; + + decomposed = XEXP (x, n); + if (!ARITHMETIC_P (decomposed)) + return NULL_RTX; + + mode = GET_MODE (x); + outer_code = GET_CODE (x); + distributed = XEXP (x, !n); + + inner_code = GET_CODE (decomposed); + inner_op0 = XEXP (decomposed, 0); + inner_op1 = XEXP (decomposed, 1); + + /* Special case (and (xor B C) (not A)), which is equivalent to + (xor (ior A B) (ior A C)) */ + if (outer_code == AND && inner_code == XOR && GET_CODE (distributed) == NOT) + { + distributed = XEXP (distributed, 0); + outer_code = IOR; + } + + if (n == 0) + { + /* Distribute the second term. */ + new_op0 = simplify_gen_binary (outer_code, mode, inner_op0, distributed); + new_op1 = simplify_gen_binary (outer_code, mode, inner_op1, distributed); + } + else + { + /* Distribute the first term. */ + new_op0 = simplify_gen_binary (outer_code, mode, distributed, inner_op0); + new_op1 = simplify_gen_binary (outer_code, mode, distributed, inner_op1); + } + + tmp = apply_distributive_law (simplify_gen_binary (inner_code, mode, + new_op0, new_op1)); + if (GET_CODE (tmp) != outer_code + && rtx_cost (tmp, SET) < rtx_cost (x, SET)) + return tmp; + + return NULL_RTX; } /* We have X, a logical `and' of VAROP with the constant CONSTOP, to be done @@ -8164,11 +8185,15 @@ simplify_and_const_int (rtx x, enum machine_mode mode, rtx varop, gen_lowpart (mode, apply_distributive_law - (gen_binary (GET_CODE (varop), GET_MODE (varop), - simplify_and_const_int (NULL_RTX, GET_MODE (varop), - XEXP (varop, 0), constop), - simplify_and_const_int (NULL_RTX, GET_MODE (varop), - XEXP (varop, 1), constop)))); + (simplify_gen_binary (GET_CODE (varop), GET_MODE (varop), + simplify_and_const_int (NULL_RTX, + GET_MODE (varop), + XEXP (varop, 0), + constop), + simplify_and_const_int (NULL_RTX, + GET_MODE (varop), + XEXP (varop, 1), + constop)))); /* If VAROP is PLUS, and the constant is a mask of low bite, distribute the AND and see if one of the operands simplifies to zero. If so, we @@ -8209,7 +8234,7 @@ simplify_and_const_int (rtx x, enum machine_mode mode, rtx varop, constop = trunc_int_for_mode (constop, mode); /* See how much, if any, of X we can use. */ if (x == 0 || GET_CODE (x) != AND || GET_MODE (x) != mode) - x = gen_binary (AND, mode, varop, GEN_INT (constop)); + x = simplify_gen_binary (AND, mode, varop, GEN_INT (constop)); else { @@ -8728,8 +8753,10 @@ simplify_shift_const (rtx x, enum rtx_code code, && exact_log2 (INTVAL (XEXP (varop, 1))) >= 0) { varop - = gen_binary (ASHIFT, GET_MODE (varop), XEXP (varop, 0), - GEN_INT (exact_log2 (INTVAL (XEXP (varop, 1))))); + = simplify_gen_binary (ASHIFT, GET_MODE (varop), + XEXP (varop, 0), + GEN_INT (exact_log2 ( + INTVAL (XEXP (varop, 1))))); continue; } break; @@ -8740,8 +8767,10 @@ simplify_shift_const (rtx x, enum rtx_code code, && exact_log2 (INTVAL (XEXP (varop, 1))) >= 0) { varop - = gen_binary (LSHIFTRT, GET_MODE (varop), XEXP (varop, 0), - GEN_INT (exact_log2 (INTVAL (XEXP (varop, 1))))); + = simplify_gen_binary (LSHIFTRT, GET_MODE (varop), + XEXP (varop, 0), + GEN_INT (exact_log2 ( + INTVAL (XEXP (varop, 1))))); continue; } break; @@ -8996,7 +9025,8 @@ simplify_shift_const (rtx x, enum rtx_code code, rtx rhs = simplify_shift_const (NULL_RTX, code, shift_mode, XEXP (varop, 1), count); - varop = gen_binary (GET_CODE (varop), shift_mode, lhs, rhs); + varop = simplify_gen_binary (GET_CODE (varop), shift_mode, + lhs, rhs); varop = apply_distributive_law (varop); count = 0; @@ -9271,7 +9301,8 @@ simplify_shift_const (rtx x, enum rtx_code code, else if (GET_RTX_CLASS (outer_op) == RTX_UNARY) x = simplify_gen_unary (outer_op, result_mode, x, result_mode); else - x = gen_binary (outer_op, result_mode, x, GEN_INT (outer_const)); + x = simplify_gen_binary (outer_op, result_mode, x, + GEN_INT (outer_const)); } return x; @@ -9506,63 +9537,6 @@ gen_lowpart_for_combine (enum machine_mode omode, rtx x) return gen_rtx_CLOBBER (imode, const0_rtx); } -/* These routines make binary and unary operations by first seeing if they - fold; if not, a new expression is allocated. */ - -static rtx -gen_binary (enum rtx_code code, enum machine_mode mode, rtx op0, rtx op1) -{ - rtx result; - rtx tem; - - if (GET_CODE (op0) == CLOBBER) - return op0; - else if (GET_CODE (op1) == CLOBBER) - return op1; - - if (GET_RTX_CLASS (code) == RTX_COMM_ARITH - && swap_commutative_operands_p (op0, op1)) - tem = op0, op0 = op1, op1 = tem; - - if (GET_RTX_CLASS (code) == RTX_COMPARE - || GET_RTX_CLASS (code) == RTX_COMM_COMPARE) - { - enum machine_mode op_mode = GET_MODE (op0); - - /* Strip the COMPARE from (REL_OP (compare X Y) 0) to get - just (REL_OP X Y). */ - if (GET_CODE (op0) == COMPARE && op1 == const0_rtx) - { - op1 = XEXP (op0, 1); - op0 = XEXP (op0, 0); - op_mode = GET_MODE (op0); - } - - if (op_mode == VOIDmode) - op_mode = GET_MODE (op1); - result = simplify_relational_operation (code, mode, op_mode, op0, op1); - } - else - result = simplify_binary_operation (code, mode, op0, op1); - - if (result) - return result; - - /* Put complex operands first and constants second. */ - if (GET_RTX_CLASS (code) == RTX_COMM_ARITH - && swap_commutative_operands_p (op0, op1)) - return gen_rtx_fmt_ee (code, mode, op1, op0); - - /* If we are turning off bits already known off in OP0, we need not do - an AND. */ - else if (code == AND && GET_CODE (op1) == CONST_INT - && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT - && (nonzero_bits (op0, mode) & ~INTVAL (op1)) == 0) - return op0; - - return gen_rtx_fmt_ee (code, mode, op0, op1); -} - /* Simplify a comparison between *POP0 and *POP1 where CODE is the comparison code that will be tested. @@ -10304,7 +10278,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) if (code == LT || code == NE) new_code = GET_CODE (op0); else - new_code = combine_reversed_comparison_code (op0); + new_code = reversed_comparison_code (op0, NULL); if (new_code != UNKNOWN) { @@ -10431,9 +10405,9 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) && c1 != mask && c1 != GET_MODE_MASK (tmode)) { - op0 = gen_binary (AND, tmode, - SUBREG_REG (XEXP (op0, 0)), - gen_int_mode (c1, tmode)); + op0 = simplify_gen_binary (AND, tmode, + SUBREG_REG (XEXP (op0, 0)), + gen_int_mode (c1, tmode)); op0 = gen_lowpart (mode, op0); continue; } @@ -10577,12 +10551,12 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) { rtx inner = XEXP (XEXP (XEXP (op0, 0), 0), 0); rtx add_const = XEXP (XEXP (op0, 0), 1); - rtx new_const = gen_binary (ASHIFTRT, GET_MODE (op0), add_const, - XEXP (op0, 1)); + rtx new_const = simplify_gen_binary (ASHIFTRT, GET_MODE (op0), + add_const, XEXP (op0, 1)); - op0 = gen_binary (PLUS, tmode, - gen_lowpart (tmode, inner), - new_const); + op0 = simplify_gen_binary (PLUS, tmode, + gen_lowpart (tmode, inner), + new_const); continue; } @@ -10735,11 +10709,11 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) make a new AND in the proper mode. */ if (GET_CODE (op0) == AND && !have_insn_for (AND, mode)) - op0 = gen_binary (AND, tmode, - gen_lowpart (tmode, - XEXP (op0, 0)), - gen_lowpart (tmode, - XEXP (op0, 1))); + op0 = simplify_gen_binary (AND, tmode, + gen_lowpart (tmode, + XEXP (op0, 0)), + gen_lowpart (tmode, + XEXP (op0, 1))); op0 = gen_lowpart (tmode, op0); if (zero_extended && GET_CODE (op1) == CONST_INT) @@ -10754,10 +10728,11 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) if (op1 == const0_rtx && (code == LT || code == GE) && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) { - op0 = gen_binary (AND, tmode, - gen_lowpart (tmode, op0), - GEN_INT ((HOST_WIDE_INT) 1 - << (GET_MODE_BITSIZE (mode) - 1))); + op0 = simplify_gen_binary (AND, tmode, + gen_lowpart (tmode, op0), + GEN_INT ((HOST_WIDE_INT) 1 + << (GET_MODE_BITSIZE (mode) + - 1))); code = (code == LT) ? NE : EQ; break; } @@ -10775,38 +10750,6 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) return code; } -/* Like jump.c' reversed_comparison_code, but use combine infrastructure for - searching backward. */ -static enum rtx_code -combine_reversed_comparison_code (rtx exp) -{ - enum rtx_code code1 = reversed_comparison_code (exp, NULL); - rtx x; - - if (code1 != UNKNOWN - || GET_MODE_CLASS (GET_MODE (XEXP (exp, 0))) != MODE_CC) - return code1; - /* Otherwise try and find where the condition codes were last set and - use that. */ - x = get_last_value (XEXP (exp, 0)); - if (!x || GET_CODE (x) != COMPARE) - return UNKNOWN; - return reversed_comparison_code_parts (GET_CODE (exp), - XEXP (x, 0), XEXP (x, 1), NULL); -} - -/* Return comparison with reversed code of EXP and operands OP0 and OP1. - Return NULL_RTX in case we fail to do the reversal. */ -static rtx -reversed_comparison (rtx exp, enum machine_mode mode, rtx op0, rtx op1) -{ - enum rtx_code reversed_code = combine_reversed_comparison_code (exp); - if (reversed_code == UNKNOWN) - return NULL_RTX; - else - return gen_binary (reversed_code, mode, op0, op1); -} - /* Utility function for record_value_for_reg. Count number of rtxs in X. */ static int |