Index: llvm/trunk/test/Transforms/InstCombine/select-of-bittest.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/select-of-bittest.ll +++ llvm/trunk/test/Transforms/InstCombine/select-of-bittest.ll @@ -0,0 +1,464 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +; https://bugs.llvm.org/show_bug.cgi?id=36950 + +; These all should be just and+icmp, there should be no select. +; https://rise4fun.com/Alive/uiH + +define i32 @and_lshr_and(i32) { +; CHECK-LABEL: @and_lshr_and( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 1 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 [[TMP0]], 1 +; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP3]], i32 [[TMP5]], i32 1 +; CHECK-NEXT: ret i32 [[TMP6]] +; + %2 = and i32 %0, 1 + %3 = icmp eq i32 %2, 0 + %4 = lshr i32 %0, 1 + %5 = and i32 %4, 1 + %6 = select i1 %3, i32 %5, i32 1 + ret i32 %6 +} + +define <2 x i32> @and_lshr_and_splatvec(<2 x i32>) { +; CHECK-LABEL: @and_lshr_and_splatvec( +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <2 x i32> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = lshr <2 x i32> [[TMP0]], +; CHECK-NEXT: [[TMP5:%.*]] = and <2 x i32> [[TMP4]], +; CHECK-NEXT: [[TMP6:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[TMP5]], <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[TMP6]] +; + %2 = and <2 x i32> %0, + %3 = icmp eq <2 x i32> %2, + %4 = lshr <2 x i32> %0, + %5 = and <2 x i32> %4, + %6 = select <2 x i1> %3, <2 x i32> %5, <2 x i32> + ret <2 x i32> %6 +} + +define <2 x i32> @and_lshr_and_vec_v0(<2 x i32>) { +; CHECK-LABEL: @and_lshr_and_vec_v0( +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <2 x i32> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = lshr <2 x i32> [[TMP0]], +; CHECK-NEXT: [[TMP5:%.*]] = and <2 x i32> [[TMP4]], +; CHECK-NEXT: [[TMP6:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[TMP5]], <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[TMP6]] +; + %2 = and <2 x i32> %0, ; mask is not splat + %3 = icmp eq <2 x i32> %2, + %4 = lshr <2 x i32> %0, + %5 = and <2 x i32> %4, + %6 = select <2 x i1> %3, <2 x i32> %5, <2 x i32> + ret <2 x i32> %6 +} + +define <2 x i32> @and_lshr_and_vec_v1(<2 x i32>) { +; CHECK-LABEL: @and_lshr_and_vec_v1( +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <2 x i32> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = lshr <2 x i32> [[TMP0]], +; CHECK-NEXT: [[TMP5:%.*]] = and <2 x i32> [[TMP4]], +; CHECK-NEXT: [[TMP6:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[TMP5]], <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[TMP6]] +; + %2 = and <2 x i32> %0, + %3 = icmp eq <2 x i32> %2, + %4 = lshr <2 x i32> %0, ; shift is not splat + %5 = and <2 x i32> %4, + %6 = select <2 x i1> %3, <2 x i32> %5, <2 x i32> + ret <2 x i32> %6 +} + +define <2 x i32> @and_lshr_and_vec_v2(<2 x i32>) { +; CHECK-LABEL: @and_lshr_and_vec_v2( +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <2 x i32> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = lshr <2 x i32> [[TMP0]], +; CHECK-NEXT: [[TMP5:%.*]] = and <2 x i32> [[TMP4]], +; CHECK-NEXT: [[TMP6:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[TMP5]], <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[TMP6]] +; + %2 = and <2 x i32> %0, ; mask is not splat + %3 = icmp eq <2 x i32> %2, + %4 = lshr <2 x i32> %0, ; shift is not splat + %5 = and <2 x i32> %4, + %6 = select <2 x i1> %3, <2 x i32> %5, <2 x i32> + ret <2 x i32> %6 +} + +define <3 x i32> @and_lshr_and_vec_undef(<3 x i32>) { +; CHECK-LABEL: @and_lshr_and_vec_undef( +; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <3 x i32> [[TMP2]], +; CHECK-NEXT: [[TMP4:%.*]] = lshr <3 x i32> [[TMP0]], +; CHECK-NEXT: [[TMP5:%.*]] = and <3 x i32> [[TMP4]], +; CHECK-NEXT: [[TMP6:%.*]] = select <3 x i1> [[TMP3]], <3 x i32> [[TMP5]], <3 x i32> +; CHECK-NEXT: ret <3 x i32> [[TMP6]] +; + %2 = and <3 x i32> %0, + %3 = icmp eq <3 x i32> %2, + %4 = lshr <3 x i32> %0, + %5 = and <3 x i32> %4, + %6 = select <3 x i1> %3, <3 x i32> %5, <3 x i32> + ret <3 x i32> %6 +} + +define i32 @and_and(i32) { +; CHECK-LABEL: @and_and( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 2 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP0]], 1 +; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], i32 [[TMP4]], i32 1 +; CHECK-NEXT: ret i32 [[TMP5]] +; + %2 = and i32 %0, 2 + %3 = icmp eq i32 %2, 0 + %4 = and i32 %0, 1 + %5 = select i1 %3, i32 %4, i32 1 + ret i32 %5 +} + +define <2 x i32> @and_and_splatvec(<2 x i32>) { +; CHECK-LABEL: @and_and_splatvec( +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <2 x i32> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = and <2 x i32> [[TMP0]], +; CHECK-NEXT: [[TMP5:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[TMP5]] +; + %2 = and <2 x i32> %0, + %3 = icmp eq <2 x i32> %2, + %4 = and <2 x i32> %0, + %5 = select <2 x i1> %3, <2 x i32> %4, <2 x i32> + ret <2 x i32> %5 +} + +define <2 x i32> @and_and_vec(<2 x i32>) { +; CHECK-LABEL: @and_and_vec( +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <2 x i32> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = and <2 x i32> [[TMP0]], +; CHECK-NEXT: [[TMP5:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[TMP5]] +; + %2 = and <2 x i32> %0, ; mask is not splat + %3 = icmp eq <2 x i32> %2, + %4 = and <2 x i32> %0, + %5 = select <2 x i1> %3, <2 x i32> %4, <2 x i32> + ret <2 x i32> %5 +} + +define <3 x i32> @and_and_vec_undef(<3 x i32>) { +; CHECK-LABEL: @and_and_vec_undef( +; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <3 x i32> [[TMP2]], +; CHECK-NEXT: [[TMP4:%.*]] = and <3 x i32> [[TMP0]], +; CHECK-NEXT: [[TMP5:%.*]] = select <3 x i1> [[TMP3]], <3 x i32> [[TMP4]], <3 x i32> +; CHECK-NEXT: ret <3 x i32> [[TMP5]] +; + %2 = and <3 x i32> %0, + %3 = icmp eq <3 x i32> %2, + %4 = and <3 x i32> %0, + %5 = select <3 x i1> %3, <3 x i32> %4, <3 x i32> + ret <3 x i32> %5 +} + +; ============================================================================ ; +; Mask can be a variable, too. +; ============================================================================ ; + +define i32 @f_var0(i32, i32) { +; CHECK-LABEL: @f_var0( +; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0:%.*]], [[TMP1:%.*]] +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = lshr i32 [[TMP0]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], 1 +; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP4]], i32 [[TMP6]], i32 1 +; CHECK-NEXT: ret i32 [[TMP7]] +; + %3 = and i32 %0, %1 + %4 = icmp eq i32 %3, 0 + %5 = lshr i32 %0, 1 + %6 = and i32 %5, 1 + %7 = select i1 %4, i32 %6, i32 1 + ret i32 %7 +} + +define <2 x i32> @f_var0_splatvec(<2 x i32>, <2 x i32>) { +; CHECK-LABEL: @f_var0_splatvec( +; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i32> [[TMP0:%.*]], [[TMP1:%.*]] +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq <2 x i32> [[TMP3]], zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = lshr <2 x i32> [[TMP0]], +; CHECK-NEXT: [[TMP6:%.*]] = and <2 x i32> [[TMP5]], +; CHECK-NEXT: [[TMP7:%.*]] = select <2 x i1> [[TMP4]], <2 x i32> [[TMP6]], <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[TMP7]] +; + %3 = and <2 x i32> %0, %1 + %4 = icmp eq <2 x i32> %3, + %5 = lshr <2 x i32> %0, + %6 = and <2 x i32> %5, + %7 = select <2 x i1> %4, <2 x i32> %6, <2 x i32> + ret <2 x i32> %7 +} + +define <2 x i32> @f_var0_vec(<2 x i32>, <2 x i32>) { +; CHECK-LABEL: @f_var0_vec( +; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i32> [[TMP0:%.*]], [[TMP1:%.*]] +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq <2 x i32> [[TMP3]], zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = lshr <2 x i32> [[TMP0]], +; CHECK-NEXT: [[TMP6:%.*]] = and <2 x i32> [[TMP5]], +; CHECK-NEXT: [[TMP7:%.*]] = select <2 x i1> [[TMP4]], <2 x i32> [[TMP6]], <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[TMP7]] +; + %3 = and <2 x i32> %0, %1 + %4 = icmp eq <2 x i32> %3, + %5 = lshr <2 x i32> %0, ; shift is not splat + %6 = and <2 x i32> %5, + %7 = select <2 x i1> %4, <2 x i32> %6, <2 x i32> + ret <2 x i32> %7 +} + +define <3 x i32> @f_var0_vec_undef(<3 x i32>, <3 x i32>) { +; CHECK-LABEL: @f_var0_vec_undef( +; CHECK-NEXT: [[TMP3:%.*]] = and <3 x i32> [[TMP0:%.*]], [[TMP1:%.*]] +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq <3 x i32> [[TMP3]], +; CHECK-NEXT: [[TMP5:%.*]] = lshr <3 x i32> [[TMP0]], +; CHECK-NEXT: [[TMP6:%.*]] = and <3 x i32> [[TMP5]], +; CHECK-NEXT: [[TMP7:%.*]] = select <3 x i1> [[TMP4]], <3 x i32> [[TMP6]], <3 x i32> +; CHECK-NEXT: ret <3 x i32> [[TMP7]] +; + %3 = and <3 x i32> %0, %1 + %4 = icmp eq <3 x i32> %3, + %5 = lshr <3 x i32> %0, + %6 = and <3 x i32> %5, + %7 = select <3 x i1> %4, <3 x i32> %6, <3 x i32> + ret <3 x i32> %7 +} + +define i32 @f_var1(i32, i32) { +; CHECK-LABEL: @f_var1( +; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0:%.*]], [[TMP1:%.*]] +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP0]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], i32 [[TMP5]], i32 1 +; CHECK-NEXT: ret i32 [[TMP6]] +; + %3 = and i32 %0, %1 + %4 = icmp eq i32 %3, 0 + %5 = and i32 %0, 1 + %6 = select i1 %4, i32 %5, i32 1 + ret i32 %6 +} + +define <2 x i32> @f_var1_vec(<2 x i32>, <2 x i32>) { +; CHECK-LABEL: @f_var1_vec( +; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i32> [[TMP0:%.*]], [[TMP1:%.*]] +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq <2 x i32> [[TMP3]], zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = and <2 x i32> [[TMP0]], +; CHECK-NEXT: [[TMP6:%.*]] = select <2 x i1> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[TMP6]] +; + %3 = and <2 x i32> %0, %1 + %4 = icmp eq <2 x i32> %3, + %5 = and <2 x i32> %0, + %6 = select <2 x i1> %4, <2 x i32> %5, <2 x i32> + ret <2 x i32> %6 +} + +define <3 x i32> @f_var1_vec_undef(<3 x i32>, <3 x i32>) { +; CHECK-LABEL: @f_var1_vec_undef( +; CHECK-NEXT: [[TMP3:%.*]] = and <3 x i32> [[TMP0:%.*]], [[TMP1:%.*]] +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq <3 x i32> [[TMP3]], +; CHECK-NEXT: [[TMP5:%.*]] = and <3 x i32> [[TMP0]], +; CHECK-NEXT: [[TMP6:%.*]] = select <3 x i1> [[TMP4]], <3 x i32> [[TMP5]], <3 x i32> +; CHECK-NEXT: ret <3 x i32> [[TMP6]] +; + %3 = and <3 x i32> %0, %1 + %4 = icmp eq <3 x i32> %3, + %5 = and <3 x i32> %0, + %6 = select <3 x i1> %4, <3 x i32> %5, <3 x i32> + ret <3 x i32> %6 +} + +; ============================================================================ ; +; Negative tests. Should not be folded. +; ============================================================================ ; + +; Different variables are used + +define i32 @n0(i32, i32) { +; CHECK-LABEL: @n0( +; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0:%.*]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = lshr i32 [[TMP1:%.*]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], 1 +; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP4]], i32 [[TMP6]], i32 1 +; CHECK-NEXT: ret i32 [[TMP7]] +; + %3 = and i32 %0, 1 + %4 = icmp eq i32 %3, 0 + %5 = lshr i32 %1, 1 ; works on %1 instead of %0 + %6 = and i32 %5, 1 + %7 = select i1 %4, i32 %6, i32 1 + ret i32 %7 +} + +define i32 @n1(i32, i32) { +; CHECK-LABEL: @n1( +; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0:%.*]], 2 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP1:%.*]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], i32 [[TMP5]], i32 1 +; CHECK-NEXT: ret i32 [[TMP6]] +; + %3 = and i32 %0, 2 + %4 = icmp eq i32 %3, 0 + %5 = and i32 %1, 1 ; works on %1 instead of %0 + %6 = select i1 %4, i32 %5, i32 1 + ret i32 %6 +} + +; False-value is not 1 + +define i32 @n2(i32) { +; CHECK-LABEL: @n2( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 1 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 [[TMP0]], 2 +; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP3]], i32 [[TMP5]], i32 0 +; CHECK-NEXT: ret i32 [[TMP6]] +; + %2 = and i32 %0, 1 + %3 = icmp eq i32 %2, 0 + %4 = lshr i32 %0, 2 + %5 = and i32 %4, 1 + %6 = select i1 %3, i32 %5, i32 0 ; 0 instead of 1 + ret i32 %6 +} + +define i32 @n3(i32) { +; CHECK-LABEL: @n3( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 2 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP0]], 1 +; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], i32 [[TMP4]], i32 0 +; CHECK-NEXT: ret i32 [[TMP5]] +; + %2 = and i32 %0, 2 + %3 = icmp eq i32 %2, 0 + %4 = and i32 %0, 1 + %5 = select i1 %3, i32 %4, i32 0 ; 0 instead of 1 + ret i32 %5 +} + +; Mask of second and is not one + +define i32 @n4(i32) { +; CHECK-LABEL: @n4( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 1 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 [[TMP0]], 2 +; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 2 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP3]], i32 [[TMP5]], i32 1 +; CHECK-NEXT: ret i32 [[TMP6]] +; + %2 = and i32 %0, 1 + %3 = icmp eq i32 %2, 0 + %4 = lshr i32 %0, 2 + %5 = and i32 %4, 2 ; 2 instead of 1 + %6 = select i1 %3, i32 %5, i32 1 + ret i32 %6 +} + +define i32 @n5(i32) { +; CHECK-LABEL: @n5( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 2 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP0]], 2 +; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], i32 [[TMP4]], i32 1 +; CHECK-NEXT: ret i32 [[TMP5]] +; + %2 = and i32 %0, 2 + %3 = icmp eq i32 %2, 0 + %4 = and i32 %0, 2 ; 2 instead of 1 + %5 = select i1 %3, i32 %4, i32 1 + ret i32 %5 +} + +; Wrong icmp pred + +define i32 @n6(i32) { +; CHECK-LABEL: @n6( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 1 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 [[TMP0]], 2 +; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP3]], i32 1, i32 [[TMP5]] +; CHECK-NEXT: ret i32 [[TMP6]] +; + %2 = and i32 %0, 1 + %3 = icmp ne i32 %2, 0 ; ne, not eq + %4 = lshr i32 %0, 2 + %5 = and i32 %4, 1 + %6 = select i1 %3, i32 %5, i32 1 + ret i32 %6 +} + +define i32 @n7(i32) { +; CHECK-LABEL: @n7( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 2 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP0]], 1 +; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], i32 1, i32 [[TMP4]] +; CHECK-NEXT: ret i32 [[TMP5]] +; + %2 = and i32 %0, 2 + %3 = icmp ne i32 %2, 0 ; ne, not eq + %4 = and i32 %0, 1 + %5 = select i1 %3, i32 %4, i32 1 + ret i32 %5 +} + +; icmp second operand is not zero + +define i32 @n8(i32) { +; CHECK-LABEL: @n8( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 1 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 [[TMP0]], 2 +; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP3]], i32 1, i32 [[TMP5]] +; CHECK-NEXT: ret i32 [[TMP6]] +; + %2 = and i32 %0, 1 + %3 = icmp eq i32 %2, 1 ; 1, not 0 + %4 = lshr i32 %0, 2 + %5 = and i32 %4, 1 + %6 = select i1 %3, i32 %5, i32 1 + ret i32 %6 +} + +; Shift not by a constant + +define i32 @n9(i32, i32) { +; CHECK-LABEL: @n9( +; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP0:%.*]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = lshr i32 [[TMP0]], [[TMP1:%.*]] +; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], 1 +; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP4]], i32 [[TMP6]], i32 1 +; CHECK-NEXT: ret i32 [[TMP7]] +; + %3 = and i32 %0, 1 + %4 = icmp eq i32 %3, 0 + %5 = lshr i32 %0, %1 ; %1, should be a constant + %6 = and i32 %5, 1 + %7 = select i1 %4, i32 %6, i32 1 + ret i32 %7 +}