From d2658378b38bceb1ce88ffc570339ee3ae4691b5 Mon Sep 17 00:00:00 2001 From: Veera Date: Tue, 3 Dec 2024 17:00:06 +0000 Subject: [PATCH 1/2] Add Test --- .../InstSimplify/select-icmp-relational.ll | 472 ++++++++++++++++++ 1 file changed, 472 insertions(+) create mode 100644 llvm/test/Transforms/InstSimplify/select-icmp-relational.ll diff --git a/llvm/test/Transforms/InstSimplify/select-icmp-relational.ll b/llvm/test/Transforms/InstSimplify/select-icmp-relational.ll new file mode 100644 index 0000000000000..2ec80878e4e9b --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/select-icmp-relational.ll @@ -0,0 +1,472 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i1 @ult_ule(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ult_ule( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ult i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nuw i8 %x, %z + %c2 = icmp ule i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @ult_ule_no_flags(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ult_ule_no_flags( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ult i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add i8 %x, %z + %c2 = icmp ule i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @slt_sle(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @slt_sle( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp slt i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp sle i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp slt i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nsw i8 %x, %z + %c2 = icmp sle i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @slt_sle_no_flags(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @slt_sle_no_flags( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp slt i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp sle i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp slt i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add i8 %x, %z + %c2 = icmp sle i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @ugt_uge(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ugt_uge( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp uge i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ugt i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nuw i8 %x, %z + %c2 = icmp uge i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @sgt_sge(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @sgt_sge( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp sge i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp sgt i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nsw i8 %x, %z + %c2 = icmp sge i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define <2 x i1> @ult_ule_splat_vector(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: define <2 x i1> @ult_ule_splat_vector( +; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ult <2 x i8> [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext <2 x i1> [[C1]] to <2 x i8> +; CHECK-NEXT: [[ADD:%.*]] = add nuw <2 x i8> [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp ule <2 x i8> [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select <2 x i1> [[C1]], <2 x i1> [[C2]], <2 x i1> zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[AND]] +; + %c1 = icmp ult <2 x i8> %x, %y + %z = zext <2 x i1> %c1 to <2 x i8> + %add = add nuw <2 x i8> %x, %z + %c2 = icmp ule <2 x i8> %add, %y + %and = select <2 x i1> %c1, <2 x i1> %c2, <2 x i1> + ret <2 x i1> %and +} + +define <2 x i1> @ult_ule_vector_with_poison(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: define <2 x i1> @ult_ule_vector_with_poison( +; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ult <2 x i8> [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext <2 x i1> [[C1]] to <2 x i8> +; CHECK-NEXT: [[ADD:%.*]] = add nuw <2 x i8> [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp ule <2 x i8> [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select <2 x i1> [[C1]], <2 x i1> [[C2]], <2 x i1> +; CHECK-NEXT: ret <2 x i1> [[AND]] +; + %c1 = icmp ult <2 x i8> %x, %y + %z = zext <2 x i1> %c1 to <2 x i8> + %add = add nuw <2 x i8> %x, %z + %c2 = icmp ule <2 x i8> %add, %y + %and = select <2 x i1> %c1, <2 x i1> %c2, <2 x i1> + ret <2 x i1> %and +} + +define i1 @ugt_uge_with_poison(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ugt_uge_with_poison( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: ret i1 false +; + %c1 = icmp ugt i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nuw i8 %x, poison + %c2 = icmp uge i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +declare void @use(i8) +declare void @use_bit(i1) + +define i1 @ult_ule_multi_use(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ult_ule_multi_use( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], [[Y]] +; CHECK-NEXT: call void @use_bit(i1 [[C1]]) +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] +; CHECK-NEXT: call void @use_bit(i1 [[C2]]) +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ult i8 %x, %y + call void @use_bit(i1 %c1) + %z = zext i1 %c1 to i8 + %add = add nuw i8 %x, %z + %c2 = icmp ule i8 %add, %y + call void @use_bit(i1 %c2) + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @ult_ule_multi_use_add(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ult_ule_multi_use_add( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] +; CHECK-NEXT: call void @use(i8 [[ADD]]) +; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ult i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nuw i8 %x, %z + call void @use(i8 %add) + %c2 = icmp ule i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @ult_ule_commuted_binop(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ult_ule_commuted_binop( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ult i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nuw i8 %z, %x + %c2 = icmp ule i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @ult_sext_sub_ule(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ult_sext_sub_ule( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z_NEG:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Z_NEG]] +; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ult i8 %x, %y + %z = sext i1 %c1 to i8 + %add = sub nuw i8 %x, %z + %c2 = icmp ule i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @ugt_uge_const_fold_false(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ugt_uge_const_fold_false( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp uge i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ugt i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nuw i8 %x, %z + %c2 = icmp uge i8 %add, %y + %c3 = icmp ult i8 10, 1 + %and = select i1 %c1, i1 %c2, i1 %c3 + ret i1 %and +} + +define void @rust_inlclusive_noop(i8 noundef %n) unnamed_addr { +; CHECK-LABEL: define void @rust_inlclusive_noop( +; CHECK-SAME: i8 noundef [[N:%.*]]) unnamed_addr { +; CHECK-NEXT: [[START:.*]]: +; CHECK-NEXT: br label %[[BB2_I:.*]] +; CHECK: [[BB2_I]]: +; CHECK-NEXT: [[ITER_SROA_0_07:%.*]] = phi i8 [ 0, %[[START]] ], [ [[SPEC_SELECT5:%.*]], %[[BB2_I]] ] +; CHECK-NEXT: [[_0_I3_I:%.*]] = icmp ult i8 [[ITER_SROA_0_07]], [[N]] +; CHECK-NEXT: [[_0_I4_I:%.*]] = zext i1 [[_0_I3_I]] to i8 +; CHECK-NEXT: [[SPEC_SELECT5]] = add nuw i8 [[ITER_SROA_0_07]], [[_0_I4_I]] +; CHECK-NEXT: [[_0_I_NOT_I:%.*]] = icmp ule i8 [[SPEC_SELECT5]], [[N]] +; CHECK-NEXT: [[OR_COND_NOT:%.*]] = select i1 [[_0_I3_I]], i1 [[_0_I_NOT_I]], i1 false +; CHECK-NEXT: br i1 [[OR_COND_NOT]], label %[[BB2_I]], label %[[THEEND:.*]] +; CHECK: [[THEEND]]: +; CHECK-NEXT: ret void +; +start: + br label %bb2.i + +bb2.i: + %iter.sroa.0.07 = phi i8 [ 0, %start ], [ %spec.select5, %bb2.i ] + %_0.i3.i = icmp ult i8 %iter.sroa.0.07, %n + %_0.i4.i = zext i1 %_0.i3.i to i8 + %spec.select5 = add nuw i8 %iter.sroa.0.07, %_0.i4.i + %_0.i.not.i = icmp ule i8 %spec.select5, %n + %or.cond.not = select i1 %_0.i3.i, i1 %_0.i.not.i, i1 false + br i1 %or.cond.not, label %bb2.i, label %theend + +theend: + ret void +} + +define i1 @ule_ule_negative(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ule_ule_negative( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ule i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ule i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nuw i8 %x, %z + %c2 = icmp ule i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @ugt_ugt_negative(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ugt_ugt_negative( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp ugt i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ugt i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nuw i8 %x, %z + %c2 = icmp ugt i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @ugt_sext_sub_uge_negative(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ugt_sext_sub_uge_negative( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z_NEG:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Z_NEG]] +; CHECK-NEXT: [[C2:%.*]] = icmp uge i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ugt i8 %x, %y + %z = sext i1 %c1 to i8 + %add = sub nuw i8 %x, %z + %c2 = icmp uge i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @false_value_is_true_negative(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @false_value_is_true_negative( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp uge i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[NOT_C1:%.*]] = xor i1 [[C1]], true +; CHECK-NEXT: [[AND:%.*]] = select i1 [[NOT_C1]], i1 true, i1 [[C2]] +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ugt i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nuw i8 %x, %z + %c2 = icmp uge i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 true + ret i1 %and +} + +define i1 @non_specific_operands_negative(i8 %x, i8 %y, i8 %a, i8 %b) { +; CHECK-LABEL: define i1 @non_specific_operands_negative( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[A]], [[B]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ult i8 %a, %b + %z = zext i1 %c1 to i8 + %add = add nuw i8 %x, %z + %c2 = icmp ule i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @sgt_nuw_sge_negative(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @sgt_nuw_sge_negative( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp sge i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp sgt i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nuw i8 %x, %z + %c2 = icmp sge i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @ugt_nsw_uge_negative(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ugt_nsw_uge_negative( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp uge i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ugt i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nsw i8 %x, %z + %c2 = icmp uge i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @non_strict_predicate_negative(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @non_strict_predicate_negative( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp uge i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp eq i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add nsw i8 %x, %z + %c2 = icmp uge i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @ugt_uge_no_flags_negative(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @ugt_uge_no_flags_negative( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp uge i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp ugt i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add i8 %x, %z + %c2 = icmp uge i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} + +define i1 @sgt_sge_no_flags_negative(i8 %x, i8 %y) { +; CHECK-LABEL: define i1 @sgt_sge_no_flags_negative( +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[X]], [[Y]] +; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Z]] +; CHECK-NEXT: [[C2:%.*]] = icmp sge i8 [[ADD]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %c1 = icmp sgt i8 %x, %y + %z = zext i1 %c1 to i8 + %add = add i8 %x, %z + %c2 = icmp sge i8 %add, %y + %and = select i1 %c1, i1 %c2, i1 false + ret i1 %and +} From a005baabf62246d6437569940d790b72e4962f28 Mon Sep 17 00:00:00 2001 From: Veera Date: Wed, 4 Dec 2024 02:19:39 +0000 Subject: [PATCH 2/2] Fold `X < Y ? (X + zext(X < Y)) <= Y : false` to `X < Y` --- llvm/lib/Analysis/InstructionSimplify.cpp | 42 ++++++++++ .../InstSimplify/select-icmp-relational.ll | 77 ++++--------------- 2 files changed, 56 insertions(+), 63 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 01b0a089aab71..8e4731651ea59 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4639,6 +4639,45 @@ static Value *simplifySelectWithEquivalence(Value *CmpLHS, Value *CmpRHS, return nullptr; } +/// Simplifies: +/// `X > Y ? (X + zext(X > Y)) >= Y : false` to `X > Y` +/// `X < Y ? (X + zext(X < Y)) <= Y : false` to `X < Y` +static Value *simplifySelectWithStrictICmp(Value *CondVal, Value *TVal, + Value *FVal, + const SimplifyQuery &Q) { + if (!match(FVal, m_Zero())) + return nullptr; + + ICmpInst::Predicate Pred; + Value *CmpLHS, *CmpRHS; + + if (!match(CondVal, m_ICmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS)))) + return nullptr; + + if (!CmpInst::isStrictPredicate(Pred)) + return nullptr; + + ICmpInst::Predicate NonStrictPred = ICmpInst::getNonStrictPredicate(Pred); + BinaryOperator *BinOp; + + if (!match(TVal, + m_SpecificICmp(NonStrictPred, m_BinOp(BinOp), m_Specific(CmpRHS)))) + return nullptr; + + // This fold works for GT only when it does not wrap. + if (Pred == ICmpInst::ICMP_UGT && !Q.IIQ.hasNoUnsignedWrap(BinOp)) + return nullptr; + + if (Pred == ICmpInst::ICMP_SGT && !Q.IIQ.hasNoSignedWrap(BinOp)) + return nullptr; + + if (!match(BinOp, m_c_BinOp(Instruction::Add, m_Specific(CmpLHS), + m_ZExt(m_Specific(CondVal))))) + return nullptr; + + return CondVal; +} + /// Try to simplify a select instruction when its condition operand is an /// integer comparison. static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal, @@ -4761,6 +4800,9 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal, } } + if (Value *V = simplifySelectWithStrictICmp(CondVal, TrueVal, FalseVal, Q)) + return V; + return nullptr; } diff --git a/llvm/test/Transforms/InstSimplify/select-icmp-relational.ll b/llvm/test/Transforms/InstSimplify/select-icmp-relational.ll index 2ec80878e4e9b..c2f120469c6b5 100644 --- a/llvm/test/Transforms/InstSimplify/select-icmp-relational.ll +++ b/llvm/test/Transforms/InstSimplify/select-icmp-relational.ll @@ -5,11 +5,7 @@ define i1 @ult_ule(i8 %x, i8 %y) { ; CHECK-LABEL: define i1 @ult_ule( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { ; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], [[Y]] -; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 -; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] -; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: ret i1 [[C1]] ; %c1 = icmp ult i8 %x, %y %z = zext i1 %c1 to i8 @@ -23,11 +19,7 @@ define i1 @ult_ule_no_flags(i8 %x, i8 %y) { ; CHECK-LABEL: define i1 @ult_ule_no_flags( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { ; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], [[Y]] -; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Z]] -; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: ret i1 [[C1]] ; %c1 = icmp ult i8 %x, %y %z = zext i1 %c1 to i8 @@ -41,11 +33,7 @@ define i1 @slt_sle(i8 %x, i8 %y) { ; CHECK-LABEL: define i1 @slt_sle( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { ; CHECK-NEXT: [[C1:%.*]] = icmp slt i8 [[X]], [[Y]] -; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 -; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X]], [[Z]] -; CHECK-NEXT: [[C2:%.*]] = icmp sle i8 [[ADD]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: ret i1 [[C1]] ; %c1 = icmp slt i8 %x, %y %z = zext i1 %c1 to i8 @@ -59,11 +47,7 @@ define i1 @slt_sle_no_flags(i8 %x, i8 %y) { ; CHECK-LABEL: define i1 @slt_sle_no_flags( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { ; CHECK-NEXT: [[C1:%.*]] = icmp slt i8 [[X]], [[Y]] -; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Z]] -; CHECK-NEXT: [[C2:%.*]] = icmp sle i8 [[ADD]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: ret i1 [[C1]] ; %c1 = icmp slt i8 %x, %y %z = zext i1 %c1 to i8 @@ -77,11 +61,7 @@ define i1 @ugt_uge(i8 %x, i8 %y) { ; CHECK-LABEL: define i1 @ugt_uge( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { ; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], [[Y]] -; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 -; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] -; CHECK-NEXT: [[C2:%.*]] = icmp uge i8 [[ADD]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: ret i1 [[C1]] ; %c1 = icmp ugt i8 %x, %y %z = zext i1 %c1 to i8 @@ -95,11 +75,7 @@ define i1 @sgt_sge(i8 %x, i8 %y) { ; CHECK-LABEL: define i1 @sgt_sge( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { ; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[X]], [[Y]] -; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 -; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X]], [[Z]] -; CHECK-NEXT: [[C2:%.*]] = icmp sge i8 [[ADD]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: ret i1 [[C1]] ; %c1 = icmp sgt i8 %x, %y %z = zext i1 %c1 to i8 @@ -113,11 +89,7 @@ define <2 x i1> @ult_ule_splat_vector(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: define <2 x i1> @ult_ule_splat_vector( ; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { ; CHECK-NEXT: [[C1:%.*]] = icmp ult <2 x i8> [[X]], [[Y]] -; CHECK-NEXT: [[Z:%.*]] = zext <2 x i1> [[C1]] to <2 x i8> -; CHECK-NEXT: [[ADD:%.*]] = add nuw <2 x i8> [[X]], [[Z]] -; CHECK-NEXT: [[C2:%.*]] = icmp ule <2 x i8> [[ADD]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = select <2 x i1> [[C1]], <2 x i1> [[C2]], <2 x i1> zeroinitializer -; CHECK-NEXT: ret <2 x i1> [[AND]] +; CHECK-NEXT: ret <2 x i1> [[C1]] ; %c1 = icmp ult <2 x i8> %x, %y %z = zext <2 x i1> %c1 to <2 x i8> @@ -131,11 +103,7 @@ define <2 x i1> @ult_ule_vector_with_poison(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: define <2 x i1> @ult_ule_vector_with_poison( ; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { ; CHECK-NEXT: [[C1:%.*]] = icmp ult <2 x i8> [[X]], [[Y]] -; CHECK-NEXT: [[Z:%.*]] = zext <2 x i1> [[C1]] to <2 x i8> -; CHECK-NEXT: [[ADD:%.*]] = add nuw <2 x i8> [[X]], [[Z]] -; CHECK-NEXT: [[C2:%.*]] = icmp ule <2 x i8> [[ADD]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = select <2 x i1> [[C1]], <2 x i1> [[C2]], <2 x i1> -; CHECK-NEXT: ret <2 x i1> [[AND]] +; CHECK-NEXT: ret <2 x i1> [[C1]] ; %c1 = icmp ult <2 x i8> %x, %y %z = zext <2 x i1> %c1 to <2 x i8> @@ -170,8 +138,7 @@ define i1 @ult_ule_multi_use(i8 %x, i8 %y) { ; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] ; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] ; CHECK-NEXT: call void @use_bit(i1 [[C2]]) -; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: ret i1 [[C1]] ; %c1 = icmp ult i8 %x, %y call void @use_bit(i1 %c1) @@ -190,9 +157,7 @@ define i1 @ult_ule_multi_use_add(i8 %x, i8 %y) { ; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 ; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] ; CHECK-NEXT: call void @use(i8 [[ADD]]) -; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: ret i1 [[C1]] ; %c1 = icmp ult i8 %x, %y %z = zext i1 %c1 to i8 @@ -207,11 +172,7 @@ define i1 @ult_ule_commuted_binop(i8 %x, i8 %y) { ; CHECK-LABEL: define i1 @ult_ule_commuted_binop( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { ; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], [[Y]] -; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 -; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] -; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: ret i1 [[C1]] ; %c1 = icmp ult i8 %x, %y %z = zext i1 %c1 to i8 @@ -225,11 +186,7 @@ define i1 @ult_sext_sub_ule(i8 %x, i8 %y) { ; CHECK-LABEL: define i1 @ult_sext_sub_ule( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { ; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], [[Y]] -; CHECK-NEXT: [[Z_NEG:%.*]] = zext i1 [[C1]] to i8 -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Z_NEG]] -; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: ret i1 [[C1]] ; %c1 = icmp ult i8 %x, %y %z = sext i1 %c1 to i8 @@ -243,11 +200,7 @@ define i1 @ugt_uge_const_fold_false(i8 %x, i8 %y) { ; CHECK-LABEL: define i1 @ugt_uge_const_fold_false( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { ; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], [[Y]] -; CHECK-NEXT: [[Z:%.*]] = zext i1 [[C1]] to i8 -; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X]], [[Z]] -; CHECK-NEXT: [[C2:%.*]] = icmp uge i8 [[ADD]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: ret i1 [[C1]] ; %c1 = icmp ugt i8 %x, %y %z = zext i1 %c1 to i8 @@ -268,9 +221,7 @@ define void @rust_inlclusive_noop(i8 noundef %n) unnamed_addr { ; CHECK-NEXT: [[_0_I3_I:%.*]] = icmp ult i8 [[ITER_SROA_0_07]], [[N]] ; CHECK-NEXT: [[_0_I4_I:%.*]] = zext i1 [[_0_I3_I]] to i8 ; CHECK-NEXT: [[SPEC_SELECT5]] = add nuw i8 [[ITER_SROA_0_07]], [[_0_I4_I]] -; CHECK-NEXT: [[_0_I_NOT_I:%.*]] = icmp ule i8 [[SPEC_SELECT5]], [[N]] -; CHECK-NEXT: [[OR_COND_NOT:%.*]] = select i1 [[_0_I3_I]], i1 [[_0_I_NOT_I]], i1 false -; CHECK-NEXT: br i1 [[OR_COND_NOT]], label %[[BB2_I]], label %[[THEEND:.*]] +; CHECK-NEXT: br i1 [[_0_I3_I]], label %[[BB2_I]], label %[[THEEND:.*]] ; CHECK: [[THEEND]]: ; CHECK-NEXT: ret void ;