define i16 @rotateleft_16_neg_mask(i16 %v, i16 %shamt) {
; CHECK-LABEL: @rotateleft_16_neg_mask(
-; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.fshl.i16(i16 [[V:%.*]], i16 [[V]], i16 [[SHAMT:%.*]])
-; CHECK-NEXT: ret i16 [[RET]]
+; CHECK-NEXT: [[OR:%.*]] = call i16 @llvm.fshl.i16(i16 [[V:%.*]], i16 [[V]], i16 [[SHAMT:%.*]])
+; CHECK-NEXT: ret i16 [[OR]]
;
%neg = sub i16 0, %shamt
%lshamt = and i16 %shamt, 15
define i16 @rotateleft_16_neg_mask_commute(i16 %v, i16 %shamt) {
; CHECK-LABEL: @rotateleft_16_neg_mask_commute(
-; CHECK-NEXT: [[RET:%.*]] = call i16 @llvm.fshl.i16(i16 [[V:%.*]], i16 [[V]], i16 [[SHAMT:%.*]])
-; CHECK-NEXT: ret i16 [[RET]]
+; CHECK-NEXT: [[OR:%.*]] = call i16 @llvm.fshl.i16(i16 [[V:%.*]], i16 [[V]], i16 [[SHAMT:%.*]])
+; CHECK-NEXT: ret i16 [[OR]]
;
%neg = sub i16 0, %shamt
%lshamt = and i16 %shamt, 15
define i8 @rotateright_8_neg_mask(i8 %v, i8 %shamt) {
; CHECK-LABEL: @rotateright_8_neg_mask(
-; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.fshr.i8(i8 [[V:%.*]], i8 [[V]], i8 [[SHAMT:%.*]])
-; CHECK-NEXT: ret i8 [[RET]]
+; CHECK-NEXT: [[OR:%.*]] = call i8 @llvm.fshr.i8(i8 [[V:%.*]], i8 [[V]], i8 [[SHAMT:%.*]])
+; CHECK-NEXT: ret i8 [[OR]]
;
%neg = sub i8 0, %shamt
%rshamt = and i8 %shamt, 7
define i8 @rotateright_8_neg_mask_commute(i8 %v, i8 %shamt) {
; CHECK-LABEL: @rotateright_8_neg_mask_commute(
-; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.fshr.i8(i8 [[V:%.*]], i8 [[V]], i8 [[SHAMT:%.*]])
-; CHECK-NEXT: ret i8 [[RET]]
+; CHECK-NEXT: [[OR:%.*]] = call i8 @llvm.fshr.i8(i8 [[V:%.*]], i8 [[V]], i8 [[SHAMT:%.*]])
+; CHECK-NEXT: ret i8 [[OR]]
;
%neg = sub i8 0, %shamt
%rshamt = and i8 %shamt, 7
ret i24 %r
}
+define i32 @rotl_select_zext_shamt(i32 %x, i8 %y) {
+; CHECK-LABEL: @rotl_select_zext_shamt(
+; CHECK-NEXT: [[REM:%.*]] = and i8 [[Y:%.*]], 31
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[REM]], 0
+; CHECK-NEXT: [[SH_PROM:%.*]] = zext i8 [[REM]] to i32
+; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i8 32, [[REM]]
+; CHECK-NEXT: [[SH_PROM1:%.*]] = zext i8 [[SUB]] to i32
+; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X:%.*]], [[SH_PROM1]]
+; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X]], [[SH_PROM]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[OR]]
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %rem = and i8 %y, 31
+ %cmp = icmp eq i8 %rem, 0
+ %sh_prom = zext i8 %rem to i32
+ %sub = sub nuw nsw i8 32, %rem
+ %sh_prom1 = zext i8 %sub to i32
+ %shr = lshr i32 %x, %sh_prom1
+ %shl = shl i32 %x, %sh_prom
+ %or = or i32 %shl, %shr
+ %r = select i1 %cmp, i32 %x, i32 %or
+ ret i32 %r
+}
+
+define i64 @rotr_select_zext_shamt(i64 %x, i32 %y) {
+; CHECK-LABEL: @rotr_select_zext_shamt(
+; CHECK-NEXT: [[REM:%.*]] = and i32 [[Y:%.*]], 63
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 0
+; CHECK-NEXT: [[SH_PROM:%.*]] = zext i32 [[REM]] to i64
+; CHECK-NEXT: [[SHR:%.*]] = lshr i64 [[X:%.*]], [[SH_PROM]]
+; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 64, [[REM]]
+; CHECK-NEXT: [[SH_PROM1:%.*]] = zext i32 [[SUB]] to i64
+; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[X]], [[SH_PROM1]]
+; CHECK-NEXT: [[OR:%.*]] = or i64 [[SHL]], [[SHR]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i64 [[X]], i64 [[OR]]
+; CHECK-NEXT: ret i64 [[R]]
+;
+ %rem = and i32 %y, 63
+ %cmp = icmp eq i32 %rem, 0
+ %sh_prom = zext i32 %rem to i64
+ %shr = lshr i64 %x, %sh_prom
+ %sub = sub nuw nsw i32 64, %rem
+ %sh_prom1 = zext i32 %sub to i64
+ %shl = shl i64 %x, %sh_prom1
+ %or = or i64 %shl, %shr
+ %r = select i1 %cmp, i64 %x, i64 %or
+ ret i64 %r
+}
+
; Test that the transform doesn't crash when there's an "or" with a ConstantExpr operand.
@external_global = external global i8