[llvm] [InstCombine] Fold `(shl ShVal, (X + 1) & (Width-1)) | (lshr ShVal, (X + Width-1) ^ (Width-1))` --> `fshl(ShVal, ShVal, X+1)` (PR #214035)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 4 12:01:08 PDT 2026


https://github.com/VachanVY updated https://github.com/llvm/llvm-project/pull/214035

>From 62b25fef6bcf47bad015c33f11b854e1e3fef420 Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Wed, 5 Aug 2026 00:04:34 +0530
Subject: [PATCH 1/2] [InstCombine] Pre-Commit Tests. NFC

---
 llvm/test/Transforms/InstCombine/fsh.ll | 277 ++++++++++++++++++++++++
 1 file changed, 277 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/fsh.ll b/llvm/test/Transforms/InstCombine/fsh.ll
index 79d3f94182b0b..e42f30223d76d 100644
--- a/llvm/test/Transforms/InstCombine/fsh.ll
+++ b/llvm/test/Transforms/InstCombine/fsh.ll
@@ -9,6 +9,7 @@ declare <2 x i32> @llvm.fshr.v2i32(<2 x i32>, <2 x i32>, <2 x i32>)
 declare <2 x i31> @llvm.fshl.v2i31(<2 x i31>, <2 x i31>, <2 x i31>)
 declare <3 x i16> @llvm.fshl.v3i16(<3 x i16>, <3 x i16>, <3 x i16>)
 
+declare void @use_i8(i8)
 declare void @use_v2(<2 x i31>)
 declare void @use_v3(<3 x i16>)
 
@@ -1301,3 +1302,279 @@ define i32 @rot_fsh(i32 %x, i32 %y) {
   ret i32 %r2
 }
 
+; Fold `(shl ShVal, (X + 1) & (Width-1)) | (lshr ShVal, (X + Width-1) ^ (Width-1))` --> `fshl(ShVal, ShVal, X+1)`
+
+define i8 @rot_add_xor_mask_fshl(i8 %x, i8 %y) {
+; CHECK-LABEL: @rot_add_xor_mask_fshl(
+; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i8 [[Y:%.*]], 1
+; CHECK-NEXT:    [[SHL_M:%.*]] = and i8 [[SHL_AMT]], 7
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X:%.*]], [[SHL_M]]
+; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i8 [[Y]], 7
+; CHECK-NEXT:    [[LSHR_M:%.*]] = xor i8 [[LSHR_AMT]], 7
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X]], [[LSHR_M]]
+; CHECK-NEXT:    [[R:%.*]] = or i8 [[SHL]], [[LSHR]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %shl_amt = add i8 %y, 1
+  %shl_m = and i8 %shl_amt, 7
+  %shl = shl i8 %x, %shl_m
+  %lshr_amt = add i8 %y, 7
+  %lshr_m = xor i8 %lshr_amt, 7
+  %lshr = lshr i8 %x, %lshr_m
+  %r = or i8 %shl, %lshr
+  ret i8 %r
+}
+
+define i64 @rot_add_xor_mask_fshl_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: @rot_add_xor_mask_fshl_i64(
+; CHECK-NEXT:    [[SHL_AMT:%.*]] = add nuw i64 [[Y:%.*]], 1
+; CHECK-NEXT:    [[SHL_M:%.*]] = and i64 [[SHL_AMT]], 63
+; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[X:%.*]], [[SHL_M]]
+; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i64 [[Y]], 63
+; CHECK-NEXT:    [[LSHR_M:%.*]] = xor i64 [[LSHR_AMT]], 63
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i64 [[X]], [[LSHR_M]]
+; CHECK-NEXT:    [[R:%.*]] = or i64 [[SHL]], [[LSHR]]
+; CHECK-NEXT:    ret i64 [[R]]
+;
+  %shl_amt = add nuw i64 %y, 1
+  %shl_m = and i64 %shl_amt, 63
+  %shl = shl i64 %x, %shl_m
+  %lshr_amt = add i64 %y, 63
+  %lshr_m = xor i64 %lshr_amt, 63
+  %lshr = lshr i64 %x, %lshr_m
+  %r = or i64 %shl, %lshr
+  ret i64 %r
+}
+
+define i8 @rot_add_xor_mask_fshl_commute(i8 %x, i8 %y) {
+; CHECK-LABEL: @rot_add_xor_mask_fshl_commute(
+; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i8 [[Y:%.*]], 1
+; CHECK-NEXT:    [[SHL_M:%.*]] = and i8 [[SHL_AMT]], 7
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X:%.*]], [[SHL_M]]
+; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i8 [[Y]], 7
+; CHECK-NEXT:    [[LSHR_M:%.*]] = xor i8 [[LSHR_AMT]], 7
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X]], [[LSHR_M]]
+; CHECK-NEXT:    [[R:%.*]] = or i8 [[LSHR]], [[SHL]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %shl_amt = add i8 %y, 1
+  %shl_m = and i8 %shl_amt, 7
+  %shl = shl i8 %x, %shl_m
+  %lshr_amt = add i8 %y, 7
+  %lshr_m = xor i8 %lshr_amt, 7
+  %lshr = lshr i8 %x, %lshr_m
+  %r = or i8 %lshr, %shl
+  ret i8 %r
+}
+
+define <2 x i8> @rot_add_xor_mask_fshl_vec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @rot_add_xor_mask_fshl_vec(
+; CHECK-NEXT:    [[SHL_AMT:%.*]] = add <2 x i8> [[Y:%.*]], splat (i8 1)
+; CHECK-NEXT:    [[SHL_M:%.*]] = and <2 x i8> [[SHL_AMT]], splat (i8 7)
+; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i8> [[X:%.*]], [[SHL_M]]
+; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add <2 x i8> [[Y]], splat (i8 7)
+; CHECK-NEXT:    [[LSHR_M:%.*]] = xor <2 x i8> [[LSHR_AMT]], splat (i8 7)
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr <2 x i8> [[X]], [[LSHR_M]]
+; CHECK-NEXT:    [[R:%.*]] = or <2 x i8> [[SHL]], [[LSHR]]
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %shl_amt = add <2 x i8> %y, splat (i8 1)
+  %shl_m = and <2 x i8> %shl_amt, splat (i8 7)
+  %shl = shl <2 x i8> %x, %shl_m
+  %lshr_amt = add <2 x i8> %y, splat (i8 7)
+  %lshr_m = xor <2 x i8> %lshr_amt, splat (i8 7)
+  %lshr = lshr <2 x i8> %x, %lshr_m
+  %r = or <2 x i8> %shl, %lshr
+  ret <2 x i8> %r
+}
+
+define i8 @rot_add_xor_mask_fshr(i8 %x, i8 %y) {
+; CHECK-LABEL: @rot_add_xor_mask_fshr(
+; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i8 [[Y:%.*]], 1
+; CHECK-NEXT:    [[LSHR_M:%.*]] = and i8 [[LSHR_AMT]], 7
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X:%.*]], [[LSHR_M]]
+; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i8 [[Y]], 7
+; CHECK-NEXT:    [[SHL_M:%.*]] = xor i8 [[SHL_AMT]], 7
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X]], [[SHL_M]]
+; CHECK-NEXT:    [[R:%.*]] = or i8 [[LSHR]], [[SHL]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lshr_amt = add i8 %y, 1
+  %lshr_m = and i8 %lshr_amt, 7
+  %lshr = lshr i8 %x, %lshr_m
+  %shl_amt = add i8 %y, 7
+  %shl_m = xor i8 %shl_amt, 7
+  %shl = shl i8 %x, %shl_m
+  %r = or i8 %lshr, %shl
+  ret i8 %r
+}
+
+define i64 @rot_add_xor_mask_fshr_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: @rot_add_xor_mask_fshr_i64(
+; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add nuw i64 [[Y:%.*]], 1
+; CHECK-NEXT:    [[LSHR_M:%.*]] = and i64 [[LSHR_AMT]], 63
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i64 [[X:%.*]], [[LSHR_M]]
+; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i64 [[Y]], 63
+; CHECK-NEXT:    [[SHL_M:%.*]] = xor i64 [[SHL_AMT]], 63
+; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[X]], [[SHL_M]]
+; CHECK-NEXT:    [[R:%.*]] = or i64 [[LSHR]], [[SHL]]
+; CHECK-NEXT:    ret i64 [[R]]
+;
+  %lshr_amt = add nuw i64 %y, 1
+  %lshr_m = and i64 %lshr_amt, 63
+  %lshr = lshr i64 %x, %lshr_m
+  %shl_amt = add i64 %y, 63
+  %shl_m = xor i64 %shl_amt, 63
+  %shl = shl i64 %x, %shl_m
+  %r = or i64 %lshr, %shl
+  ret i64 %r
+}
+
+define i8 @rot_add_xor_mask_fshr_commute(i8 %x, i8 %y) {
+; CHECK-LABEL: @rot_add_xor_mask_fshr_commute(
+; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i8 [[Y:%.*]], 1
+; CHECK-NEXT:    [[LSHR_M:%.*]] = and i8 [[LSHR_AMT]], 7
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X:%.*]], [[LSHR_M]]
+; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i8 [[Y]], 7
+; CHECK-NEXT:    [[SHL_M:%.*]] = xor i8 [[SHL_AMT]], 7
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X]], [[SHL_M]]
+; CHECK-NEXT:    [[R:%.*]] = or i8 [[SHL]], [[LSHR]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lshr_amt = add i8 %y, 1
+  %lshr_m = and i8 %lshr_amt, 7
+  %lshr = lshr i8 %x, %lshr_m
+  %shl_amt = add i8 %y, 7
+  %shl_m = xor i8 %shl_amt, 7
+  %shl = shl i8 %x, %shl_m
+  %r = or i8 %shl, %lshr
+  ret i8 %r
+}
+
+;; Negative tests
+
+define i8 @rot_add_xor_mask_fshl_and_xor(i8 %x, i8 %y) {
+; CHECK-LABEL: @rot_add_xor_mask_fshl_and_xor(
+; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i8 [[Y:%.*]], 1
+; CHECK-NEXT:    [[SHL_M:%.*]] = and i8 [[SHL_AMT]], 7
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X:%.*]], [[SHL_M]]
+; CHECK-NEXT:    [[Y_M:%.*]] = and i8 [[Y]], 7
+; CHECK-NEXT:    [[LSHR_M:%.*]] = xor i8 [[Y_M]], 7
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X]], [[LSHR_M]]
+; CHECK-NEXT:    [[R:%.*]] = or i8 [[SHL]], [[LSHR]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %shl_amt = add i8 %y, 1
+  %shl_m = and i8 %shl_amt, 7
+  %shl = shl i8 %x, %shl_m
+  %y_m = and i8 %y, 7
+  %lshr_m = xor i8 %y_m, 7
+  %lshr = lshr i8 %x, %lshr_m
+  %r = or i8 %shl, %lshr
+  ret i8 %r
+}
+
+define i8 @rot_add_xor_mask_fshl_wrong_mask(i8 %x, i8 %y) {
+; CHECK-LABEL: @rot_add_xor_mask_fshl_wrong_mask(
+; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i8 [[Y:%.*]], 1
+; CHECK-NEXT:    [[SHL_M:%.*]] = and i8 [[SHL_AMT]], 3
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X:%.*]], [[SHL_M]]
+; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i8 [[Y]], 3
+; CHECK-NEXT:    [[LSHR_M:%.*]] = xor i8 [[LSHR_AMT]], 3
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X]], [[LSHR_M]]
+; CHECK-NEXT:    [[R:%.*]] = or i8 [[SHL]], [[LSHR]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %shl_amt = add i8 %y, 1
+  %shl_m = and i8 %shl_amt, 3
+  %shl = shl i8 %x, %shl_m
+  %lshr_amt = add i8 %y, 3
+  %lshr_m = xor i8 %lshr_amt, 3
+  %lshr = lshr i8 %x, %lshr_m
+  %r = or i8 %shl, %lshr
+  ret i8 %r
+}
+
+define i7 @rot_add_xor_mask_fshl_non_pow2(i7 %x, i7 %y) {
+; CHECK-LABEL: @rot_add_xor_mask_fshl_non_pow2(
+; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i7 [[Y:%.*]], 1
+; CHECK-NEXT:    [[SHL_M:%.*]] = and i7 [[SHL_AMT]], 6
+; CHECK-NEXT:    [[SHL:%.*]] = shl i7 [[X:%.*]], [[SHL_M]]
+; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i7 [[Y]], 6
+; CHECK-NEXT:    [[LSHR_M:%.*]] = xor i7 [[LSHR_AMT]], 6
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i7 [[X]], [[LSHR_M]]
+; CHECK-NEXT:    [[R:%.*]] = or i7 [[SHL]], [[LSHR]]
+; CHECK-NEXT:    ret i7 [[R]]
+;
+  %shl_amt = add i7 %y, 1
+  %shl_m = and i7 %shl_amt, 6
+  %shl = shl i7 %x, %shl_m
+  %lshr_amt = add i7 %y, 6
+  %lshr_m = xor i7 %lshr_amt, 6
+  %lshr = lshr i7 %x, %lshr_m
+  %r = or i7 %shl, %lshr
+  ret i7 %r
+}
+
+define i8 @rot_add_xor_mask_fshl_no_plus_one(i8 %x, i8 %y) {
+; CHECK-LABEL: @rot_add_xor_mask_fshl_no_plus_one(
+; CHECK-NEXT:    [[SHL_M:%.*]] = and i8 [[Y:%.*]], 7
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X:%.*]], [[SHL_M]]
+; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i8 [[Y]], 7
+; CHECK-NEXT:    [[LSHR_M:%.*]] = xor i8 [[LSHR_AMT]], 7
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X]], [[LSHR_M]]
+; CHECK-NEXT:    [[R:%.*]] = or i8 [[SHL]], [[LSHR]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %shl_m = and i8 %y, 7
+  %shl = shl i8 %x, %shl_m
+  %lshr_amt = add i8 %y, 7
+  %lshr_m = xor i8 %lshr_amt, 7
+  %lshr = lshr i8 %x, %lshr_m
+  %r = or i8 %shl, %lshr
+  ret i8 %r
+}
+
+define i8 @rot_add_xor_mask_funnel(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @rot_add_xor_mask_funnel(
+; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i8 [[Y:%.*]], 1
+; CHECK-NEXT:    [[SHL_M:%.*]] = and i8 [[SHL_AMT]], 7
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X:%.*]], [[SHL_M]]
+; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i8 [[Y]], 7
+; CHECK-NEXT:    [[LSHR_M:%.*]] = xor i8 [[LSHR_AMT]], 7
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[Z:%.*]], [[LSHR_M]]
+; CHECK-NEXT:    [[R:%.*]] = or i8 [[SHL]], [[LSHR]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %shl_amt = add i8 %y, 1
+  %shl_m = and i8 %shl_amt, 7
+  %shl = shl i8 %x, %shl_m
+  %lshr_amt = add i8 %y, 7
+  %lshr_m = xor i8 %lshr_amt, 7
+  %lshr = lshr i8 %z, %lshr_m
+  %r = or i8 %shl, %lshr
+  ret i8 %r
+}
+
+define i8 @rot_add_xor_mask_fshl_multi_use(i8 %x, i8 %y) {
+; CHECK-LABEL: @rot_add_xor_mask_fshl_multi_use(
+; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i8 [[Y:%.*]], 1
+; CHECK-NEXT:    [[SHL_M:%.*]] = and i8 [[SHL_AMT]], 7
+; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X:%.*]], [[SHL_M]]
+; CHECK-NEXT:    call void @use_i8(i8 [[SHL]])
+; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i8 [[Y]], 7
+; CHECK-NEXT:    [[LSHR_M:%.*]] = xor i8 [[LSHR_AMT]], 7
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X]], [[LSHR_M]]
+; CHECK-NEXT:    [[R:%.*]] = or i8 [[SHL]], [[LSHR]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %shl_amt = add i8 %y, 1
+  %shl_m = and i8 %shl_amt, 7
+  %shl = shl i8 %x, %shl_m
+  call void @use_i8(i8 %shl)
+  %lshr_amt = add i8 %y, 7
+  %lshr_m = xor i8 %lshr_amt, 7
+  %lshr = lshr i8 %x, %lshr_m
+  %r = or i8 %shl, %lshr
+  ret i8 %r
+}

