This is attacking case 3 of PR 94174. In v4, I attempt to bring over as many patterns from config/arm as are applicable. It's not too far away from what I had from v2.
In the process of checking all of the combinations (below), I discovered that we could probably have a better represenation for ccmp. One that the optimizers can actually do something with, rather than the if_then_else+unspec combo that we have now. A special case of that is in the last patch: ccmp_iorne. I think it should be possible to come up with some sort of logical combo that would apply to all cases, but haven't put enough thought into the problem. r~ Richard Henderson (12): aarch64: Provide expander for sub<GPI>3_compare1 aarch64: Match add<GPI>3_carryin expander and insn aarch64: Add cset, csetm, cinc patterns for carry/borrow aarch64: Add const_dword_umaxp1 aarch64: Improvements to aarch64_select_cc_mode from arm aarch64: Introduce aarch64_expand_addsubti aarch64: Rename CC_ADCmode to CC_NOTCmode arm: Merge CC_ADC and CC_B to CC_NOTC aarch64: Use CC_NOTCmode for double-word subtract aarch64: Adjust result of aarch64_gen_compare_reg aarch64: Accept 0 as first argument to compares aarch64: Implement TImode comparisons gcc/config/aarch64/aarch64-protos.h | 10 +- gcc/config/aarch64/aarch64.c | 356 ++++++++----- gcc/config/arm/arm.c | 30 +- gcc/testsuite/gcc.target/aarch64/asm-flag-1.c | 3 +- gcc/config/aarch64/aarch64-modes.def | 6 +- gcc/config/aarch64/aarch64-simd.md | 18 +- gcc/config/aarch64/aarch64-speculation.cc | 5 +- gcc/config/aarch64/aarch64.md | 473 +++++++++++------- gcc/config/aarch64/iterators.md | 3 + gcc/config/aarch64/predicates.md | 22 +- gcc/config/arm/arm-modes.def | 12 +- gcc/config/arm/arm.md | 36 +- gcc/config/arm/iterators.md | 2 +- gcc/config/arm/predicates.md | 4 +- 14 files changed, 580 insertions(+), 400 deletions(-) --- typedef signed long long s64; typedef unsigned long long u64; typedef __uint128_t u128; typedef __int128_t s128; #define i128(hi,lo) (((u128)(hi) << 64) | (u64)(lo)) int eq(u128 a, u128 b) { return a == b; } int ne(u128 a, u128 b) { return a != b; } int ltu(u128 a, u128 b) { return a < b; } int geu(u128 a, u128 b) { return a >= b; } int leu(u128 a, u128 b) { return a <= b; } int gtu(u128 a, u128 b) { return a > b; } int lt(s128 a, s128 b) { return a < b; } int ge(s128 a, s128 b) { return a >= b; } int le(s128 a, s128 b) { return a <= b; } int gt(s128 a, s128 b) { return a > b; } int eqS(u128 a, u64 b) { return a == b; } int neS(u128 a, u64 b) { return a != b; } int ltuS(u128 a, u64 b) { return a < b; } int geuS(u128 a, u64 b) { return a >= b; } int leuS(u128 a, u64 b) { return a <= b; } int gtuS(u128 a, u64 b) { return a > b; } int ltS(s128 a, s64 b) { return a < b; } int geS(s128 a, s64 b) { return a >= b; } int leS(s128 a, s64 b) { return a <= b; } int gtS(s128 a, s64 b) { return a > b; } int eqSH(u128 a, u64 b) { return a == (u128)b << 64; } int neSH(u128 a, u64 b) { return a != (u128)b << 64; } int ltuSH(u128 a, u64 b) { return a < (u128)b << 64; } int geuSH(u128 a, u64 b) { return a >= (u128)b << 64; } int leuSH(u128 a, u64 b) { return a <= (u128)b << 64; } int gtuSH(u128 a, u64 b) { return a > (u128)b << 64; } int ltSH(s128 a, s64 b) { return a < (s128)b << 64; } int geSH(s128 a, s64 b) { return a >= (s128)b << 64; } int leSH(s128 a, s64 b) { return a <= (s128)b << 64; } int gtSH(s128 a, s64 b) { return a > (s128)b << 64; } int eqFFHS(u128 a, u64 b) { return a == i128(-1,b); } int neFFHS(u128 a, u64 b) { return a != i128(-1,b); } int ltuFFHS(u128 a, u64 b) { return a < i128(-1,b); } int geuFFHS(u128 a, u64 b) { return a >= i128(-1,b); } int leuFFHS(u128 a, u64 b) { return a <= i128(-1,b); } int gtuFFHS(u128 a, u64 b) { return a > i128(-1,b); } int ltFFHS(s128 a, s64 b) { return a < (s128)i128(-1,b); } int geFFHS(s128 a, s64 b) { return a >= (s128)i128(-1,b); } int leFFHS(s128 a, s64 b) { return a <= (s128)i128(-1,b); } int gtFFHS(s128 a, s64 b) { return a > (s128)i128(-1,b); } int eq0(u128 a) { return a == 0; } int ne0(u128 a) { return a != 0; } int ltu0(u128 a) { return a < 0; } int geu0(u128 a) { return a >= 0; } int leu0(u128 a) { return a <= 0; } int gtu0(u128 a) { return a > 0; } int lt0(s128 a) { return a < 0; } int ge0(s128 a) { return a >= 0; } int le0(s128 a) { return a <= 0; } int gt0(s128 a) { return a > 0; } int eq1(u128 a) { return a == 1; } int ne1(u128 a) { return a != 1; } int ltu1(u128 a) { return a < 1; } int geu1(u128 a) { return a >= 1; } int leu1(u128 a) { return a <= 1; } int gtu1(u128 a) { return a > 1; } int lt1(s128 a) { return a < 1; } int ge1(s128 a) { return a >= 1; } int le1(s128 a) { return a <= 1; } int gt1(s128 a) { return a > 1; } int eqm1(u128 a) { return a == -1; } int nem1(u128 a) { return a != -1; } int ltum1(u128 a) { return a < -1; } int geum1(u128 a) { return a >= -1; } int leum1(u128 a) { return a <= -1; } int gtum1(u128 a) { return a > -1; } int ltm1(s128 a) { return a < -1; } int gem1(s128 a) { return a >= -1; } int lem1(s128 a) { return a <= -1; } int gtm1(s128 a) { return a > -1; } int eq42(u128 a) { return a == 42; } int ne42(u128 a) { return a != 42; } int ltu42(u128 a) { return a < 42; } int geu42(u128 a) { return a >= 42; } int leu42(u128 a) { return a <= 42; } int gtu42(u128 a) { return a > 42; } int lt42(s128 a) { return a < 42; } int ge42(s128 a) { return a >= 42; } int le42(s128 a) { return a <= 42; } int gt42(s128 a) { return a > 42; } int eqFF(u128 a) { return a == (u64)-1; } int neFF(u128 a) { return a != (u64)-1; } int ltuFF(u128 a) { return a < (u64)-1; } int geuFF(u128 a) { return a >= (u64)-1; } int leuFF(u128 a) { return a <= (u64)-1; } int gtuFF(u128 a) { return a > (u64)-1; } int ltFF(s128 a) { return a < (u64)-1; } int geFF(s128 a) { return a >= (u64)-1; } int leFF(s128 a) { return a <= (u64)-1; } int gtFF(s128 a) { return a > (u64)-1; } int eq1H(u128 a) { return a == i128(1,0); } int ne1H(u128 a) { return a != i128(1,0); } int ltu1H(u128 a) { return a < i128(1,0); } int geu1H(u128 a) { return a >= i128(1,0); } int leu1H(u128 a) { return a <= i128(1,0); } int gtu1H(u128 a) { return a > i128(1,0); } int lt1H(s128 a) { return a < i128(1,0); } int ge1H(s128 a) { return a >= i128(1,0); } int le1H(s128 a) { return a <= i128(1,0); } int gt1H(s128 a) { return a > i128(1,0); } int eqFFH(u128 a) { return a == i128(-1,0); } int neFFH(u128 a) { return a != i128(-1,0); } int ltuFFH(u128 a) { return a < i128(-1,0); } int geuFFH(u128 a) { return a >= i128(-1,0); } int leuFFH(u128 a) { return a <= i128(-1,0); } int gtuFFH(u128 a) { return a > i128(-1,0); } int ltFFH(s128 a) { return a < i128(-1,0); } int geFFH(s128 a) { return a >= i128(-1,0); } int leFFH(s128 a) { return a <= i128(-1,0); } int gtFFH(s128 a) { return a > i128(-1,0); }