]> granicus.if.org Git - llvm/commitdiff
[InstCombine] narrow lshr with constant
authorSanjay Patel <spatel@rotateright.com>
Fri, 4 Aug 2017 15:42:47 +0000 (15:42 +0000)
committerSanjay Patel <spatel@rotateright.com>
Fri, 4 Aug 2017 15:42:47 +0000 (15:42 +0000)
Name: narrow_shift
Pre: C1 < 8
%zx = zext i8 %x to i32
%l = lshr i32 %zx, C1
  =>
%narrowC = trunc i32 C1 to i8
%ns = lshr i8 %x, %narrowC
%l = zext i8 %ns to i32

http://rise4fun.com/Alive/jIV

This isn't directly applicable to PR34046 as written, but we
need to have more narrowing folds like this to be sure that
rotate patterns are recognized.

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

lib/Transforms/InstCombine/InstCombineShifts.cpp
test/Transforms/InstCombine/cast.ll
test/Transforms/InstCombine/lshr.ll
test/Transforms/InstCombine/select-with-bitwise-ops.ll
test/Transforms/InstCombine/trunc.ll

index 7ed141c7fd79d51af13f124dc1fddc1e9bbb3cd9..f4e2458fba2dbde945d9ff67c0b7ea8051a88c4b 100644 (file)
@@ -680,6 +680,15 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
       return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, Mask));
     }
 
+    if (match(Op0, m_OneUse(m_ZExt(m_Value(X)))) &&
+        (!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType()))) {
+      unsigned SrcTyBitWidth = X->getType()->getScalarSizeInBits();
+      assert(ShAmt < SrcTyBitWidth && "Big shift not simplified to zero?");
+      // lshr (zext iM X to iN), C --> zext (lshr X, C) to iN
+      Value *NewLShr = Builder.CreateLShr(X, ShAmt);
+      return new ZExtInst(NewLShr, Ty);
+    }
+
     if (match(Op0, m_SExt(m_Value(X))) &&
         (!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType()))) {
       // Are we moving the sign bit to the low bit and widening with high zeros?
index dedbd783d3f1a1e4b29475b3beeec578139d7244..1d3e223329858d4a04323e7b9a12798421eefcaf 100644 (file)
@@ -761,9 +761,9 @@ define i64 @test59(i8 %A, i8 %B) nounwind {
 ; CHECK-NEXT:    [[C:%.*]] = zext i8 %A to i64
 ; CHECK-NEXT:    [[D:%.*]] = shl nuw nsw i64 [[C]], 4
 ; CHECK-NEXT:    [[E:%.*]] = and i64 [[D]], 48
-; CHECK-NEXT:    [[F:%.*]] = zext i8 %B to i64
-; CHECK-NEXT:    [[G:%.*]] = lshr i64 [[F]], 4
-; CHECK-NEXT:    [[H:%.*]] = or i64 [[G]], [[E]]
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i8 %B, 4
+; CHECK-NEXT:    [[G:%.*]] = zext i8 [[TMP1]] to i64
+; CHECK-NEXT:    [[H:%.*]] = or i64 [[E]], [[G]]
 ; CHECK-NEXT:    ret i64 [[H]]
 ;
   %C = zext i8 %A to i32
index 4cdcb98f730c19b8042119360f053930038c7dd9..8ab3ca8874183d57bccfa3c189cc4c0e69f840bd 100644 (file)
@@ -190,3 +190,16 @@ define <2 x i8> @fake_sext_splat(<2 x i3> %x) {
   ret <2 x i8> %sh
 }
 
+; Use a narrow shift: lshr (zext iM X to iN), C --> zext (lshr X, C) to iN
+
+define <2 x i32> @narrow_lshr_constant(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @narrow_lshr_constant(
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr <2 x i8> %x, <i8 3, i8 3>
+; CHECK-NEXT:    [[SH:%.*]] = zext <2 x i8> [[TMP1]] to <2 x i32>
+; CHECK-NEXT:    ret <2 x i32> [[SH]]
+;
+  %zx = zext <2 x i8> %x to <2 x i32>
+  %sh = lshr <2 x i32> %zx, <i32 3, i32 3>
+  ret <2 x i32> %sh
+}
+
index 437f09be2e7c9f923745685a7d7ee15494394f38..f562c6ebafb0747a5d1db3a45d352741d1798598 100644 (file)
@@ -283,10 +283,10 @@ define i32 @test66(i64 %x) {
 
 define i32 @test67(i16 %x) {
 ; CHECK-LABEL: @test67(
-; CHECK-NEXT:    [[TMP1:%.*]] = and i16 %x, 4
-; CHECK-NEXT:    [[TMP2:%.*]] = zext i16 [[TMP1]] to i32
-; CHECK-NEXT:    [[TMP3:%.*]] = lshr exact i32 [[TMP2]], 1
-; CHECK-NEXT:    [[TMP4:%.*]] = xor i32 [[TMP3]], 42
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i16 %x, 1
+; CHECK-NEXT:    [[TMP2:%.*]] = and i16 [[TMP1]], 2
+; CHECK-NEXT:    [[TMP3:%.*]] = xor i16 [[TMP2]], 42
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i16 [[TMP3]] to i32
 ; CHECK-NEXT:    ret i32 [[TMP4]]
 ;
   %1 = and i16 %x, 4
index dd86e5a907b8ef19143da00be2e71367ddac258b..3ba0b866e478822ddb9e4723ee4e4596997d189a 100644 (file)
@@ -91,9 +91,9 @@ define i32 @test6(i64 %A) {
 
 define i92 @test7(i64 %A) {
 ; CHECK-LABEL: @test7(
-; CHECK-NEXT:    [[B:%.*]] = zext i64 %A to i92
-; CHECK-NEXT:    [[C:%.*]] = lshr i92 [[B]], 32
-; CHECK-NEXT:    ret i92 [[C]]
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i64 %A, 32
+; CHECK-NEXT:    [[D:%.*]] = zext i64 [[TMP1]] to i92
+; CHECK-NEXT:    ret i92 [[D]]
 ;
   %B = zext i64 %A to i128
   %C = lshr i128 %B, 32