[llvm] r290928 - [InstCombine] Move casts around shift operations

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 3 18:21:35 PST 2017


Author: majnemer
Date: Tue Jan  3 20:21:34 2017
New Revision: 290928

URL: http://llvm.org/viewvc/llvm-project?rev=290928&view=rev
Log:
[InstCombine] Move casts around shift operations

It is possible to perform a left shift before zero extending if the
shift would only shift out zeros.

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp
    llvm/trunk/test/Transforms/InstCombine/rem.ll
    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=290928&r1=290927&r2=290928&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp Tue Jan  3 20:21:34 2017
@@ -731,6 +731,25 @@ Instruction *InstCombiner::visitShl(Bina
   if (ConstantInt *Op1C = dyn_cast<ConstantInt>(I.getOperand(1))) {
     unsigned ShAmt = Op1C->getZExtValue();
 
+    // Turn:
+    //  %zext = zext i32 %V to i64
+    //  %res = shl i64 %V, 8
+    //
+    // Into:
+    //  %shl = shl i32 %V, 8
+    //  %res = zext i32 %shl to i64
+    //
+    // This is only valid if %V would have zeros shifted out.
+    if (auto *ZI = dyn_cast<ZExtInst>(I.getOperand(0))) {
+      unsigned SrcBitWidth = ZI->getSrcTy()->getScalarSizeInBits();
+      if (ShAmt < SrcBitWidth &&
+          MaskedValueIsZero(ZI->getOperand(0),
+                            APInt::getHighBitsSet(SrcBitWidth, ShAmt), 0, &I)) {
+        auto *Shl = Builder->CreateShl(ZI->getOperand(0), ShAmt);
+        return new ZExtInst(Shl, I.getType());
+      }
+    }
+
     // If the shifted-out value is known-zero, then this is a NUW shift.
     if (!I.hasNoUnsignedWrap() &&
         MaskedValueIsZero(I.getOperand(0),

Modified: llvm/trunk/test/Transforms/InstCombine/rem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/rem.ll?rev=290928&r1=290927&r2=290928&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/rem.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/rem.ll Tue Jan  3 20:21:34 2017
@@ -204,11 +204,11 @@ define i32 @test17(i32 %X) {
 
 define i32 @test18(i16 %x, i32 %y) {
 ; CHECK: @test18
-; CHECK-NEXT: [[AND:%.*]] = and i16 %x, 4
-; CHECK-NEXT: [[EXT:%.*]] = zext i16 [[AND]] to i32
-; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[EXT]], 3
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[SHL]], 63
-; CHECK-NEXT: [[REM:%.*]] = and i32 [[XOR]], %y
+; CHECK-NEXT: [[SHL:%.*]] = shl i16 %x, 3
+; CHECK-NEXT: [[AND:%.*]] = and i16 [[SHL]], 32
+; CHECK-NEXT: [[XOR:%.*]] = xor i16 [[AND]], 63
+; CHECK-NEXT: [[EXT:%.*]] = zext i16 [[XOR]] to i32
+; CHECK-NEXT: [[REM:%.*]] = and i32 [[EXT]], %y
 ; CHECK-NEXT: ret i32 [[REM]]
 	%1 = and i16 %x, 4
 	%2 = icmp ne i16 %1, 0

Modified: llvm/trunk/test/Transforms/InstCombine/shift.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/shift.ll?rev=290928&r1=290927&r2=290928&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/shift.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/shift.ll Tue Jan  3 20:21:34 2017
@@ -1049,3 +1049,15 @@ define <2 x i65> @test_63(<2 x i64> %t)
   %b = ashr <2 x i65> %sext, <i65 33, i65 33>
   ret <2 x i65> %b
 }
+
+define i64 @test_64(i32 %t) {
+; CHECK-LABEL: @test_64(
+; CHECK-NEXT: [[SHL:%.*]] = shl i32 %t, 8
+; CHECK-NEXT: [[EXT:%.*]] = zext i32 [[SHL]] to i64
+; CHECK-NEXT: ret i64 [[EXT]]
+
+  %and = and i32 %t, 16777215
+  %ext = zext i32 %and to i64
+  %shl = shl i64 %ext, 8
+  ret i64 %shl
+}




More information about the llvm-commits mailing list