On 11/24/2021 2:19 PM, Navid Rahimi via Gcc wrote:
Hi GCC community,

I have a question about pattern matching in match.pd.

So I have a pattern like this [1]:
#define CMP !=
bool f(bool c, int i) { return (c << i) CMP 0; }
bool g(bool c, int i) { return c CMP 0;}

It is verifiably correct to transfer f to g [2]. Although this pattern looks simple, but the 
problem rises because GIMPLE converts booleans to int before "<<" operation.
So at the end you have boolean->integer->boolean conversion and the shift will 
happen on the integer in the middle.

For example, for something like:

bool g(bool c){return (c << 22);}

The GIMPLE is:
_Bool g (_Bool c)
{
   int _1;
   int _2;
   _Bool _4;

   <bb 2> [local count: 1073741824]:
   _1 = (int) c_3(D);
   _2 = _1 << 22;
   _4 = _2 != 0;
   return _4;
}

I wrote a patch to fix this problem in match.pd:

+(match boolean_valued_p
+ @0
+ (if (TREE_CODE (type) == BOOLEAN_TYPE
+      && TYPE_PRECISION (type) == 1)))
+(for op (tcc_comparison truth_and truth_andif truth_or truth_orif truth_xor)
+ (match boolean_valued_p
+  (op @0 @1)))
+(match boolean_valued_p
+  (truth_not @0))

+/* cmp : ==, != */
+/* ((B0 << x) cmp 0) -> B0 cmp 0 */
+(for cmp (eq ne)
+ (simplify
+  (cmp (lshift (convert@3 boolean_valued_p@0) @1) integer_zerop@2)
+   (if (TREE_CODE (TREE_TYPE (@3)) == INTEGER_TYPE
+       && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))
+    (cmp @0 @2))))


But the problem is I am not able to restrict to the cases I am interested in. 
There are many hits in other libraries I have tried compiling with trunk+patch.

Any feedback?

1) https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98956
2) https://alive2.llvm.org/ce/z/UUTJ_v
It would help to also see the cases you're triggering that you do not want to trigger.

Could we think of the optimization opportunity in a different way?


(A << B) eq/ne 0  -> A eq/ne (0U >> B)

And I would expect the 0U >> B to get simplified to 0.

Would looking at things that way help?

jeff

Reply via email to