[llvm] fc3b34c - [InstSimplify] remove shift that is redundant with part of funnel shift

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 23 06:10:06 PST 2022


Author: Sanjay Patel
Date: 2022-02-23T09:10:01-05:00
New Revision: fc3b34c50803274b8ba3b8a30df9177b7d29063c

URL: https://github.com/llvm/llvm-project/commit/fc3b34c50803274b8ba3b8a30df9177b7d29063c
DIFF: https://github.com/llvm/llvm-project/commit/fc3b34c50803274b8ba3b8a30df9177b7d29063c.diff

LOG: [InstSimplify] remove shift that is redundant with part of funnel shift

In D111530, I suggested that we add some relatively basic pattern-matching
folds for shifts and funnel shifts and avoid a more specialized solution
if possible.

We can start by implementing at least one of these in IR because it's
easier to write the code and verify with Alive2:
https://alive2.llvm.org/ce/z/qHpmNn

This will need to be adapted/extended for SDAG to handle the motivating
bug ( #49541 ) because the patterns only appear later with that example
(added some tests: bb850d422b64)

This can be extended within InstSimplify to handle cases where we 'and'
with a shift too (in that case, kill the funnel shift).
We could also handle patterns where the shift and funnel shift directions
are inverted, but I think it's better to canonicalize that instead to
avoid pattern-match case explosion.

Differential Revision: https://reviews.llvm.org/D120253

Added: 
    

Modified: 
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstSimplify/or.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index b3459b5ffb013..641098eaa9ef9 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2329,6 +2329,31 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
     }
   }
 
+  // A funnel shift (rotate) can be decomposed into simpler shifts. See if we
+  // are mixing in another shift that is redundant with the funnel shift.
+
+  // (fshl X, ?, Y) | (shl X, Y) --> fshl X, ?, Y
+  // (shl X, Y) | (fshl X, ?, Y) --> fshl X, ?, Y
+  if (match(Op0,
+            m_Intrinsic<Intrinsic::fshl>(m_Value(X), m_Value(), m_Value(Y))) &&
+      match(Op1, m_Shl(m_Specific(X), m_Specific(Y))))
+    return Op0;
+  if (match(Op1,
+            m_Intrinsic<Intrinsic::fshl>(m_Value(X), m_Value(), m_Value(Y))) &&
+      match(Op0, m_Shl(m_Specific(X), m_Specific(Y))))
+    return Op1;
+
+  // (fshr ?, X, Y) | (lshr X, Y) --> fshr ?, X, Y
+  // (lshr X, Y) | (fshr ?, X, Y) --> fshr ?, X, Y
+  if (match(Op0,
+            m_Intrinsic<Intrinsic::fshr>(m_Value(), m_Value(X), m_Value(Y))) &&
+      match(Op1, m_LShr(m_Specific(X), m_Specific(Y))))
+    return Op0;
+  if (match(Op1,
+            m_Intrinsic<Intrinsic::fshr>(m_Value(), m_Value(X), m_Value(Y))) &&
+      match(Op0, m_LShr(m_Specific(X), m_Specific(Y))))
+    return Op1;
+
   if (Value *V = simplifyAndOrOfCmps(Q, Op0, Op1, false))
     return V;
 

