Index: llvm/test/Transforms/InstCombine/and-or-icmps.ll =================================================================== --- llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -2682,3 +2682,381 @@ ret <2 x i64> %E } + +define i32 @icmp_slt_0_and_icmp_sge_neg1_i32(i32 %x) { +; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg1_i32( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -1 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 +; CHECK-NEXT: [[D:%.*]] = and i32 [[C]], [[B]] +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp sgt i32 %x, -1 + %B = zext i1 %A to i32 + %C = lshr i32 %x, 31 + %D = and i32 %C, %B + ret i32 %D +} + +define i32 @icmp_slt_0_or_icmp_sge_neg1_i32(i32 %x) { +; CHECK-LABEL: @icmp_slt_0_or_icmp_sge_neg1_i32( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -2 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 +; CHECK-NEXT: [[D:%.*]] = or i32 [[C]], [[B]] +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp sge i32 %x, -1 + %B = zext i1 %A to i32 + %C = lshr i32 %x, 31 + %D = or i32 %C, %B + ret i32 %D +} + +define i32 @icmp_slt_0_or_icmp_sge_100_i32(i32 %x) { +; CHECK-LABEL: @icmp_slt_0_or_icmp_sge_100_i32( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], 99 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 +; CHECK-NEXT: [[D:%.*]] = or i32 [[C]], [[B]] +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp sge i32 %x, 100 + %B = zext i1 %A to i32 + %C = lshr i32 %x, 31 + %D = or i32 %C, %B + ret i32 %D +} + +define i64 @icmp_slt_0_and_icmp_sge_neg1_i64(i64 %x) { +; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg1_i64( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i64 [[X:%.*]], -2 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i64 +; CHECK-NEXT: [[C:%.*]] = lshr i64 [[X]], 63 +; CHECK-NEXT: [[D:%.*]] = and i64 [[C]], [[B]] +; CHECK-NEXT: ret i64 [[D]] +; + %A = icmp sge i64 %x, -1 + %B = zext i1 %A to i64 + %C = lshr i64 %x, 63 + %D = and i64 %C, %B + ret i64 %D +} + +define i64 @icmp_slt_0_and_icmp_sge_neg2_i64(i64 %x) { +; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg2_i64( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i64 [[X:%.*]], -3 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i64 +; CHECK-NEXT: [[C:%.*]] = lshr i64 [[X]], 63 +; CHECK-NEXT: [[D:%.*]] = and i64 [[C]], [[B]] +; CHECK-NEXT: ret i64 [[D]] +; + %A = icmp sge i64 %x, -2 + %B = zext i1 %A to i64 + %C = lshr i64 %x, 63 + %D = and i64 %C, %B + ret i64 %D +} + +define i64 @ashr_and_icmp_sge_neg1_i64(i64 %x) { +; CHECK-LABEL: @ashr_and_icmp_sge_neg1_i64( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i64 [[X:%.*]], -2 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i64 +; CHECK-NEXT: [[C1:%.*]] = lshr i64 [[X]], 63 +; CHECK-NEXT: [[D:%.*]] = and i64 [[C1]], [[B]] +; CHECK-NEXT: ret i64 [[D]] +; + %A = icmp sge i64 %x, -1 + %B = zext i1 %A to i64 + %C = ashr i64 %x, 63 + %D = and i64 %C, %B + ret i64 %D +} + +define i64 @icmp_slt_0_and_icmp_sgt_neg1_i64(i64 %x) { +; CHECK-LABEL: @icmp_slt_0_and_icmp_sgt_neg1_i64( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i64 [[X:%.*]], -1 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i64 +; CHECK-NEXT: [[C:%.*]] = lshr i64 [[X]], 63 +; CHECK-NEXT: [[D:%.*]] = and i64 [[C]], [[B]] +; CHECK-NEXT: ret i64 [[D]] +; + %A = icmp sgt i64 %x, -1 + %B = zext i1 %A to i64 + %C = lshr i64 %x, 63 + %D = and i64 %C, %B + ret i64 %D +} + +define i64 @icmp_slt_0_and_icmp_sge_neg1_i64_fail(i64 %x) { +; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg1_i64_fail( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i64 [[X:%.*]], -2 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i64 +; CHECK-NEXT: [[C:%.*]] = lshr i64 [[X]], 62 +; CHECK-NEXT: [[D:%.*]] = and i64 [[C]], [[B]] +; CHECK-NEXT: ret i64 [[D]] +; + %A = icmp sge i64 %x, -1 + %B = zext i1 %A to i64 + %C = lshr i64 %x, 62 + %D = and i64 %C, %B + ret i64 %D +} + +define <2 x i32> @icmp_slt_0_and_icmp_sge_neg1_i32x2(<2 x i32> %x) { +; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg1_i32x2( +; CHECK-NEXT: [[A:%.*]] = icmp sgt <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[B:%.*]] = zext <2 x i1> [[A]] to <2 x i32> +; CHECK-NEXT: [[C:%.*]] = lshr <2 x i32> [[X]], +; CHECK-NEXT: [[D:%.*]] = and <2 x i32> [[C]], [[B]] +; CHECK-NEXT: ret <2 x i32> [[D]] +; + %A = icmp sge <2 x i32> %x, + %B = zext <2 x i1> %A to <2 x i32> + %C = lshr <2 x i32> %x, + %D = and <2 x i32> %C, %B + ret <2 x i32> %D +} + +define <2 x i32> @icmp_slt_0_and_icmp_sge_neg2_i32x2(<2 x i32> %x) { +; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg2_i32x2( +; CHECK-NEXT: [[A:%.*]] = icmp sgt <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[B:%.*]] = zext <2 x i1> [[A]] to <2 x i32> +; CHECK-NEXT: [[C:%.*]] = lshr <2 x i32> [[X]], +; CHECK-NEXT: [[D:%.*]] = and <2 x i32> [[C]], [[B]] +; CHECK-NEXT: ret <2 x i32> [[D]] +; + %A = icmp sge <2 x i32> %x, + %B = zext <2 x i1> %A to <2 x i32> + %C = lshr <2 x i32> %x, + %D = and <2 x i32> %C, %B + ret <2 x i32> %D +} + +define i32 @icmp_x_slt_0_xor_icmp_y_sgt_neg1_i32(i32 %x, i32 %y) { +; CHECK-LABEL: @icmp_x_slt_0_xor_icmp_y_sgt_neg1_i32( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -1 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[Y:%.*]], 31 +; CHECK-NEXT: [[D:%.*]] = xor i32 [[C]], [[B]] +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp sgt i32 %x, -1 + %B = zext i1 %A to i32 + %C = lshr i32 %y, 31 + %D = xor i32 %C, %B + ret i32 %D +} + +define i32 @icmp_slt_0_and_icmp_sge_neg1_i32_multiuse0(i32 %x) { +; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg1_i32_multiuse0( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -3 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 +; CHECK-NEXT: [[D:%.*]] = and i32 [[C]], [[B]] +; CHECK-NEXT: call void @use(i1 [[A]]) +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp sge i32 %x, -2 + %B = zext i1 %A to i32 + %C = lshr i32 %x, 31 + %D = and i32 %C, %B + call void @use(i1 %A) + ret i32 %D +} + +define i32 @icmp_slt_0_and_icmp_sge_neg2_i32_multiuse1(i32 %x) { +; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg2_i32_multiuse1( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -3 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 +; CHECK-NEXT: [[D:%.*]] = and i32 [[C]], [[B]] +; CHECK-NEXT: call void @use32(i32 [[B]]) +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp sge i32 %x, -2 + %B = zext i1 %A to i32 + %C = lshr i32 %x, 31 + %D = and i32 %C, %B + call void @use32(i32 %B) + ret i32 %D +} + +define i32 @icmp_slt_0_and_icmp_sge_neg2_i32_multiuse2(i32 %x) { +; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg2_i32_multiuse2( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -3 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 +; CHECK-NEXT: [[D:%.*]] = and i32 [[C]], [[B]] +; CHECK-NEXT: call void @use32(i32 [[C]]) +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp sge i32 %x, -2 + %B = zext i1 %A to i32 + %C = lshr i32 %x, 31 + %D = and i32 %C, %B + call void @use32(i32 %C) + ret i32 %D +} + +define i32 @icmp_slt_0_and_icmp_sge_neg2_i32_multiuse_fail0(i32 %x) { +; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg2_i32_multiuse_fail0( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -3 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 +; CHECK-NEXT: [[D:%.*]] = and i32 [[C]], [[B]] +; CHECK-NEXT: call void @use32(i32 [[B]]) +; CHECK-NEXT: call void @use32(i32 [[C]]) +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp sge i32 %x, -2 + %B = zext i1 %A to i32 + %C = lshr i32 %x, 31 + %D = and i32 %C, %B + call void @use32(i32 %B) + call void @use32(i32 %C) + ret i32 %D +} + +define i32 @icmp_slt_0_or_icmp_eq_100_i32_multiuse_fail1(i32 %x) { +; CHECK-LABEL: @icmp_slt_0_or_icmp_eq_100_i32_multiuse_fail1( +; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 100 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 +; CHECK-NEXT: [[D:%.*]] = or i32 [[C]], [[B]] +; CHECK-NEXT: call void @use32(i32 [[C]]) +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp eq i32 %x, 100 + %B = zext i1 %A to i32 + %C = lshr i32 %x, 31 + %D = or i32 %C, %B + call void @use32(i32 %C) + ret i32 %D +} + +define i32 @icmp_x_slt_0_and_icmp_y_ne_neg2_i32_multiuse_fail2(i32 %x, i32 %y) { +; CHECK-LABEL: @icmp_x_slt_0_and_icmp_y_ne_neg2_i32_multiuse_fail2( +; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[X:%.*]], -2 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[Y:%.*]], 31 +; CHECK-NEXT: [[D:%.*]] = and i32 [[C]], [[B]] +; CHECK-NEXT: call void @use32(i32 [[C]]) +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp ne i32 %x, -2 + %B = zext i1 %A to i32 + %C = lshr i32 %y, 31 + %D = and i32 %C, %B + call void @use32(i32 %C) + ret i32 %D +} + +define i32 @icmp_slt_0_or_icmp_eq_100_i32_multiuse_fail3(i32 %x) { +; CHECK-LABEL: @icmp_slt_0_or_icmp_eq_100_i32_multiuse_fail3( +; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 100 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 +; CHECK-NEXT: [[D:%.*]] = or i32 [[C]], [[B]] +; CHECK-NEXT: call void @use32(i32 [[B]]) +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp eq i32 %x, 100 + %B = zext i1 %A to i32 + %C = lshr i32 %x, 31 + %D = or i32 %C, %B + call void @use32(i32 %B) + ret i32 %D +} + +define i32 @icmp_slt_0_or_icmp_eq_100_i32_fail(i32 %x) { +; CHECK-LABEL: @icmp_slt_0_or_icmp_eq_100_i32_fail( +; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 100 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 +; CHECK-NEXT: [[D:%.*]] = or i32 [[C]], [[B]] +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp eq i32 %x, 100 + %B = zext i1 %A to i32 + %C = lshr i32 %x, 31 + %D = or i32 %C, %B + ret i32 %D +} + +define i32 @icmp_slt_0_and_icmp_ne_neg2_i32_fail(i32 %x) { +; CHECK-LABEL: @icmp_slt_0_and_icmp_ne_neg2_i32_fail( +; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[X:%.*]], -2 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 +; CHECK-NEXT: [[D:%.*]] = and i32 [[C]], [[B]] +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp ne i32 %x, -2 + %B = zext i1 %A to i32 + %C = lshr i32 %x, 31 + %D = and i32 %C, %B + ret i32 %D +} + +define i32 @icmp_x_slt_0_and_icmp_y_ne_neg2_i32_fail(i32 %x, i32 %y) { +; CHECK-LABEL: @icmp_x_slt_0_and_icmp_y_ne_neg2_i32_fail( +; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[X:%.*]], -2 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[Y:%.*]], 31 +; CHECK-NEXT: [[D:%.*]] = and i32 [[C]], [[B]] +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp ne i32 %x, -2 + %B = zext i1 %A to i32 + %C = lshr i32 %y, 31 + %D = and i32 %C, %B + ret i32 %D +} + +define i32 @icmp_x_slt_0_and_icmp_y_sgt_neg1_i32_fail(i32 %x, i32 %y) { +; CHECK-LABEL: @icmp_x_slt_0_and_icmp_y_sgt_neg1_i32_fail( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -1 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[Y:%.*]], 31 +; CHECK-NEXT: [[D:%.*]] = and i32 [[C]], [[B]] +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp sgt i32 %x, -1 + %B = zext i1 %A to i32 + %C = lshr i32 %y, 31 + %D = and i32 %C, %B + ret i32 %D +} + +define i32 @icmp_slt_0_xor_icmp_sge_neg2_i32_fail(i32 %x) { +; CHECK-LABEL: @icmp_slt_0_xor_icmp_sge_neg2_i32_fail( +; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -3 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 +; CHECK-NEXT: [[D:%.*]] = xor i32 [[C]], [[B]] +; CHECK-NEXT: ret i32 [[D]] +; + %A = icmp sge i32 %x, -2 + %B = zext i1 %A to i32 + %C = lshr i32 %x, 31 + %D = xor i32 %C, %B + ret i32 %D +} + +define i32 @icmp_slt_0_or_icmp_add_1_sge_100_i32_fail(i32 %x) { +; CHECK-LABEL: @icmp_slt_0_or_icmp_add_1_sge_100_i32_fail( +; CHECK-NEXT: [[X1:%.*]] = add i32 [[X:%.*]], 1 +; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X1]], 99 +; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 +; CHECK-NEXT: [[D:%.*]] = or i32 [[C]], [[B]] +; CHECK-NEXT: ret i32 [[D]] +; + %X1 = add i32 %x, 1 + %A = icmp sge i32 %X1, 100 + %B = zext i1 %A to i32 + %C = lshr i32 %x, 31 + %D = or i32 %C, %B + ret i32 %D +}