This patch implements transform for pattern "(~A & B) ^ A -> (A | B)".
And this pattern is already implemented in gcc.
Differential D86395
[InstCombine] transform pattern "(~A & B) ^ A -> (A | B)" added spatel on Aug 22 2020, 4:45 AM. Authored by
Details This patch implements transform for pattern "(~A & B) ^ A -> (A | B)". And this pattern is already implemented in gcc.
Diff Detail Event Timeline
Comment Actions The tests should be pre-committed with current CHECK lines (ie, without this patch), so we just see the diffs - and can confirm that the tests actually represent the patterns shown in the test comments.
Comment Actions I have created IR and assembly files like below (without this patch), And I am not getting "%x = add i32 %p, 42 ; thwart complexity-based canonicalization" $ cat test.c int f(int A,int B) { return(A ^ (~A & B)); } $ clang test.c -S -O1 -emit-llvm $ cat test.ll ... ... define dso_local i32 @f(i32 %0, i32 %1) local_unnamed_addr #0 { %3 = xor i32 %0, -1 %4 = and i32 %3, %1 %5 = xor i32 %4, %0 ret i32 %5 } ... ... $ clang test.c -S -O1 $ cat test.s ... f: # @f .cfi_startproc # %bb.0: movl %edi, %eax notl %eax andl %esi, %eax xorl %edi, %eax retq .Lfunc_end0: ... Comment Actions Assembly is irrelevant. This is an IR to IR patch. Comment Actions @spatel ,Thank you so much for such informative reply. Now anything is pending in review which need to be update?
Comment Actions I don't see any changes to the tests from the earlier draft of the patch. That is, test1 and test2 are identical unless I'm not seeing correctly? Please open a separate review to add only the test file, so we can work through that independently of the code change. You might consider adding tests to an existing file like llvm/test/Transforms/InstCombine/xor.ll instead of creating a new file for just ~4 tests. If my earlier comment about the tests did not make sense, please grep for "thwart" in this test directory to see examples. Comment Actions A bit of clarification needed(I'm still new to this) @spatel . x = add i32 %p, 42 ; thwart complexity-based canonicalization And How to create this. ?? Because I have tried to create IR(test case) with optimization without this patch but i am not getting this line. Comment Actions Sure - "42" represents an arbitrary value. I'm not sure if this was the original joke, but see - https://en.wikipedia.org/wiki/Phrases_from_The_Hitchhiker%27s_Guide_to_the_Galaxy#Answer_to_the_Ultimate_Question_of_Life,_the_Universe,_and_Everything_(42)
Instcombine is changing the IR before it reaches your patched code. I suggest again to step through your current "test6" in the debugger and/or run "opt -debug" to see what is happening. The "thwart" instruction is creating an xor that has binops as both operands. That is required to prevent instcombine from rearranging the operands before it reaches your code. Comment Actions @spatel test cases are updated as per your review comments. Thanks for this. IR Without my patch(for test52):- define i32 @test52(i32 %0, i32 %1) { %3 = xor i32 %0, -1 %4 = and i32 %3, %1 %5 = xor i32 %4, %0 ret i32 %5 } IR after my patch(Transformation applied):- define i32 @test52(i32 %0, i32 %1) { %3 = or i32 %1, %0 ret i32 %3 } Comment Actions I committed the baseline tests, so we can see diffs. Please rebase.
Please update the tests and/or test comments if that is not working. This comment was removed by xbolva00.
Comment Actions Then I think something is wrong with your build environment. If I remove the commutative matchers, I get 0 test diffs. This makes sense given that test53 is still identical to test52 in terms of commutative matching (the only differences now are the value types).
Comment Actions @spatel it is also same for me. If I remove both the commutative matchers than I also get 0 test diffs.(change x_c_Xor with x_Xor and x_c_And with x_And)
Added test53 to cover vector test. I will update/remove the test53. Comment Actions We are going in circles. I'll give this 1 more try, and if it still doesn't make sense, then maybe another reviewer can better communicate what we expect for the tests:
Comment Actions @spatel, apologies for the confusion created due to multiple revisions. Let's consider the initial pattern and associated commutative version of this. initial pattern:- (~A & B) ^ A -> (A | B) And 8 possible commutative version of this. 1) (~A & B) ^ A -> (A | B) 2) (~B & A) ^ B -> (A | B) 3) (B & ~A) ^ A -> (A | B) --> identical to 1) 4) A ^ (~A & B) -> (A | B) --> identical to 1) 5) A ^ (B & ~A) -> (A | B) --> identical to 1) 6) (A & ~B) ^ B -> (A | B) --> identical to 2) 7) B ^ (~B & A) -> (A | B) --> identical to 2) 8) B ^ (A & ~B) -> (A | B) --> identical to 2) As you may notice that all these patterns (IR) are reducing to 2 unique patterns (pattern 1 and pattern 2). Comment Actions How so?
Comment Actions No. First, there are not 8 unique patterns. There are 4. For the sake of consistency with the code that you have proposed, you can always think of "A" as the operand with a not. Renaming that to "B" or "Foo" or anything else does not change the logic. Comment Actions And do you plan on "manually testing and re-verifying" that on each commit to LLVM as a whole made by everyone for the forseeable future? Comment Actions Rebased after adding test coverage for the 4 commuted variants. Comment Actions The tests now provide commutative coverage for the 4 variations of the pattern. If there are no other suggestions, can someone officially approve? Thanks! |
What about the case where the and is Op1?