]> granicus.if.org Git - llvm/commitdiff
[InstCombine] enable (X >>?,exact C1) << C2 --> X << (C2 - C1) for vectors with splats
authorSanjay Patel <spatel@rotateright.com>
Sun, 29 Jan 2017 17:11:18 +0000 (17:11 +0000)
committerSanjay Patel <spatel@rotateright.com>
Sun, 29 Jan 2017 17:11:18 +0000 (17:11 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293435 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineShifts.cpp
test/Transforms/InstCombine/shift.ll

index 6507bb945199d9e52d06d9b3b1ba17fc26f099c4..f6bede8fbb2bdeafbf51e3b34909bdfc5c5eacb2 100644 (file)
@@ -373,21 +373,6 @@ foldShiftByConstOfShiftByConst(BinaryOperator &I, const APInt *COp1,
   if (ShiftAmt1 < ShiftAmt2) {
     uint32_t ShiftDiff = ShiftAmt2 - ShiftAmt1;
 
-    // (X >>?,exact C1) << C2 --> X << (C2-C1)
-    // The inexact version is deferred to DAGCombine so we don't hide shl
-    // behind a bit mask.
-    if (I.getOpcode() == Instruction::Shl &&
-        ShiftOp->getOpcode() != Instruction::Shl && ShiftOp->isExact()) {
-      assert(ShiftOp->getOpcode() == Instruction::LShr ||
-             ShiftOp->getOpcode() == Instruction::AShr);
-      ConstantInt *ShiftDiffCst = ConstantInt::get(Ty, ShiftDiff);
-      BinaryOperator *NewShl =
-          BinaryOperator::Create(Instruction::Shl, X, ShiftDiffCst);
-      NewShl->setHasNoUnsignedWrap(I.hasNoUnsignedWrap());
-      NewShl->setHasNoSignedWrap(I.hasNoSignedWrap());
-      return NewShl;
-    }
-
     // (X << C1) >>u C2  --> X >>u (C2-C1) & (-1 >> C2)
     if (I.getOpcode() == Instruction::LShr &&
         ShiftOp->getOpcode() == Instruction::Shl) {
@@ -702,6 +687,7 @@ Instruction *InstCombiner::visitShl(BinaryOperator &I) {
   if (match(Op1, m_APInt(ShAmtAPInt))) {
     unsigned ShAmt = ShAmtAPInt->getZExtValue();
     unsigned BitWidth = I.getType()->getScalarSizeInBits();
+    Type *Ty = I.getType();
 
     // shl (zext X), ShAmt --> zext (shl X, ShAmt)
     // This is only valid if X would have zeros shifted out.
@@ -710,13 +696,27 @@ Instruction *InstCombiner::visitShl(BinaryOperator &I) {
       unsigned SrcWidth = X->getType()->getScalarSizeInBits();
       if (ShAmt < SrcWidth &&
           MaskedValueIsZero(X, APInt::getHighBitsSet(SrcWidth, ShAmt), 0, &I))
-        return new ZExtInst(Builder->CreateShl(X, ShAmt), I.getType());
+        return new ZExtInst(Builder->CreateShl(X, ShAmt), Ty);
     }
 
     // (X >>u C) << C --> X & (-1 << C)
     if (match(Op0, m_LShr(m_Value(X), m_Specific(Op1)))) {
       APInt Mask(APInt::getHighBitsSet(BitWidth, BitWidth - ShAmt));
-      return BinaryOperator::CreateAnd(X, ConstantInt::get(I.getType(), Mask));
+      return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, Mask));
+    }
+
+    const APInt *ShrAmt;
+    if (match(Op0, m_CombineOr(m_Exact(m_LShr(m_Value(X), m_APInt(ShrAmt))),
+                               m_Exact(m_AShr(m_Value(X), m_APInt(ShrAmt))))) &&
+        ShrAmt->ult(*ShAmtAPInt)) {
+      // If C1 < C2: (X >>?,exact C1) << C2 --> X << (C2 - C1)
+      // The inexact version is deferred to DAGCombine, so we don't hide shl
+      // behind a bit mask.
+      Constant *ShiftDiffCst = ConstantInt::get(Ty, *ShAmtAPInt - *ShrAmt);
+      auto *NewShl = BinaryOperator::Create(Instruction::Shl, X, ShiftDiffCst);
+      NewShl->setHasNoUnsignedWrap(I.hasNoUnsignedWrap());
+      NewShl->setHasNoSignedWrap(I.hasNoSignedWrap());
+      return NewShl;
     }
 
     // If the shifted-out value is known-zero, then this is a NUW shift.
index 1fd7d2e240690250be8cb5c04e3979e85719194d..ac5b27648ee5a633fc6340f97eb65d973156080e 100644 (file)
@@ -1,6 +1,4 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; This test makes sure that these instructions are properly eliminated.
-;
 ; RUN: opt < %s -instcombine -S | FileCheck %s
 
 define i32 @test1(i32 %A) {
@@ -840,8 +838,7 @@ define i32 @test48_nuw_nsw(i32 %x) {
 
 define <2 x i32> @test48_splat_vec(<2 x i32> %x) {
 ; CHECK-LABEL: @test48_splat_vec(
-; CHECK-NEXT:    [[A:%.*]] = lshr exact <2 x i32> %x, <i32 1, i32 1>
-; CHECK-NEXT:    [[B:%.*]] = shl nuw nsw <2 x i32> [[A]], <i32 3, i32 3>
+; CHECK-NEXT:    [[B:%.*]] = shl nuw nsw <2 x i32> %x, <i32 2, i32 2>
 ; CHECK-NEXT:    ret <2 x i32> [[B]]
 ;
   %A = lshr exact <2 x i32> %x, <i32 1, i32 1>
@@ -877,8 +874,7 @@ define i32 @test49_nuw_nsw(i32 %x) {
 
 define <2 x i32> @test49_splat_vec(<2 x i32> %x) {
 ; CHECK-LABEL: @test49_splat_vec(
-; CHECK-NEXT:    [[A:%.*]] = ashr exact <2 x i32> %x, <i32 1, i32 1>
-; CHECK-NEXT:    [[B:%.*]] = shl nuw nsw <2 x i32> [[A]], <i32 3, i32 3>
+; CHECK-NEXT:    [[B:%.*]] = shl nuw nsw <2 x i32> %x, <i32 2, i32 2>
 ; CHECK-NEXT:    ret <2 x i32> [[B]]
 ;
   %A = ashr exact <2 x i32> %x, <i32 1, i32 1>