[llvm] 9acc404 - [InstCombine] Recognize more rotation patterns (#78107)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 18 04:29:58 PST 2024
Author: Yingwei Zheng
Date: 2024-01-18T20:29:53+08:00
New Revision: 9acc4042300a92856527169b28c43cebf179d6d5
URL: https://github.com/llvm/llvm-project/commit/9acc4042300a92856527169b28c43cebf179d6d5
DIFF: https://github.com/llvm/llvm-project/commit/9acc4042300a92856527169b28c43cebf179d6d5.diff
LOG: [InstCombine] Recognize more rotation patterns (#78107)
InstCombine already handles the pattern `(shl ShVal, (X & (Width - 1)))
| (lshr ShVal, ((-X) & (Width - 1)))`. Under certain circumstances, `X &
(Width - 1)` will be simplified to `X`. Therefore, this patch adds
support for the pattern `(shl ShVal, X) | (lshr ShVal, ((-X) & (Width -
1)))`.
Alive2: https://alive2.llvm.org/ce/z/P7JQ2V
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/test/Transforms/InstCombine/funnel.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index de06fb8badf8173..5fd944a859ef098 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2809,6 +2809,10 @@ static Instruction *matchFunnelShift(Instruction &Or, InstCombinerImpl &IC,
match(R, m_And(m_Neg(m_Specific(X)), m_SpecificInt(Mask))))
return X;
+ // (shl ShVal, X) | (lshr ShVal, ((-X) & (Width - 1)))
+ if (match(R, m_And(m_Neg(m_Specific(L)), m_SpecificInt(Mask))))
+ return L;
+
// Similar to above, but the shift amount may be extended after masking,
// so return the extended value as the parameter for the intrinsic.
if (match(L, m_ZExt(m_And(m_Value(X), m_SpecificInt(Mask)))) &&
diff --git a/llvm/test/Transforms/InstCombine/funnel.ll b/llvm/test/Transforms/InstCombine/funnel.ll
index 772a052b3a4f84c..162519e648f3e47 100644
--- a/llvm/test/Transforms/InstCombine/funnel.ll
+++ b/llvm/test/Transforms/InstCombine/funnel.ll
@@ -559,3 +559,79 @@ define i8 @unmasked_shlop_masked_shift_amount(i16 %x, i16 %y, i16 %shamt) {
%t8 = trunc i16 %t7 to i8
ret i8 %t8
}
+
+define i32 @test_rotl_and_neg(i32 %x, i32 %shamt) {
+; CHECK-LABEL: @test_rotl_and_neg(
+; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[SHAMT:%.*]])
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %shl = shl i32 %x, %shamt
+ %neg = sub i32 0, %shamt
+ %and = and i32 %neg, 31
+ %shr = lshr i32 %x, %and
+ %or = or i32 %shl, %shr
+ ret i32 %or
+}
+
+define i32 @test_rotl_and_neg_commuted(i32 %x, i32 %shamt) {
+; CHECK-LABEL: @test_rotl_and_neg_commuted(
+; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[SHAMT:%.*]])
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %shl = shl i32 %x, %shamt
+ %neg = sub i32 0, %shamt
+ %and = and i32 %neg, 31
+ %shr = lshr i32 %x, %and
+ %or = or i32 %shr, %shl
+ ret i32 %or
+}
+
+define i32 @test_rotr_and_neg(i32 %x, i32 %shamt) {
+; CHECK-LABEL: @test_rotr_and_neg(
+; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[SHAMT:%.*]])
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %shr = lshr i32 %x, %shamt
+ %neg = sub i32 0, %shamt
+ %and = and i32 %neg, 31
+ %shl = shl i32 %x, %and
+ %or = or i32 %shl, %shr
+ ret i32 %or
+}
+
+; Negative tests
+
+; Only work for rotation patterns
+define i32 @test_fshl_and_neg(i32 %x, i32 %y, i32 %shamt) {
+; CHECK-LABEL: @test_fshl_and_neg(
+; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[SHAMT]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[NEG]], 31
+; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[Y:%.*]], [[AND]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %shl = shl i32 %x, %shamt
+ %neg = sub i32 0, %shamt
+ %and = and i32 %neg, 31
+ %shr = lshr i32 %y, %and
+ %or = or i32 %shl, %shr
+ ret i32 %or
+}
+
+define i32 @test_rotl_and_neg_wrong_mask(i32 %x, i32 %shamt) {
+; CHECK-LABEL: @test_rotl_and_neg_wrong_mask(
+; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[SHAMT]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[NEG]], 15
+; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X]], [[AND]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %shl = shl i32 %x, %shamt
+ %neg = sub i32 0, %shamt
+ %and = and i32 %neg, 15
+ %shr = lshr i32 %x, %and
+ %or = or i32 %shl, %shr
+ ret i32 %or
+}
More information about the llvm-commits
mailing list