[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp

Chris Lattner lattner at cs.uiuc.edu
Thu Jan 13 14:52:40 PST 2005



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.300 -> 1.301
---
Log message:

Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))).  This occurs in
the 'sim' program and probably elsewhere.  In sim, it comes up for cases
like this:

#define round(x) ((x)>0.0 ? (x)+0.5 : (x)-0.5)
double G;
void T(double X) { G = round(X); }

(it uses the round macro a lot).  This changes the LLVM code from:

        %tmp.1 = setgt double %X, 0.000000e+00          ; <bool> [#uses=1]
        %tmp.4 = add double %X, 5.000000e-01            ; <double> [#uses=1]
        %tmp.6 = sub double %X, 5.000000e-01            ; <double> [#uses=1]
        %mem_tmp.0 = select bool %tmp.1, double %tmp.4, double %tmp.6
        store double %mem_tmp.0, double* %G

to:

        %tmp.1 = setgt double %X, 0.000000e+00          ; <bool> [#uses=1]
        %mem_tmp.0.p = select bool %tmp.1, double 5.000000e-01, double -5.000000e-01
        %mem_tmp.0 = add double %mem_tmp.0.p, %X
        store double %mem_tmp.0, double* %G
        ret void




---
Diffs of the changes:  (+53 -0)

Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.300 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.301
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.300	Thu Jan 13 16:25:21 2005
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Thu Jan 13 16:52:24 2005
@@ -3588,6 +3588,59 @@
     }
   }
   
+  // Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))).  This is legal for
+  // FP as well.
+  if (Instruction *TI = dyn_cast<Instruction>(TrueVal))
+    if (Instruction *FI = dyn_cast<Instruction>(FalseVal))
+      if (TI->hasOneUse() && FI->hasOneUse()) {
+        bool isInverse = false;
+        Instruction *AddOp = 0, *SubOp = 0;
+
+        if (TI->getOpcode() == Instruction::Sub &&
+            FI->getOpcode() == Instruction::Add) {
+          AddOp = FI; SubOp = TI;
+        } else if (FI->getOpcode() == Instruction::Sub &&
+                   TI->getOpcode() == Instruction::Add) {
+          AddOp = TI; SubOp = FI;
+        }
+
+        if (AddOp) {
+          Value *OtherAddOp = 0;
+          if (SubOp->getOperand(0) == AddOp->getOperand(0)) {
+            OtherAddOp = AddOp->getOperand(1);
+          } else if (SubOp->getOperand(0) == AddOp->getOperand(1)) {
+            OtherAddOp = AddOp->getOperand(0);
+          }
+
+          if (OtherAddOp) {
+            // So at this point we know we have:
+            //        select C, (add X, Y), (sub X, ?)
+            // We can do the transform profitably if either 'Y' = '?' or '?' is
+            // a constant.
+            if (SubOp->getOperand(1) == AddOp ||
+                isa<Constant>(SubOp->getOperand(1))) {
+              Value *NegVal;
+              if (Constant *C = dyn_cast<Constant>(SubOp->getOperand(1))) {
+                NegVal = ConstantExpr::getNeg(C);
+              } else {
+                NegVal = InsertNewInstBefore(
+                           BinaryOperator::createNeg(SubOp->getOperand(1)), SI);
+              }
+
+              Value *NewTrueOp = AddOp->getOperand(1);
+              Value *NewFalseOp = NegVal;
+              if (AddOp != TI)
+                std::swap(NewTrueOp, NewFalseOp);
+              Instruction *NewSel =
+                new SelectInst(CondVal, NewTrueOp,NewFalseOp,SI.getName()+".p");
+                               
+              NewSel = InsertNewInstBefore(NewSel, SI);
+              return BinaryOperator::createAdd(AddOp->getOperand(0), NewSel);
+            }
+          }
+        }
+      }
+  
   // See if we can fold the select into one of our operands.
   if (SI.getType()->isInteger()) {
     // See the comment above GetSelectFoldableOperands for a description of the






More information about the llvm-commits mailing list