summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp7
-rw-r--r--llvm/test/Transforms/InstCombine/rotate.ll18
2 files changed, 11 insertions, 14 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 31cf6386918..f1766fd4fce 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1898,6 +1898,13 @@ static Instruction *matchRotate(Instruction &Or) {
match(R, m_And(m_Neg(m_Specific(X)), m_SpecificInt(Mask))))
return X;
+ // 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)))) &&
+ match(R, m_And(m_Neg(m_ZExt(m_And(m_Specific(X), m_SpecificInt(Mask)))),
+ m_SpecificInt(Mask))))
+ return L;
+
return nullptr;
};
diff --git a/llvm/test/Transforms/InstCombine/rotate.ll b/llvm/test/Transforms/InstCombine/rotate.ll
index 984dac1cbc1..a11fcd97424 100644
--- a/llvm/test/Transforms/InstCombine/rotate.ll
+++ b/llvm/test/Transforms/InstCombine/rotate.ll
@@ -710,13 +710,8 @@ define i32 @rotl_constant_expr(i32 %shamt) {
define i32 @rotateleft32_doubleand1(i32 %v, i8 %r) {
; CHECK-LABEL: @rotateleft32_doubleand1(
-; CHECK-NEXT: [[M:%.*]] = and i8 [[R:%.*]], 31
-; CHECK-NEXT: [[Z:%.*]] = zext i8 [[M]] to i32
-; CHECK-NEXT: [[NEG:%.*]] = sub nsw i32 0, [[Z]]
-; CHECK-NEXT: [[AND2:%.*]] = and i32 [[NEG]], 31
-; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[V:%.*]], [[Z]]
-; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[V]], [[AND2]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHR]], [[SHL]]
+; CHECK-NEXT: [[Z:%.*]] = zext i8 [[R:%.*]] to i32
+; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshl.i32(i32 [[V:%.*]], i32 [[V]], i32 [[Z]])
; CHECK-NEXT: ret i32 [[OR]]
;
%m = and i8 %r, 31
@@ -731,13 +726,8 @@ define i32 @rotateleft32_doubleand1(i32 %v, i8 %r) {
define i32 @rotateright32_doubleand1(i32 %v, i16 %r) {
; CHECK-LABEL: @rotateright32_doubleand1(
-; CHECK-NEXT: [[M:%.*]] = and i16 [[R:%.*]], 31
-; CHECK-NEXT: [[Z:%.*]] = zext i16 [[M]] to i32
-; CHECK-NEXT: [[NEG:%.*]] = sub nsw i32 0, [[Z]]
-; CHECK-NEXT: [[AND2:%.*]] = and i32 [[NEG]], 31
-; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[V:%.*]], [[AND2]]
-; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[V]], [[Z]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHR]], [[SHL]]
+; CHECK-NEXT: [[Z:%.*]] = zext i16 [[R:%.*]] to i32
+; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshr.i32(i32 [[V:%.*]], i32 [[V]], i32 [[Z]])
; CHECK-NEXT: ret i32 [[OR]]
;
%m = and i16 %r, 31
OpenPOWER on IntegriCloud