implement shift.ll:test25. This compiles:
authorChris Lattner <sabre@nondot.org>
Sun, 18 Sep 2005 05:12:10 +0000 (05:12 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 18 Sep 2005 05:12:10 +0000 (05:12 +0000)
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus3 (unsigned int x) {
  b.k += x;
}

to:

_plus3:
        lis r2, ha16(L_b$non_lazy_ptr)
        lwz r2, lo16(L_b$non_lazy_ptr)(r2)
        lwz r3, 0(r2)
        rlwinm r4, r3, 0, 0, 14
        add r4, r4, r3
        rlwimi r4, r3, 0, 15, 31
        stw r4, 0(r2)
        blr

instead of:

_plus3:
        lis r2, ha16(L_b$non_lazy_ptr)
        lwz r2, lo16(L_b$non_lazy_ptr)(r2)
        lwz r4, 0(r2)
        srwi r5, r4, 17
        add r3, r5, r3
        slwi r3, r3, 17
        rlwimi r3, r4, 0, 15, 31
        stw r3, 0(r2)
        blr

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23381 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/InstructionCombining.cpp

index 2a03bc1461d80afa25671431c65a27e2c1a376cd..2d7adf4ea8d6fe2f933e98699929bc863626021c 100644 (file)
@@ -3355,9 +3355,58 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
         }
       }
 
-      // If the operand is an bitwise operator with a constant RHS, and the
-      // shift is the only use, we can pull it out of the shift.
-      if (BinaryOperator *Op0BO = dyn_cast<BinaryOperator>(Op0))
+      if (BinaryOperator *Op0BO = dyn_cast<BinaryOperator>(Op0)) {
+        // Turn ((X >> C) + Y) << C  ->  (X + (Y << C)) & (~0 << C)
+        switch (Op0BO->getOpcode()) {
+        default: break;
+        case Instruction::Add:
+        case Instruction::And:
+        case Instruction::Or:
+        case Instruction::Xor:
+          // These operators commute.
+          // Turn (Y + (X >> C)) << C  ->  (X + (Y << C)) & (~0 << C)
+          if (ShiftInst *XS = dyn_cast<ShiftInst>(Op0BO->getOperand(1)))
+            if (isLeftShift && XS->hasOneUse() && XS->getOperand(1) == CUI &&
+                XS->getOpcode() == Instruction::Shr) {
+              break;
+              Instruction *YS = new ShiftInst(Instruction::Shl, 
+                                              Op0BO->getOperand(0), CUI,
+                                              Op0BO->getName());
+              InsertNewInstBefore(YS, I); // (Y << C)
+              Instruction *X = BinaryOperator::create(Op0BO->getOpcode(), YS,
+                                                      XS->getOperand(0),
+                                                      XS->getName());
+              InsertNewInstBefore(X, I);  // (X + (Y << C))
+              Constant *C2 = ConstantInt::getAllOnesValue(X->getType());
+              C2 = ConstantExpr::getShl(C2, CUI);
+              std::cerr << "FOLD1: " << *Op0BO;
+              return BinaryOperator::createAnd(X, C2);
+            }
+          // Fall through.
+        case Instruction::Sub:
+          // Turn ((X >> C) + Y) << C  ->  (X + (Y << C)) & (~0 << C)
+          if (ShiftInst *XS = dyn_cast<ShiftInst>(Op0BO->getOperand(0)))
+            if (isLeftShift && XS->hasOneUse() && XS->getOperand(1) == CUI &&
+                XS->getOpcode() == Instruction::Shr) {
+              Instruction *YS = new ShiftInst(Instruction::Shl, 
+                                              Op0BO->getOperand(0), CUI,
+                                              Op0BO->getName());
+              InsertNewInstBefore(YS, I); // (Y << C)
+              Instruction *X = BinaryOperator::create(Op0BO->getOpcode(), YS,
+                                                      XS->getOperand(0),
+                                                      XS->getName());
+              InsertNewInstBefore(X, I);  // (X + (Y << C))
+              Constant *C2 = ConstantInt::getAllOnesValue(X->getType());
+              C2 = ConstantExpr::getShl(C2, CUI);
+              std::cerr << "FOLD2: " << *Op0BO;
+              return BinaryOperator::createAnd(X, C2);
+            }
+          break;
+        }
+
+
+        // If the operand is an bitwise operator with a constant RHS, and the
+        // shift is the only use, we can pull it out of the shift.
         if (ConstantInt *Op0C = dyn_cast<ConstantInt>(Op0BO->getOperand(1))) {
           bool isValid = true;     // Valid only for And, Or, Xor
           bool highBitSet = false; // Transform if high bit of constant set?
@@ -3400,6 +3449,7 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
                                           NewRHS);
           }
         }
+      }
     }
 
     // If this is a shift of a shift, see if we can fold the two together...