; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s declare i8 @llvm.fshl.i8(i8, i8, i8) declare i8 @llvm.fshr.i8(i8, i8, i8) declare <2 x i5> @llvm.fshl.v2i5(<2 x i5>, <2 x i5>, <2 x i5>) declare <2 x i5> @llvm.fshr.v2i5(<2 x i5>, <2 x i5>, <2 x i5>) declare void @use(i8) define i1 @rol_eq(i8 %x, i8 %y, i8 %z) { ; CHECK-LABEL: @rol_eq( ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %z) %f2 = tail call i8 @llvm.fshl.i8(i8 %y, i8 %y, i8 %z) %r = icmp eq i8 %f, %f2 ret i1 %r } define i1 @rol_ne(i8 %x, i8 %y, i8 %z) { ; CHECK-LABEL: @rol_ne( ; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %z) %f2 = tail call i8 @llvm.fshl.i8(i8 %y, i8 %y, i8 %z) %r = icmp ne i8 %f, %f2 ret i1 %r } define i1 @ror_eq(i8 %x, i8 %y, i8 %z) { ; CHECK-LABEL: @ror_eq( ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 %z) %f2 = tail call i8 @llvm.fshr.i8(i8 %y, i8 %y, i8 %z) %r = icmp eq i8 %f, %f2 ret i1 %r } define i1 @ror_ne(i8 %x, i8 %y, i8 %z) { ; CHECK-LABEL: @ror_ne( ; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 %z) %f2 = tail call i8 @llvm.fshr.i8(i8 %y, i8 %y, i8 %z) %r = icmp ne i8 %f, %f2 ret i1 %r } define i1 @rol_eq_use(i8 %x, i8 %y, i8 %z) { ; CHECK-LABEL: @rol_eq_use( ; CHECK-NEXT: [[F:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Z:%.*]]) ; CHECK-NEXT: call void @use(i8 [[F]]) ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %z) call void @use(i8 %f) %f2 = tail call i8 @llvm.fshl.i8(i8 %y, i8 %y, i8 %z) %r = icmp eq i8 %f, %f2 ret i1 %r } define i1 @rol_eq_uses(i8 %x, i8 %y, i8 %z) { ; CHECK-LABEL: @rol_eq_uses( ; CHECK-NEXT: [[F:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Z:%.*]]) ; CHECK-NEXT: call void @use(i8 [[F]]) ; CHECK-NEXT: [[F2:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[Y:%.*]], i8 [[Y]], i8 [[Z]]) ; CHECK-NEXT: call void @use(i8 [[F2]]) ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], [[Y]] ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %z) call void @use(i8 %f) %f2 = tail call i8 @llvm.fshl.i8(i8 %y, i8 %y, i8 %z) call void @use(i8 %f2) %r = icmp eq i8 %f, %f2 ret i1 %r } define <2 x i1> @rol_eq_vec(<2 x i5> %x, <2 x i5> %y, <2 x i5> %z) { ; CHECK-LABEL: @rol_eq_vec( ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i5> [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; %f = tail call <2 x i5> @llvm.fshl.v2i5(<2 x i5> %x, <2 x i5> %x, <2 x i5> %z) %f2 = tail call <2 x i5> @llvm.fshl.v2i5(<2 x i5> %y, <2 x i5> %y, <2 x i5> %z) %r = icmp eq <2 x i5> %f, %f2 ret <2 x i1> %r } define <2 x i1> @ror_eq_vec(<2 x i5> %x, <2 x i5> %y, <2 x i5> %z) { ; CHECK-LABEL: @ror_eq_vec( ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i5> [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; %f = tail call <2 x i5> @llvm.fshr.v2i5(<2 x i5> %x, <2 x i5> %x, <2 x i5> %z) %f2 = tail call <2 x i5> @llvm.fshr.v2i5(<2 x i5> %y, <2 x i5> %y, <2 x i5> %z) %r = icmp eq <2 x i5> %f, %f2 ret <2 x i1> %r } define i1 @rol_eq_cst(i8 %x) { ; CHECK-LABEL: @rol_eq_cst( ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], 64 ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 3) %r = icmp eq i8 %f, 2 ret i1 %r } define i1 @rol_ne_cst(i8 %x) { ; CHECK-LABEL: @rol_ne_cst( ; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], 64 ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 3) %r = icmp ne i8 %f, 2 ret i1 %r } define i1 @rol_eq_cst_use(i8 %x) { ; CHECK-LABEL: @rol_eq_cst_use( ; CHECK-NEXT: [[F:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 3) ; CHECK-NEXT: call void @use(i8 [[F]]) ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], 64 ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 3) call void @use(i8 %f) %r = icmp eq i8 %f, 2 ret i1 %r } define i1 @ror_eq_cst(i8 %x) { ; CHECK-LABEL: @ror_eq_cst( ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], 12 ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 2) %r = icmp eq i8 %f, 3 ret i1 %r } define i1 @ror_ne_cst(i8 %x) { ; CHECK-LABEL: @ror_ne_cst( ; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], 12 ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 2) %r = icmp ne i8 %f, 3 ret i1 %r } define <2 x i1> @rol_eq_cst_vec(<2 x i5> %x) { ; CHECK-LABEL: @rol_eq_cst_vec( ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i5> [[X:%.*]], <i5 8, i5 8> ; CHECK-NEXT: ret <2 x i1> [[R]] ; %f = tail call <2 x i5> @llvm.fshl.v2i5(<2 x i5> %x, <2 x i5> %x, <2 x i5> <i5 3, i5 3>) %r = icmp eq <2 x i5> %f, <i5 2, i5 2> ret <2 x i1> %r } define <2 x i1> @rol_eq_cst_undef(<2 x i5> %x) { ; CHECK-LABEL: @rol_eq_cst_undef( ; CHECK-NEXT: [[F:%.*]] = tail call <2 x i5> @llvm.fshl.v2i5(<2 x i5> [[X:%.*]], <2 x i5> [[X]], <2 x i5> <i5 3, i5 3>) ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i5> [[F]], <i5 2, i5 undef> ; CHECK-NEXT: ret <2 x i1> [[R]] ; %f = tail call <2 x i5> @llvm.fshl.v2i5(<2 x i5> %x, <2 x i5> %x, <2 x i5> <i5 3, i5 3>) %r = icmp eq <2 x i5> %f, <i5 2, i5 undef> ret <2 x i1> %r } ; negative test - not a rotate define i1 @no_rotate(i8 %x, i8 %y, i8 %z) { ; CHECK-LABEL: @no_rotate( ; CHECK-NEXT: [[F:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) ; CHECK-NEXT: [[F2:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[Y]], i8 [[Y]], i8 [[Z]]) ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[F]], [[F2]] ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshl.i8(i8 %x, i8 %y, i8 %z) %f2 = tail call i8 @llvm.fshl.i8(i8 %y, i8 %y, i8 %z) %r = icmp eq i8 %f, %f2 ret i1 %r } ; negative test - wrong predicate define i1 @wrong_pred(i8 %x, i8 %y, i8 %z) { ; CHECK-LABEL: @wrong_pred( ; CHECK-NEXT: [[F:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Z:%.*]]) ; CHECK-NEXT: [[F2:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[Y:%.*]], i8 [[Y]], i8 [[Z]]) ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[F]], [[F2]] ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %z) %f2 = tail call i8 @llvm.fshl.i8(i8 %y, i8 %y, i8 %z) %r = icmp ult i8 %f, %f2 ret i1 %r } ; negative test - rotate amounts mismatch define i1 @amounts_mismatch(i8 %x, i8 %y, i8 %z, i8 %w) { ; CHECK-LABEL: @amounts_mismatch( ; CHECK-NEXT: [[F:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Z:%.*]]) ; CHECK-NEXT: [[F2:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[Y:%.*]], i8 [[Y]], i8 [[W:%.*]]) ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[F]], [[F2]] ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %z) %f2 = tail call i8 @llvm.fshl.i8(i8 %y, i8 %y, i8 %w) %r = icmp eq i8 %f, %f2 ret i1 %r } ; negative test - wrong predicate define i1 @wrong_pred2(i8 %x) { ; CHECK-LABEL: @wrong_pred2( ; CHECK-NEXT: [[F:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 5) ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[F]], 2 ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 27) %r = icmp ugt i8 %f, 2 ret i1 %r }