)]}'
{
  "commit": "56c81c325cccf432954ddea4c73069e2fa047922",
  "tree": "5b8e1f112c8221f5d5f458ae7cf7102ce024a0bb",
  "parents": [
    "e91f79891fc657d48310f82da0da61eb4a0587ed"
  ],
  "author": {
    "name": "Dominic P",
    "email": "gcc@gcc.dp11.uk",
    "time": "Sun Sep 13 13:34:45 2026 -0600"
  },
  "committer": {
    "name": "Jeff Law",
    "email": "jeffreyalaw@gmail.com",
    "time": "Sun Sep 13 13:34:45 2026 -0600"
  },
  "message": "[PATCH] match.pd: Fold ((X + C1) | (C2 - X)) \u003c 0 to an unsigned range test\n\nThe sign bit of (X + C1) | (C2 - X) is the disjunction of the two sign\nbits, so the test is X \u003c -C1 || X \u003e C2, that is (unsigned) (X + C1) \u003e\nC1 + C2.  With U for X + C1 and D for C1 + C2 the second operand is\nD - U, and for 0 \u003c\u003d D \u003c 2 ** (prec - 1) the disjunction is negative\nexactly when U \u003e D unsigned; D non-negative in the type is the only\nguard, and no no-overflow assumption is involved.  D is tested with\nwi::ge_p (..., SIGNED), not tree_int_cst_sgn: after over_widening the\nconstants have an unsigned type, for which tree_int_cst_sgn is 1\nwhatever the bit pattern.\n\nMatched in every spelling that reaches match.pd: the comparison, the\ncomparison of a same-precision conversion of it (what narrow types and\nunsigned data reduce to), the sign-bit extraction x264 uses in\nencoder/cavlc.c, and the C1 \u003d\u003d 0 and C2 \u003d\u003d 0 forms, where the addition\nis absent and the subtraction is a negate.  Those need matchers of their\nown: genmatch cannot make a binary operand optional, and negate does not\nfit a (for) with minus.  The disjunction needs single_use, or both\noperands stay live and the fold only adds a compare (7 -\u003e 9 x86_64).\n\nABS_EXPR \u003cX\u003e \u003e C and \u003c\u003d C are the same range test, and so is the\nABSU_EXPR pair; ABSU_EXPR needs no assumption about the minimum value,\nABS_EXPR needs TYPE_OVERFLOW_UNDEFINED.  C \u003d\u003d TYPE_MAX is left to the\nexisting fold to a constant; \u003d\u003d and !\u003d are not range tests and are\nuntouched.  The addition is built in the unsigned type, so the fold does\nnot invent a signed overflow for the sanitizer to report.\n\nAll of it is GIMPLE-only, as single_use is always true on GENERIC, and\ndeclines under -fsanitize\u003dsigned-integer-overflow, where the operand it\ndrops carries a check.  The nearest pattern, \"Optimize (a | b) \u003c 0 to\na \u003c 0 if b is non-negative\", does not fire as neither operand is known\nnon-negative.  Not matched: ((X + C1) | ~X) \u003c 0, spelled with a\nBIT_NOT_EXPR rather than a minus, and the arithmetic-shift 0/-1 mask\nspelling, which is also how vectors reach match.pd.\n\naarch64 -O2: the x264 site 6 -\u003e 4 insns, the range test 6 -\u003e 4, abs \u003e C\n5 -\u003e 4; x86_64 6 -\u003e 5, 6 -\u003e 5, 7 -\u003e 5.  Checked against a bit-exact\nmodel over every 16-bit X for 26 constant pairs in all four spellings,\nboth ABS forms and ABSU_EXPR, and over 32-bit edge and random values.\n\nBootstrapped and regression tested on x86_64-pc-linux-gnu.\n\nAssisted-by: Claude Opus 5 (Anthropic)\n\ngcc/ChangeLog:\n\n\t* match.pd (ior_range_test, ior_range_test_1, ior_range_test_0):\n\tNew matchers.\n\t(((X + C1) | (C2 - X)) \u003c 0): New simplification.\n\t((unsigned) ((X + C1) | (C2 - X)) \u003e\u003e (prec - 1)): Likewise.\n\t(ABS_EXPR \u003cX\u003e \u003e C): Likewise.\n\ngcc/testsuite/ChangeLog:\n\n\t* gcc.dg/torture/abs-gt-1.c: New test.\n\t* gcc.dg/torture/ior-range-test-1.c: New test.\n\t* gcc.dg/tree-ssa/ior-range-test-1.c: New test.\n\t* gcc.dg/tree-ssa/ior-range-test-2.c: New test.\n\t* gcc.dg/tree-ssa/ior-range-test-3.c: New test.\n\nSigned-off-by: Dominic P \u003cgcc@gcc.dp11.uk\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "3d7091e81b79f9fa10035a1b2d7867ae76791b50",
      "old_mode": 33188,
      "old_path": "gcc/match.pd",
      "new_id": "213b118da06a5fc96dd45e911c71f8dd851ae5bd",
      "new_mode": 33188,
      "new_path": "gcc/match.pd"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "41118ebb7ba75e719b38ec07db84cfe89f397fc0",
      "new_mode": 33188,
      "new_path": "gcc/testsuite/gcc.dg/torture/abs-gt-1.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "b9002e3f25d9f4f59b65929e70d2b1ac4b3999e1",
      "new_mode": 33188,
      "new_path": "gcc/testsuite/gcc.dg/torture/ior-range-test-1.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "9d1e338bd37c8df02b5d47db9e790f27ec36aefe",
      "new_mode": 33188,
      "new_path": "gcc/testsuite/gcc.dg/tree-ssa/ior-range-test-1.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "ed6a171b9e0b70b352790e8609c2f9b5f8c25276",
      "new_mode": 33188,
      "new_path": "gcc/testsuite/gcc.dg/tree-ssa/ior-range-test-2.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "b8da406cb3514ad527134de55b490115985daa60",
      "new_mode": 33188,
      "new_path": "gcc/testsuite/gcc.dg/tree-ssa/ior-range-test-3.c"
    }
  ]
}