>From 00f5f30b17aa47f161076f34b9e80e15fd3d55df Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Wed, 5 Aug 2026 00:29:11 +0530
Subject: [PATCH 2/2] [InstCombine] Optimization + Check Diff

---
 .../InstCombine/InstCombineAndOrXor.cpp       | 11 +++++
 llvm/test/Transforms/InstCombine/fsh.ll       | 49 +++----------------
 2 files changed, 18 insertions(+), 42 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index b6f4a55c07e8a..49f416e69cdc8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3013,6 +3013,17 @@ InstCombinerImpl::convertOrOfShiftsToFunnelShift(Instruction &Or) {
           match(R, m_And(m_Neg(m_Specific(X)), m_SpecificInt(Mask))))
         return X;
 
+      // (shl ShVal, (X + 1) & (Width-1)) | (lshr ShVal, (X + Width-1) ^
+      // (Width-1))
+      {
+        Value *ShAmt = nullptr;
+        if (match(L, m_c_And(m_Value(ShAmt), m_SpecificInt(Mask))) &&
+            match(ShAmt, m_c_Add(m_Value(X), m_SpecificInt(1))) &&
+            match(R, m_c_Xor(m_c_Add(m_Specific(X), m_SpecificInt(Mask)),
+                             m_SpecificInt(Mask))))
+          return ShAmt;
+      }
+
       // (shl ShVal, X) | (lshr ShVal, ((-X) & (Width - 1)))
       if (match(R, m_And(m_Neg(m_Specific(L)), m_SpecificInt(Mask))))
         return L;
