[llvm-commits] Div->[USF]Div Patch, Attempt #2

Chris Lattner clattner at apple.com
Wed Oct 25 21:19:34 PDT 2006


On Oct 25, 2006, at 12:15 PM, Reid Spencer wrote:

> Attached are two patch files to replace the DIV instruction with 3
> instructions: SDiv, UDiv, FDiv. The first file patches llvm. The  
> second
> file patches llvm-gcc4.
>
> This is the 2nd attempt to provide the patch.  All comments are  
> welcome.
>
> Reid.
> <DIV.patch>
> <DIV-llvmgcc.patch>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

Overall, this patch looks very nice.  Please fix the one bug below  
(adding the regtest) and you are approved to check the whole mess in.



Final part (instcombine):

+Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
+  Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+  return commonDivTransforms(I);
+}

You can delete Op0/Op1.


+          // FIXME: If the operand types don't match the type of the  
divide
+          // then don't attempt this transform. The code below  
doesn't have the
+          // logic to deal with a signed divide and an unsigned  
compare (and
+          // vice versa). This is because (x /s C1) <s C2  produces  
different
+          // results than (x /s C1) <u C2 or (x /u C1) <s C2 or even
+          // (x /u C1) <u C2.  Simply casting the operands and  
result won't
+          // work. :(  The if statement below tests that condition  
and bails
+          // if it finds it.
+          const Type* DivRHSTy = DivRHS->getType();
+          unsigned DivOpCode = LHSI->getOpcode();
+          if ((DivOpCode == Instruction::SDiv && DivRHSTy->isUnsigned 
()) ||
+              (DivOpCode == Instruction::UDiv && DivRHSTy->isSigned()))
+            break;


This is good but slightly over conservative.  Please allow the xform  
to happen if the comparison is an ==/!= comparison (i.e.  
SetCondInst::isEquality() returns true).



Instruction* InstCombiner::commonDivTransforms(BinaryOperator &I) {

Please add comments above each new function.  The visit* methods  
don't need comments above them.


     // (X / C1) / C2  -> X / (C1*C2)
     if (Instruction *LHS = dyn_cast<Instruction>(Op0))
       if (Instruction::BinaryOps(LHS->getOpcode()) == I.getOpcode())

This code is a bit simpler as:

     // (X / C1) / C2  -> X / (C1*C2)
     if (BinaryOperator *LHS = dyn_cast<BinaryOperator>(Op0))
       if (LHS->getOpcode() == I.getOpcode())


   // udiv X, (Select Cond, C1, C2) --> Select Cond, (shr X, C1),  
(shr X, C2)
   // where C1&C2 are powers of two.
...
                 X = InsertNewInstBefore(
                   new CastInst(X, X->getType()->getUnsignedVersion 
()), I);

This (and similar cases) is easier/cleaner with InsertCastBefore.


               // Finally, construct the select instruction and  
return it.
               return new SelectInst(SI->getOperand(0), TSI, FSI);

In the same xform, this needs to cast the result back to the right  
type if the operation was signed.  Please write a short regtest for  
this and check it in with your patch to verify that you get this  
right (add it to the end of div.ll or something).  Something like this:

int %test(int %X, int %Y, bool %C) {
	%A = select bool %C, int 1024, int 32
	%B = udiv int %Y, %A
	ret int %B
}

-Chris
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20061025/9803b95d/attachment.html>


More information about the llvm-commits mailing list