[PATCH] D33221: [InstSimplify] add folds for constant mask of value shifted by constant

Sanjay Patel via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon May 15 16:25:48 PDT 2017


spatel created this revision.
Herald added a subscriber: mcrosier.

I was investigating why a different simplification wasn't happening and noticed that we don't have this fold for the easy case with constants.

We would eventually catch these via demanded bits and computing known bits in InstCombine, but I think it's better to handle the simple cases as soon as possible as a matter of efficiency?

If there's a better way to do the APInt manipulations, please let me know.


https://reviews.llvm.org/D33221

Files:
  lib/Analysis/InstructionSimplify.cpp
  test/Transforms/InstSimplify/AndOrXor.ll


Index: test/Transforms/InstSimplify/AndOrXor.ll
===================================================================
--- test/Transforms/InstSimplify/AndOrXor.ll
+++ test/Transforms/InstSimplify/AndOrXor.ll
@@ -738,8 +738,7 @@
 define i8 @lshr_perfect_mask(i8 %x) {
 ; CHECK-LABEL: @lshr_perfect_mask(
 ; CHECK-NEXT:    [[SH:%.*]] = lshr i8 %x, 5
-; CHECK-NEXT:    [[MASK:%.*]] = and i8 [[SH]], 7
-; CHECK-NEXT:    ret i8 [[MASK]]
+; CHECK-NEXT:    ret i8 [[SH]]
 ;
   %sh = lshr i8 %x, 5
   %mask = and i8 %sh, 7  ; 0x07
@@ -749,8 +748,7 @@
 define <2 x i8> @lshr_oversized_mask_splat(<2 x i8> %x) {
 ; CHECK-LABEL: @lshr_oversized_mask_splat(
 ; CHECK-NEXT:    [[SH:%.*]] = lshr <2 x i8> %x, <i8 5, i8 5>
-; CHECK-NEXT:    [[MASK:%.*]] = and <2 x i8> [[SH]], <i8 -121, i8 -121>
-; CHECK-NEXT:    ret <2 x i8> [[MASK]]
+; CHECK-NEXT:    ret <2 x i8> [[SH]]
 ;
   %sh = lshr <2 x i8> %x, <i8 5, i8 5>
   %mask = and <2 x i8> %sh, <i8 135, i8 135>  ; 0x87
@@ -771,8 +769,7 @@
 define <2 x i8> @shl_perfect_mask_splat(<2 x i8> %x) {
 ; CHECK-LABEL: @shl_perfect_mask_splat(
 ; CHECK-NEXT:    [[SH:%.*]] = shl <2 x i8> %x, <i8 6, i8 6>
-; CHECK-NEXT:    [[MASK:%.*]] = and <2 x i8> [[SH]], <i8 -64, i8 -64>
-; CHECK-NEXT:    ret <2 x i8> [[MASK]]
+; CHECK-NEXT:    ret <2 x i8> [[SH]]
 ;
   %sh = shl <2 x i8> %x, <i8 6, i8 6>
   %mask = and <2 x i8> %sh, <i8 192, i8 192>  ; 0xC0
@@ -782,8 +779,7 @@
 define i8 @shl_oversized_mask(i8 %x) {
 ; CHECK-LABEL: @shl_oversized_mask(
 ; CHECK-NEXT:    [[SH:%.*]] = shl i8 %x, 6
-; CHECK-NEXT:    [[MASK:%.*]] = and i8 [[SH]], -61
-; CHECK-NEXT:    ret i8 [[MASK]]
+; CHECK-NEXT:    ret i8 [[SH]]
 ;
   %sh = shl i8 %x, 6
   %mask = and i8 %sh, 195  ; 0xC3
Index: lib/Analysis/InstructionSimplify.cpp
===================================================================
--- lib/Analysis/InstructionSimplify.cpp
+++ lib/Analysis/InstructionSimplify.cpp
@@ -1752,6 +1752,25 @@
       (A == Op0 || B == Op0))
     return Op0;
 
+  // A mask that only clears known zeros of a shifted value is a no-op.
+  Value *X;
+  const APInt *Mask;
+  const APInt *ShAmt;
+  if (match(Op1, m_APInt(Mask))) {
+    // If all bits in the shifted mask are set:
+    // and (shl X, ShAmt), Mask --> shl X, ShAmt
+    if (match(Op0, m_Shl(m_Value(X), m_APInt(ShAmt))) &&
+        Mask->ashr(*ShAmt).isAllOnesValue())
+      return Op0;
+
+    // If all bits in the shifted mask are set:
+    // and (lshr X, ShAmt), Mask --> lshr X, ShAmt
+    // We can't shift ones in from the bottom, so signed-shift the mask back.
+    if (match(Op0, m_LShr(m_Value(X), m_APInt(ShAmt))) &&
+        Mask->shl(*ShAmt).ashr(*ShAmt).isAllOnesValue())
+      return Op0;
+  }
+
   // A & (-A) = A if A is a power of two or zero.
   if (match(Op0, m_Neg(m_Specific(Op1))) ||
       match(Op1, m_Neg(m_Specific(Op0)))) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D33221.99080.patch
Type: text/x-patch
Size: 2818 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170515/875352f3/attachment.bin>


More information about the llvm-commits mailing list