[PATCH] Added instruction combine to transform few more negative values addition to subtraction

Dinesh Dwivedi dinesh.d at samsung.com
Tue May 27 23:47:32 PDT 2014


This is to answer [[http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140526/218895.html | Philip's comments]]
> Both your comment and function name here seem misleading.  As far as I 
> can tell from your transforms, none are actual predicated on an argument 
> being negative.  I also see no use of subtraction.
>
> Then for this one, I'm probably missing something obvious, but where are 
> you initializing C1 and C2?  In general, the code structure here is a 
> bit hard to read.

If name of the function is misleading, I don't mind any other name. This
function tries to find if any of the operand is negative and use them to 
convert ADD to SUB and remove negation. I have not added ADD in function 
name as I am looking to use this function to convert SUB to ADD too. 

I have found 3 patterns mentioned in comment which llvm is not optimizing 
any further. This functions tries to identify those patterns and optimise them. 
I have put comments for one of the pattern in code. Other patterns are 
implemented in similar fashion. Let me know if it is still not clear.

  // Checks if any operand is negative and we can convert add to sub.
  // This function checks for following patterns
  //   ADD(XOR(OR(Z, NOT(C)), C)), 1) == NEG(AND(Z, C))
  //   ADD(XOR(AND(Z, ~C), ~C), 1)    == NEG(OR(Z, C)) if C is even
  //   XOR(AND(Z, ~C), (~C + 1))      == NEG(OR(Z, C)) if C is odd

  Value *checkForNegativeOperand(...) {
  
  ...

Here I am looking for first 2 patterns i.e. ADD(X, 1) where X is XOR-AND/ XOR-OR
which can occur on either side, following 2 lines to check if pattern is on RHS, 
then swapping LHS and RHS will put it in LHS. This is just pointer swap and will 
not change anything else. This approach will help in avoiding code duplication as 
without this, I need to do all checks for first LHS and then RHS.

  // if ONE is on other side, swap
  if (match(RHS, m_Add(m_Value(X), m_One())))
    std::swap(LHS, RHS);
	
So if LHS = B and RHS = (X + 1), after above lines, it will become LHS = (X + 1), RHS = B.

    if (match(LHS, m_Add(m_Value(X), m_One()))) {
	
After this check, we can be sure that I has (X + 1) on any side and LHS is pointing to that 
operand as match will true only of pattern matches and because of m_Value(X), Value *X will 
be pointing to X part of (X + 1) pattern.
	
    // if XOR on other side, swap
    if (match(RHS, m_Xor(m_Value(Y), m_APInt(C1))))
      std::swap(X, RHS);
	  
Above 2 lines is to check for XOR and swap (X, RHS) if pattern is LHS = (X + 1), RHS = B and 
XOR on RHS.
	  
    if (match(X, m_Xor(m_Value(Y), m_APInt(C1)))) {

Once above check is true, we will be sure that there is XOR(Y, Constant) instruction and X is 
pointing to that. Again, above swap is to avoid code duplication. Further, because of m_APInt(C1), 
if match returns true, C1 will point to constant part of XOR.
	
      // ADD(XOR(OR(Z, NOT(C)), C)), 1) == NEG(AND(Z, C))
      if (match(Y, m_Or(m_Value(Z), m_APInt(C2))) && (*C1 == ~(*C2))) {

Same way, I am checking if X is in OR(Z, C2) form where C2 == NOT(C1). if above match is true, we 
can convert initial ADD(X+1, B) instruction to SUB(B, AND(Z, C1)) as 'ADD(XOR(OR(Z, NOT(C1)), C1)), 1)' 
complete instruction can be converted to NEG(AND(Z, C1)) and ADD(NEG(AND(Z, C1)), B) is same as
SUB(B, NEG(AND(Z, C1)))
		
        Value *NewAnd = Builder->CreateAnd(Z, *C1);

Above line create AND(Z, C1)
		  
        return Builder->CreateSub(RHS, NewAnd, "", IHasNUW, IHasNSW);

and this line create SUB instruction and return to caller, where this SUB instruction can be used
to replace ADD instruction.
		  
      }
		
    ...

Returns nullptr, if I's operand does not match to any of the pattern.

   return nullptr;
 }

http://reviews.llvm.org/D3733






More information about the llvm-commits mailing list