[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