[llvm] r293570 - [InstCombine] enable (X <<nsw C1) >>s C2 --> X <<nsw (C1 - C2) for vectors with splat constants

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 30 15:35:53 PST 2017


Author: spatel
Date: Mon Jan 30 17:35:52 2017
New Revision: 293570

URL: http://llvm.org/viewvc/llvm-project?rev=293570&view=rev
Log:
[InstCombine] enable (X <<nsw C1) >>s C2 --> X <<nsw (C1 - C2) for vectors with splat constants

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp
    llvm/trunk/test/Transforms/InstCombine/shift.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp?rev=293570&r1=293569&r2=293570&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp Mon Jan 30 17:35:52 2017
@@ -341,53 +341,6 @@ foldShiftByConstOfShiftByConst(BinaryOpe
                                   ConstantInt::get(I.getType(), AmtSum));
   }
 
-  // This is a constant shift of a constant shift. Be careful about hiding
-  // shl instructions behind bit masks. They are used to represent multiplies
-  // by a constant, and it is important that simple arithmetic expressions
-  // are still recognizable by scalar evolution.
-  //
-  // The transforms applied to shl are very similar to the transforms applied
-  // to mul by constant. We can be more aggressive about optimizing right
-  // shifts.
-  //
-  // Combinations of right and left shifts will still be optimized in
-  // DAGCombine where scalar evolution no longer applies.
-
-  Value *X = ShiftOp->getOperand(0);
-  unsigned ShiftAmt1 = ShAmt1->getLimitedValue();
-  unsigned ShiftAmt2 = COp1->getLimitedValue();
-  assert(ShiftAmt2 != 0 && "Should have been simplified earlier");
-  if (ShiftAmt1 == 0)
-    return nullptr; // Will be simplified in the future.
-
-  if (ShiftAmt1 == ShiftAmt2)
-    return nullptr;
-
-  // FIXME: Everything under here should be extended to work with vector types.
-
-  auto *ShiftAmt1C = dyn_cast<ConstantInt>(ShiftOp->getOperand(1));
-  if (!ShiftAmt1C)
-    return nullptr;
-
-  IntegerType *Ty = cast<IntegerType>(I.getType());
-  if (ShiftAmt2 < ShiftAmt1) {
-    uint32_t ShiftDiff = ShiftAmt1 - ShiftAmt2;
-
-    // We can't handle (X << C1) >>s C2, it shifts arbitrary bits in. However,
-    // we can handle (X <<nsw C1) >>s C2 since it only shifts in sign bits.
-    if (I.getOpcode() == Instruction::AShr &&
-        ShiftOp->getOpcode() == Instruction::Shl) {
-      if (ShiftOp->hasNoSignedWrap()) {
-        // (X <<nsw C1) >>s C2 --> X <<nsw (C1-C2)
-        ConstantInt *ShiftDiffCst = ConstantInt::get(Ty, ShiftDiff);
-        BinaryOperator *NewShl =
-            BinaryOperator::Create(Instruction::Shl, X, ShiftDiffCst);
-        NewShl->setHasNoSignedWrap(true);
-        return NewShl;
-      }
-    }
-  }
-
   return nullptr;
 }
 
@@ -640,6 +593,9 @@ Instruction *InstCombiner::visitShl(Bina
       return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, Mask));
     }
 
+    // Be careful about hiding shl instructions behind bit masks. They are used
+    // to represent multiplies by a constant, and it is important that simple
+    // arithmetic expressions are still recognizable by scalar evolution.
     // The inexact versions are deferred to DAGCombine, so we don't hide shl
     // behind a bit mask.
     const APInt *ShrOp1;
@@ -792,13 +748,22 @@ Instruction *InstCombiner::visitAShr(Bin
     // We can't handle (X << C1) >>s C2. It shifts arbitrary bits in. However,
     // we can handle (X <<nsw C1) >>s C2 since it only shifts in sign bits.
     const APInt *ShlAmtAPInt;
-    if (match(Op0, m_NSWShl(m_Value(X), m_APInt(ShlAmtAPInt))) &&
-        ShlAmtAPInt->ult(*ShAmtAPInt)) {
-      // (X <<nsw C1) >>s C2 --> X >>s (C2 - C1)
-      Constant *ShiftDiff = ConstantInt::get(Ty, *ShAmtAPInt - *ShlAmtAPInt);
-      auto *NewAShr = BinaryOperator::CreateAShr(X, ShiftDiff);
-      NewAShr->setIsExact(I.isExact());
-      return NewAShr;
+    if (match(Op0, m_NSWShl(m_Value(X), m_APInt(ShlAmtAPInt)))) {
+      unsigned ShlAmt = ShlAmtAPInt->getZExtValue();
+      if (ShlAmt < ShAmt) {
+        // (X <<nsw C1) >>s C2 --> X >>s (C2 - C1)
+        Constant *ShiftDiff = ConstantInt::get(Ty, ShAmt - ShlAmt);
+        auto *NewAShr = BinaryOperator::CreateAShr(X, ShiftDiff);
+        NewAShr->setIsExact(I.isExact());
+        return NewAShr;
+      }
+      if (ShlAmt > ShAmt) {
+        // (X <<nsw C1) >>s C2 --> X <<nsw (C1 - C2)
+        Constant *ShiftDiff = ConstantInt::get(Ty, ShlAmt - ShAmt);
+        auto *NewShl = BinaryOperator::Create(Instruction::Shl, X, ShiftDiff);
+        NewShl->setHasNoSignedWrap(true);
+        return NewShl;
+      }
     }
 
     // If the shifted-out value is known-zero, then this is an exact shift.

Modified: llvm/trunk/test/Transforms/InstCombine/shift.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/shift.ll?rev=293570&r1=293569&r2=293570&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/shift.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/shift.ll Mon Jan 30 17:35:52 2017
@@ -1003,8 +1003,7 @@ define i32 @test52(i32 %x) {
 
 define <2 x i32> @test52_splat_vec(<2 x i32> %x) {
 ; CHECK-LABEL: @test52_splat_vec(
-; CHECK-NEXT:    [[A:%.*]] = shl nsw <2 x i32> %x, <i32 3, i32 3>
-; CHECK-NEXT:    [[B:%.*]] = ashr exact <2 x i32> [[A]], <i32 1, i32 1>
+; CHECK-NEXT:    [[B:%.*]] = shl nsw <2 x i32> %x, <i32 2, i32 2>
 ; CHECK-NEXT:    ret <2 x i32> [[B]]
 ;
   %A = shl nsw <2 x i32> %x, <i32 3, i32 3>




More information about the llvm-commits mailing list