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;
};
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
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