@@ -698,6 +698,104 @@ define i64 @rotateleft_64_zext_neg_mask_amount(i64 %0, i32 %1) {
698
698
ret i64 %10
699
699
}
700
700
701
+ define i64 @rotateright_64_zext_double_conversion (i64 %x , i32 %y ) {
702
+ ; CHECK-LABEL: @rotateright_64_zext_double_conversion(
703
+ ; CHECK-NEXT: [[Z:%.*]] = zext nneg i32 [[Y:%.*]] to i64
704
+ ; CHECK-NEXT: [[OR:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Z]])
705
+ ; CHECK-NEXT: ret i64 [[OR]]
706
+ ;
707
+ %z = zext i32 %y to i64
708
+ %neg = sub nsw i32 0 , %y
709
+ %and2 = and i32 %neg , 63
710
+ %conv = zext i32 %and2 to i64
711
+ %shl = shl i64 %x , %conv
712
+ %shr = lshr i64 %x , %z
713
+ %or = or i64 %shr , %shl
714
+ ret i64 %or
715
+ }
716
+
717
+ define i32 @rotateright_32_trunc_early (i32 %x , i64 %y ) {
718
+ ; CHECK-LABEL: @rotateright_32_trunc_early(
719
+ ; CHECK-NEXT: [[Z:%.*]] = trunc i64 [[Y:%.*]] to i32
720
+ ; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Z]])
721
+ ; CHECK-NEXT: ret i32 [[OR]]
722
+ ;
723
+ %z = trunc i64 %y to i32
724
+ %neg = sub nsw i32 0 , %z
725
+ %and2 = and i32 %neg , 31
726
+ %shl = shl i32 %x , %and2
727
+ %shr = lshr i32 %x , %z
728
+ %or = or i32 %shr , %shl
729
+ ret i32 %or
730
+ }
731
+
732
+ define i32 @rotateright_32_trunc_neg_mask_amount (i32 %x , i64 %y ) {
733
+ ; CHECK-LABEL: @rotateright_32_trunc_neg_mask_amount(
734
+ ; CHECK-NEXT: [[Z:%.*]] = trunc i64 [[Y:%.*]] to i32
735
+ ; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Z]])
736
+ ; CHECK-NEXT: ret i32 [[OR]]
737
+ ;
738
+ %z = trunc i64 %y to i32
739
+ %neg = sub i64 0 , %y
740
+ %and2 = and i64 %neg , 31
741
+ %conv = trunc i64 %and2 to i32
742
+ %shl = shl i32 %x , %conv
743
+ %shr = lshr i32 %x , %z
744
+ %or = or i32 %shr , %shl
745
+ ret i32 %or
746
+ }
747
+
748
+ ; restrict the shift amount before rotating
749
+
750
+ define i32 @rotateleft_32_restricted_shamt (i32 %x , i32 %shAmt ) {
751
+ ; CHECK-LABEL: @rotateleft_32_restricted_shamt(
752
+ ; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 30
753
+ ; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshl.i32(i32 [[X]], i32 [[X]], i32 [[AND]])
754
+ ; CHECK-NEXT: ret i32 [[OR]]
755
+ ;
756
+ %and = and i32 %x , 30
757
+ %shl = shl i32 %x , %and
758
+ %sub = sub i32 0 , %and
759
+ %shr = lshr i32 %x , %sub
760
+ %or = or i32 %shl , %shr
761
+ ret i32 %or
762
+ }
763
+
764
+ ; unncessarily large and masks
765
+
766
+ define i32 @rotateleft_32_non_restricted_shamt (i32 %x , i32 %t ) {
767
+ ; CHECK-LABEL: @rotateleft_32_non_restricted_shamt(
768
+ ; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[T:%.*]])
769
+ ; CHECK-NEXT: ret i32 [[OR]]
770
+ ;
771
+ %and = and i32 %t , 31
772
+ %shl = shl i32 %x , %and
773
+ %sub = sub nsw i32 0 , %and
774
+ %and2 = and i32 %sub , 31
775
+ %shr = lshr i32 %x , %and2
776
+ %or = or i32 %shl , %shr
777
+ ret i32 %or
778
+ }
779
+
780
+ ; negative test - right and mask is too small (should be >=31)
781
+
782
+ define i32 @rotateleft_32_incorrect_right_mask (i32 %x , i32 %t ) {
783
+ ; CHECK-LABEL: @rotateleft_32_incorrect_right_mask(
784
+ ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], [[T:%.*]]
785
+ ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[T]]
786
+ ; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], 30
787
+ ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X]], [[AND]]
788
+ ; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
789
+ ; CHECK-NEXT: ret i32 [[OR]]
790
+ ;
791
+ %shl = shl i32 %x , %t
792
+ %sub = sub nsw i32 0 , %t
793
+ %and = and i32 %sub , 30
794
+ %shr = lshr i32 %x , %and
795
+ %or = or i32 %shl , %shr
796
+ ret i32 %or
797
+ }
798
+
701
799
; Non-power-of-2 types. This could be transformed, but it's not a typical rotate pattern.
702
800
703
801
define i9 @rotateleft_9_neg_mask_wide_amount_commute (i9 %v , i33 %shamt ) {
@@ -1086,3 +1184,42 @@ define i32 @not_rotl_i32_add_less(i32 %x, i32 %y) {
1086
1184
%r = add i32 %shr , %shl
1087
1185
ret i32 %r
1088
1186
}
1187
+
1188
+ ; multi-use tests
1189
+ define i32 @rotateleft_32_use_zext (i32 %x , i16 %shAmt ) {
1190
+ ; CHECK-LABEL: @rotateleft_32_use_zext(
1191
+ ; CHECK-NEXT: [[CONV:%.*]] = zext i16 [[SHAMT:%.*]] to i32
1192
+ ; CHECK-NEXT: call void @use(i32 [[CONV]])
1193
+ ; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[CONV]])
1194
+ ; CHECK-NEXT: ret i32 [[OR]]
1195
+ ;
1196
+ %conv = zext i16 %shAmt to i32
1197
+ call void @use (i32 %conv )
1198
+ %shl = shl i32 %x , %conv
1199
+ %sub = sub i32 0 , %conv
1200
+ %shr = lshr i32 %x , %sub
1201
+ %or = or i32 %shl , %shr
1202
+ ret i32 %or
1203
+ }
1204
+
1205
+ define i64 @rotateleft_64_use_and (i64 %x , i32 %y ) {
1206
+ ; CHECK-LABEL: @rotateleft_64_use_and(
1207
+ ; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], 63
1208
+ ; CHECK-NEXT: [[Z:%.*]] = zext nneg i32 [[AND]] to i64
1209
+ ; CHECK-NEXT: call void @use(i64 [[Z]])
1210
+ ; CHECK-NEXT: [[OR:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Z]])
1211
+ ; CHECK-NEXT: ret i64 [[OR]]
1212
+ ;
1213
+ %and = and i32 %y , 63
1214
+ %z = zext i32 %and to i64
1215
+ call void @use (i64 %z )
1216
+ %neg = sub nsw i32 0 , %y
1217
+ %and2 = and i32 %neg , 63
1218
+ %conv = zext i32 %and2 to i64
1219
+ %shl = shl i64 %x , %conv
1220
+ %shr = lshr i64 %x , %z
1221
+ %or = or i64 %shr , %shl
1222
+ ret i64 %or
1223
+ }
1224
+
1225
+ declare void @use (i32 )
0 commit comments