diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 31cf6386918..f1766fd4fce 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/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/test/Transforms/InstCombine/rotate.ll b/test/Transforms/InstCombine/rotate.ll index 984dac1cbc1..a11fcd97424 100644 --- a/test/Transforms/InstCombine/rotate.ll +++ b/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