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

Chris Lattner lattner at cs.uiuc.edu
Sat Sep 17 21:24:56 PDT 2005



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.373 -> 1.374
---
Log message:

Implement add.ll:test29.  Codegening:

struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus1 (unsigned int x) {
  b.i += x;
}

as:
_plus1:
        lis r2, ha16(L_b$non_lazy_ptr)
        lwz r2, lo16(L_b$non_lazy_ptr)(r2)
        lwz r4, 0(r2)
        add r3, r4, r3
        rlwimi r3, r4, 0, 0, 25
        stw r3, 0(r2)
        blr

instead of:

_plus1:
        lis r2, ha16(L_b$non_lazy_ptr)
        lwz r2, lo16(L_b$non_lazy_ptr)(r2)
        lwz r4, 0(r2)
        rlwinm r5, r4, 0, 26, 31
        add r3, r5, r3
        rlwimi r3, r4, 0, 0, 25
        stw r3, 0(r2)
        blr



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

 InstructionCombining.cpp |   66 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 66 insertions(+)


Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.373 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.374
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.373	Sat Sep 17 22:50:25 2005
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Sat Sep 17 23:24:45 2005
@@ -222,6 +222,9 @@
 
     Instruction *OptAndOp(Instruction *Op, ConstantIntegral *OpRHS,
                           ConstantIntegral *AndRHS, BinaryOperator &TheAnd);
+    
+    Value *FoldLogicalPlusAnd(Value *LHS, Value *RHS, ConstantIntegral *Mask,
+                              bool isSub, Instruction &I);
 
     Instruction *InsertRangeTest(Value *V, Constant *Lo, Constant *Hi,
                                  bool Inside, Instruction &IB);
@@ -1570,6 +1573,46 @@
   return new SetCondInst(Instruction::SetGT, OffsetVal, AddCST);
 }
 
+/// FoldLogicalPlusAnd - We know that Mask is of the form 0+1+, and that this is
+/// part of an expression (LHS +/- RHS) & Mask, where isSub determines whether
+/// the operator is a sub.  If we can fold one of the following xforms:
+/// 
+/// ((A & N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == Mask
+/// ((A | N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == 0
+/// ((A ^ N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == 0
+///
+/// return (A +/- B).
+///
+Value *InstCombiner::FoldLogicalPlusAnd(Value *LHS, Value *RHS,
+                                        ConstantIntegral *Mask, bool isSub,
+                                        Instruction &I) {
+  Instruction *LHSI = dyn_cast<Instruction>(LHS);
+  if (!LHSI || LHSI->getNumOperands() != 2 ||
+      !isa<ConstantInt>(LHSI->getOperand(1))) return 0;
+
+  ConstantInt *N = cast<ConstantInt>(LHSI->getOperand(1));
+
+  switch (LHSI->getOpcode()) {
+  default: return 0;
+  case Instruction::And:
+    if (ConstantExpr::getAnd(N, Mask) == Mask)
+      break;
+    return 0;
+  case Instruction::Or:
+  case Instruction::Xor:
+    if (ConstantExpr::getAnd(N, Mask)->isNullValue())
+      break;
+    return 0;
+  }
+  
+  Instruction *New;
+  if (isSub)
+    New = BinaryOperator::createSub(LHSI->getOperand(0), RHS, "fold");
+  else
+    New = BinaryOperator::createAdd(LHSI->getOperand(0), RHS, "fold");
+  return InsertNewInstBefore(New, I);
+}
+
 
 Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
   bool Changed = SimplifyCommutative(I);
@@ -1640,6 +1683,29 @@
             MaskedValueIsZero(Op0RHS, AndRHS))
           return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
         break;
+      case Instruction::Add:
+        // If the AndRHS is a power of two minus one (0+1+).
+        if ((AndRHS->getRawValue() & AndRHS->getRawValue()+1) == 0) {
+          // ((A & N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == AndRHS.
+          // ((A | N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == 0
+          // ((A ^ N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == 0
+          if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, false, I))
+            return BinaryOperator::createAnd(V, AndRHS);
+          if (Value *V = FoldLogicalPlusAnd(Op0RHS, Op0LHS, AndRHS, false, I))
+            return BinaryOperator::createAnd(V, AndRHS);  // Add commutes
+        }
+        break;
+
+      case Instruction::Sub:
+        // If the AndRHS is a power of two minus one (0+1+).
+        if ((AndRHS->getRawValue() & AndRHS->getRawValue()+1) == 0) {
+          // ((A & N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == AndRHS.
+          // ((A | N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == 0
+          // ((A ^ N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == 0
+          if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, true, I))
+            return BinaryOperator::createAnd(V, AndRHS);
+        }
+        break;
       }
 
       if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1)))






More information about the llvm-commits mailing list