diff  --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll
index 07910443ad759..a279cab582d93 100644
--- a/llvm/test/Transforms/InstSimplify/or.ll
+++ b/llvm/test/Transforms/InstSimplify/or.ll
@@ -1045,10 +1045,8 @@ declare i32 @llvm.fshr.i32 (i32, i32, i32)
 
 define i32 @or_shl_fshl(i32 %x, i32 %y, i32 %s) {
 ; CHECK-LABEL: @or_shl_fshl(
-; CHECK-NEXT:    [[SHY:%.*]] = shl i32 [[Y:%.*]], [[S:%.*]]
-; CHECK-NEXT:    [[FUN:%.*]] = call i32 @llvm.fshl.i32(i32 [[Y]], i32 [[X:%.*]], i32 [[S]])
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[FUN]], [[SHY]]
-; CHECK-NEXT:    ret i32 [[OR]]
+; CHECK-NEXT:    [[FUN:%.*]] = call i32 @llvm.fshl.i32(i32 [[Y:%.*]], i32 [[X:%.*]], i32 [[S:%.*]])
+; CHECK-NEXT:    ret i32 [[FUN]]
 ;
   %shy = shl i32 %y, %s
   %fun = call i32 @llvm.fshl.i32(i32 %y, i32 %x, i32 %s)
@@ -1058,10 +1056,8 @@ define i32 @or_shl_fshl(i32 %x, i32 %y, i32 %s) {
 
 define i32 @or_shl_fshl_commute(i32 %x, i32 %y, i32 %s) {
 ; CHECK-LABEL: @or_shl_fshl_commute(
-; CHECK-NEXT:    [[SHY:%.*]] = shl i32 [[Y:%.*]], [[S:%.*]]
-; CHECK-NEXT:    [[FUN:%.*]] = call i32 @llvm.fshl.i32(i32 [[Y]], i32 [[X:%.*]], i32 [[S]])
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[SHY]], [[FUN]]
-; CHECK-NEXT:    ret i32 [[OR]]
+; CHECK-NEXT:    [[FUN:%.*]] = call i32 @llvm.fshl.i32(i32 [[Y:%.*]], i32 [[X:%.*]], i32 [[S:%.*]])
+; CHECK-NEXT:    ret i32 [[FUN]]
 ;
   %shy = shl i32 %y, %s
   %fun = call i32 @llvm.fshl.i32(i32 %y, i32 %x, i32 %s)
@@ -1069,6 +1065,8 @@ define i32 @or_shl_fshl_commute(i32 %x, i32 %y, i32 %s) {
   ret i32 %or
 }
 
+; negative test - fshl operands are not commutative
+
 define i32 @or_shl_fshl_wrong_order(i32 %x, i32 %y, i32 %s) {
 ; CHECK-LABEL: @or_shl_fshl_wrong_order(
 ; CHECK-NEXT:    [[SHY:%.*]] = shl i32 [[Y:%.*]], [[S:%.*]]
@@ -1084,10 +1082,8 @@ define i32 @or_shl_fshl_wrong_order(i32 %x, i32 %y, i32 %s) {
 
 define i32 @or_lshr_fshr(i32 %x, i32 %y, i32 %s) {
 ; CHECK-LABEL: @or_lshr_fshr(
-; CHECK-NEXT:    [[SHY:%.*]] = lshr i32 [[Y:%.*]], [[S:%.*]]
-; CHECK-NEXT:    [[FUN:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[Y]], i32 [[S]])
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[FUN]], [[SHY]]
-; CHECK-NEXT:    ret i32 [[OR]]
+; CHECK-NEXT:    [[FUN:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[S:%.*]])
+; CHECK-NEXT:    ret i32 [[FUN]]
 ;
   %shy = lshr i32 %y, %s
   %fun = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %s)
@@ -1097,10 +1093,8 @@ define i32 @or_lshr_fshr(i32 %x, i32 %y, i32 %s) {
 
 define i32 @or_lshr_fshr_commute(i32 %x, i32 %y, i32 %s) {
 ; CHECK-LABEL: @or_lshr_fshr_commute(
-; CHECK-NEXT:    [[SHY:%.*]] = lshr i32 [[Y:%.*]], [[S:%.*]]
-; CHECK-NEXT:    [[FUN:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[Y]], i32 [[S]])
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[SHY]], [[FUN]]
-; CHECK-NEXT:    ret i32 [[OR]]
+; CHECK-NEXT:    [[FUN:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[S:%.*]])
+; CHECK-NEXT:    ret i32 [[FUN]]
 ;
   %shy = lshr i32 %y, %s
   %fun = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %s)
@@ -1108,6 +1102,8 @@ define i32 @or_lshr_fshr_commute(i32 %x, i32 %y, i32 %s) {
   ret i32 %or
 }
 
+; negative test - fshr operands are not commutative
+
 define i32 @or_lshr_fshr_wrong_order(i32 %x, i32 %y, i32 %s) {
 ; CHECK-LABEL: @or_lshr_fshr_wrong_order(
 ; CHECK-NEXT:    [[SHY:%.*]] = lshr i32 [[Y:%.*]], [[S:%.*]]


        


More information about the llvm-commits mailing list