diff --git a/llvm/test/Transforms/InstCombine/fsh.ll b/llvm/test/Transforms/InstCombine/fsh.ll
index e42f30223d76d..c620d623eaf12 100644
--- a/llvm/test/Transforms/InstCombine/fsh.ll
+++ b/llvm/test/Transforms/InstCombine/fsh.ll
@@ -1307,12 +1307,7 @@ define i32 @rot_fsh(i32 %x, i32 %y) {
 define i8 @rot_add_xor_mask_fshl(i8 %x, i8 %y) {
 ; CHECK-LABEL: @rot_add_xor_mask_fshl(
 ; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i8 [[Y:%.*]], 1
-; CHECK-NEXT:    [[SHL_M:%.*]] = and i8 [[SHL_AMT]], 7
-; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X:%.*]], [[SHL_M]]
-; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i8 [[Y]], 7
-; CHECK-NEXT:    [[LSHR_M:%.*]] = xor i8 [[LSHR_AMT]], 7
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X]], [[LSHR_M]]
-; CHECK-NEXT:    [[R:%.*]] = or i8 [[SHL]], [[LSHR]]
+; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[SHL_AMT]])
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %shl_amt = add i8 %y, 1
@@ -1328,12 +1323,7 @@ define i8 @rot_add_xor_mask_fshl(i8 %x, i8 %y) {
 define i64 @rot_add_xor_mask_fshl_i64(i64 %x, i64 %y) {
 ; CHECK-LABEL: @rot_add_xor_mask_fshl_i64(
 ; CHECK-NEXT:    [[SHL_AMT:%.*]] = add nuw i64 [[Y:%.*]], 1
-; CHECK-NEXT:    [[SHL_M:%.*]] = and i64 [[SHL_AMT]], 63
-; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[X:%.*]], [[SHL_M]]
-; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i64 [[Y]], 63
-; CHECK-NEXT:    [[LSHR_M:%.*]] = xor i64 [[LSHR_AMT]], 63
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i64 [[X]], [[LSHR_M]]
-; CHECK-NEXT:    [[R:%.*]] = or i64 [[SHL]], [[LSHR]]
+; CHECK-NEXT:    [[R:%.*]] = call i64 @llvm.fshl.i64(i64 [[X:%.*]], i64 [[X]], i64 [[SHL_AMT]])
 ; CHECK-NEXT:    ret i64 [[R]]
 ;
   %shl_amt = add nuw i64 %y, 1
@@ -1349,12 +1339,7 @@ define i64 @rot_add_xor_mask_fshl_i64(i64 %x, i64 %y) {
 define i8 @rot_add_xor_mask_fshl_commute(i8 %x, i8 %y) {
 ; CHECK-LABEL: @rot_add_xor_mask_fshl_commute(
 ; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i8 [[Y:%.*]], 1
-; CHECK-NEXT:    [[SHL_M:%.*]] = and i8 [[SHL_AMT]], 7
-; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X:%.*]], [[SHL_M]]
-; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i8 [[Y]], 7
-; CHECK-NEXT:    [[LSHR_M:%.*]] = xor i8 [[LSHR_AMT]], 7
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X]], [[LSHR_M]]
-; CHECK-NEXT:    [[R:%.*]] = or i8 [[LSHR]], [[SHL]]
+; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[SHL_AMT]])
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %shl_amt = add i8 %y, 1
@@ -1370,12 +1355,7 @@ define i8 @rot_add_xor_mask_fshl_commute(i8 %x, i8 %y) {
 define <2 x i8> @rot_add_xor_mask_fshl_vec(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @rot_add_xor_mask_fshl_vec(
 ; CHECK-NEXT:    [[SHL_AMT:%.*]] = add <2 x i8> [[Y:%.*]], splat (i8 1)
-; CHECK-NEXT:    [[SHL_M:%.*]] = and <2 x i8> [[SHL_AMT]], splat (i8 7)
-; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i8> [[X:%.*]], [[SHL_M]]
-; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add <2 x i8> [[Y]], splat (i8 7)
-; CHECK-NEXT:    [[LSHR_M:%.*]] = xor <2 x i8> [[LSHR_AMT]], splat (i8 7)
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr <2 x i8> [[X]], [[LSHR_M]]
-; CHECK-NEXT:    [[R:%.*]] = or <2 x i8> [[SHL]], [[LSHR]]
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.fshl.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[X]], <2 x i8> [[SHL_AMT]])
 ; CHECK-NEXT:    ret <2 x i8> [[R]]
 ;
   %shl_amt = add <2 x i8> %y, splat (i8 1)
@@ -1391,12 +1371,7 @@ define <2 x i8> @rot_add_xor_mask_fshl_vec(<2 x i8> %x, <2 x i8> %y) {
 define i8 @rot_add_xor_mask_fshr(i8 %x, i8 %y) {
 ; CHECK-LABEL: @rot_add_xor_mask_fshr(
 ; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i8 [[Y:%.*]], 1
-; CHECK-NEXT:    [[LSHR_M:%.*]] = and i8 [[LSHR_AMT]], 7
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X:%.*]], [[LSHR_M]]
-; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i8 [[Y]], 7
-; CHECK-NEXT:    [[SHL_M:%.*]] = xor i8 [[SHL_AMT]], 7
-; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X]], [[SHL_M]]
-; CHECK-NEXT:    [[R:%.*]] = or i8 [[LSHR]], [[SHL]]
+; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[LSHR_AMT]])
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %lshr_amt = add i8 %y, 1
@@ -1412,12 +1387,7 @@ define i8 @rot_add_xor_mask_fshr(i8 %x, i8 %y) {
 define i64 @rot_add_xor_mask_fshr_i64(i64 %x, i64 %y) {
 ; CHECK-LABEL: @rot_add_xor_mask_fshr_i64(
 ; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add nuw i64 [[Y:%.*]], 1
-; CHECK-NEXT:    [[LSHR_M:%.*]] = and i64 [[LSHR_AMT]], 63
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i64 [[X:%.*]], [[LSHR_M]]
-; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i64 [[Y]], 63
-; CHECK-NEXT:    [[SHL_M:%.*]] = xor i64 [[SHL_AMT]], 63
-; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[X]], [[SHL_M]]
-; CHECK-NEXT:    [[R:%.*]] = or i64 [[LSHR]], [[SHL]]
+; CHECK-NEXT:    [[R:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 [[LSHR_AMT]])
 ; CHECK-NEXT:    ret i64 [[R]]
 ;
   %lshr_amt = add nuw i64 %y, 1
@@ -1433,12 +1403,7 @@ define i64 @rot_add_xor_mask_fshr_i64(i64 %x, i64 %y) {
 define i8 @rot_add_xor_mask_fshr_commute(i8 %x, i8 %y) {
 ; CHECK-LABEL: @rot_add_xor_mask_fshr_commute(
 ; CHECK-NEXT:    [[LSHR_AMT:%.*]] = add i8 [[Y:%.*]], 1
-; CHECK-NEXT:    [[LSHR_M:%.*]] = and i8 [[LSHR_AMT]], 7
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X:%.*]], [[LSHR_M]]
-; CHECK-NEXT:    [[SHL_AMT:%.*]] = add i8 [[Y]], 7
-; CHECK-NEXT:    [[SHL_M:%.*]] = xor i8 [[SHL_AMT]], 7
-; CHECK-NEXT:    [[SHL:%.*]] = shl i8 [[X]], [[SHL_M]]
-; CHECK-NEXT:    [[R:%.*]] = or i8 [[SHL]], [[LSHR]]
+; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[LSHR_AMT]])
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %lshr_amt = add i8 %y, 1



More information about the llvm-commits mailing list