diff --git a/llvm/test/Transforms/InstCombine/select-icmp-and-zero-shl.ll b/llvm/test/Transforms/InstCombine/select-icmp-and-zero-shl.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/select-icmp-and-zero-shl.ll @@ -0,0 +1,188 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +; (x << k) ? 2^k * x : 0 --> 2^k * x + +define i32 @test_eq(i32 %x) { +; CHECK-LABEL: @test_eq( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and i32 [[X:%.*]], 1073741823 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[SHL_MASK]], 0 +; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[X]], 2 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 0, i32 [[MUL]] +; CHECK-NEXT: ret i32 [[COND]] +; + %shl.mask = and i32 %x, 1073741823 + %tobool = icmp eq i32 %shl.mask, 0 + %mul = shl i32 %x, 2 + %cond = select i1 %tobool, i32 0, i32 %mul + ret i32 %cond +} + +define <2 x i32> @test_eq_vect(<2 x i32> %x) { +; CHECK-LABEL: @test_eq_vect( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq <2 x i32> [[SHL_MASK]], zeroinitializer +; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[X]], +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[TOBOOL]], <2 x i32> zeroinitializer, <2 x i32> [[MUL]] +; CHECK-NEXT: ret <2 x i32> [[COND]] +; + %shl.mask = and <2 x i32> %x, + %tobool = icmp eq <2 x i32> %shl.mask, zeroinitializer + %mul = shl <2 x i32> %x, + %cond = select <2 x i1> %tobool, <2 x i32> zeroinitializer, <2 x i32> %mul + ret <2 x i32> %cond +} + +define i32 @test_ne(i32 %x) { +; CHECK-LABEL: @test_ne( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and i32 [[X:%.*]], 1073741823 +; CHECK-NEXT: [[TOBOOL_NOT_NOT:%.*]] = icmp eq i32 [[SHL_MASK]], 0 +; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[X]], 2 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL_NOT_NOT]], i32 0, i32 [[MUL]] +; CHECK-NEXT: ret i32 [[COND]] +; + %shl.mask = and i32 %x, 1073741823 + %tobool.not = icmp ne i32 %shl.mask, 0 + %mul = shl i32 %x, 2 + %cond = select i1 %tobool.not, i32 %mul, i32 0 + ret i32 %cond +} + +define <2 x i32> @test_ne_vect(<2 x i32> %x) { +; CHECK-LABEL: @test_ne_vect( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[TOBOOL_NOT_NOT:%.*]] = icmp eq <2 x i32> [[SHL_MASK]], zeroinitializer +; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[X]], +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[TOBOOL_NOT_NOT]], <2 x i32> zeroinitializer, <2 x i32> [[MUL]] +; CHECK-NEXT: ret <2 x i32> [[COND]] +; + %shl.mask = and <2 x i32> %x, + %tobool.not = icmp ne <2 x i32> %shl.mask, zeroinitializer + %mul = shl <2 x i32> %x, + %cond = select <2 x i1> %tobool.not, <2 x i32> %mul, <2 x i32> zeroinitializer + ret <2 x i32> %cond +} + +define i32 @test_nuw_dropped(i32 %x) { +; CHECK-LABEL: @test_nuw_dropped( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and i32 [[X:%.*]], 1073741823 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[SHL_MASK]], 0 +; CHECK-NEXT: [[MUL:%.*]] = shl nuw i32 [[X]], 2 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 0, i32 [[MUL]] +; CHECK-NEXT: ret i32 [[COND]] +; + %shl.mask = and i32 %x, 1073741823 + %tobool = icmp eq i32 %shl.mask, 0 + %mul = shl nuw i32 %x, 2 + %cond = select i1 %tobool, i32 0, i32 %mul + ret i32 %cond +} + +define i32 @test_nsw_dropped(i32 %x) { +; CHECK-LABEL: @test_nsw_dropped( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and i32 [[X:%.*]], 1073741823 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[SHL_MASK]], 0 +; CHECK-NEXT: [[MUL:%.*]] = shl nsw i32 [[X]], 2 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 0, i32 [[MUL]] +; CHECK-NEXT: ret i32 [[COND]] +; + %shl.mask = and i32 %x, 1073741823 + %tobool = icmp eq i32 %shl.mask, 0 + %mul = shl nsw i32 %x, 2 + %cond = select i1 %tobool, i32 0, i32 %mul + ret i32 %cond +} + +declare void @use_multi(i32, i1, i32) + +; This will not be canonicalized. +define i32 @test_multi_use(i32 %x) { +; CHECK-LABEL: @test_multi_use( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and i32 [[X:%.*]], 1073741823 +; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp ne i32 [[SHL_MASK]], 0 +; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[X]], 2 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL_NOT]], i32 [[MUL]], i32 0 +; CHECK-NEXT: call void @use_multi(i32 [[SHL_MASK]], i1 [[TOBOOL_NOT]], i32 [[MUL]]) +; CHECK-NEXT: ret i32 [[COND]] +; + %shl.mask = and i32 %x, 1073741823 + %tobool.not = icmp ne i32 %shl.mask, 0 + %mul = shl i32 %x, 2 + %cond = select i1 %tobool.not, i32 %mul, i32 0 + call void @use_multi(i32 %shl.mask, i1 %tobool.not, i32 %mul) + ret i32 %cond +} + +define i32 @test_multi_use_nuw_dropped(i32 %x) { +; CHECK-LABEL: @test_multi_use_nuw_dropped( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and i32 [[X:%.*]], 1073741823 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[SHL_MASK]], 0 +; CHECK-NEXT: [[MUL:%.*]] = shl nuw i32 [[X]], 2 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 0, i32 [[MUL]] +; CHECK-NEXT: call void @use_multi(i32 [[SHL_MASK]], i1 [[TOBOOL]], i32 [[MUL]]) +; CHECK-NEXT: ret i32 [[COND]] +; + %shl.mask = and i32 %x, 1073741823 + %tobool = icmp eq i32 %shl.mask, 0 + %mul = shl nuw i32 %x, 2 + %cond = select i1 %tobool, i32 0, i32 %mul + call void @use_multi(i32 %shl.mask, i1 %tobool, i32 %mul) + ret i32 %cond +} + +define i32 @neg_test_bits_not_match(i32 %x) { +; CHECK-LABEL: @neg_test_bits_not_match( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and i32 [[X:%.*]], 1073741823 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[SHL_MASK]], 0 +; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[X]], 3 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 0, i32 [[MUL]] +; CHECK-NEXT: ret i32 [[COND]] +; + %shl.mask = and i32 %x, 1073741823 + %tobool = icmp eq i32 %shl.mask, 0 + %mul = shl i32 %x, 3 + %cond = select i1 %tobool, i32 0, i32 %mul + ret i32 %cond +} + +define i32 @neg_test_icmp_non_equality(i32 %x) { +; CHECK-LABEL: @neg_test_icmp_non_equality( +; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[X:%.*]], 2 +; CHECK-NEXT: ret i32 [[MUL]] +; + %shl.mask = and i32 %x, 1073741823 + %tobool = icmp slt i32 %shl.mask, 0 + %mul = shl i32 %x, 2 + %cond = select i1 %tobool, i32 0, i32 %mul + ret i32 %cond +} + +define i32 @neg_test_select_non_zero_constant(i32 %x) { +; CHECK-LABEL: @neg_test_select_non_zero_constant( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and i32 [[X:%.*]], 1073741823 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[SHL_MASK]], 0 +; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[X]], 2 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 1, i32 [[MUL]] +; CHECK-NEXT: ret i32 [[COND]] +; + %shl.mask = and i32 %x, 1073741823 + %tobool = icmp eq i32 %shl.mask, 0 + %mul = shl i32 %x, 2 + %cond = select i1 %tobool, i32 1, i32 %mul + ret i32 %cond +} + +define i32 @neg_test_icmp_non_zero_constant(i32 %x) { +; CHECK-LABEL: @neg_test_icmp_non_zero_constant( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and i32 [[X:%.*]], 1073741823 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[SHL_MASK]], 1 +; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[X]], 2 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 0, i32 [[MUL]] +; CHECK-NEXT: ret i32 [[COND]] +; + %shl.mask = and i32 %x, 1073741823 + %tobool = icmp eq i32 %shl.mask, 1 + %mul = shl i32 %x, 2 + %cond = select i1 %tobool, i32 0, i32 %mul + ret i32 %cond +} diff --git a/llvm/test/Transforms/InstSimplify/select.ll b/llvm/test/Transforms/InstSimplify/select.ll --- a/llvm/test/Transforms/InstSimplify/select.ll +++ b/llvm/test/Transforms/InstSimplify/select.ll @@ -1347,68 +1347,6 @@ ret i8 %sel } -; (x << k) ? 2^k * x : 0 --> 2^k * x - -define i32 @select_icmp_and_shl(i32 %x) { -; CHECK-LABEL: @select_icmp_and_shl( -; CHECK-NEXT: [[SHL_MASK:%.*]] = and i32 [[X:%.*]], 1073741823 -; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[SHL_MASK]], 0 -; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[X]], 2 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL_NOT]], i32 0, i32 [[MUL]] -; CHECK-NEXT: ret i32 [[COND]] -; - %shl.mask = and i32 %x, 1073741823 - %tobool.not = icmp eq i32 %shl.mask, 0 - %mul = shl i32 %x, 2 - %cond = select i1 %tobool.not, i32 0, i32 %mul - ret i32 %cond -} - -define <2 x i32> @select_icmp_and_shl_vect(<2 x i32> %x) { -; CHECK-LABEL: @select_icmp_and_shl_vect( -; CHECK-NEXT: [[SHL_MASK:%.*]] = and <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq <2 x i32> [[SHL_MASK]], zeroinitializer -; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[X]], -; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[TOBOOL_NOT]], <2 x i32> zeroinitializer, <2 x i32> [[MUL]] -; CHECK-NEXT: ret <2 x i32> [[COND]] -; - %shl.mask = and <2 x i32> %x, - %tobool.not = icmp eq <2 x i32> %shl.mask, zeroinitializer - %mul = shl <2 x i32> %x, - %cond = select <2 x i1> %tobool.not, <2 x i32> zeroinitializer, <2 x i32> %mul - ret <2 x i32> %cond -} - -define i32 @select_icmp_and_shl2(i32 %x) { -; CHECK-LABEL: @select_icmp_and_shl2( -; CHECK-NEXT: [[SHL_MASK:%.*]] = and i32 [[X:%.*]], 1073741823 -; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp ne i32 [[SHL_MASK]], 0 -; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[X]], 2 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL_NOT]], i32 [[MUL]], i32 0 -; CHECK-NEXT: ret i32 [[COND]] -; - %shl.mask = and i32 %x, 1073741823 - %tobool.not = icmp ne i32 %shl.mask, 0 - %mul = shl i32 %x, 2 - %cond = select i1 %tobool.not, i32 %mul, i32 0 - ret i32 %cond -} - -define <2 x i32> @select_icmp_and_shl2_vect(<2 x i32> %x) { -; CHECK-LABEL: @select_icmp_and_shl2_vect( -; CHECK-NEXT: [[SHL_MASK:%.*]] = and <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp ne <2 x i32> [[SHL_MASK]], zeroinitializer -; CHECK-NEXT: [[MUL:%.*]] = shl <2 x i32> [[X]], -; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[TOBOOL_NOT]], <2 x i32> [[MUL]], <2 x i32> zeroinitializer -; CHECK-NEXT: ret <2 x i32> [[COND]] -; - %shl.mask = and <2 x i32> %x, - %tobool.not = icmp ne <2 x i32> %shl.mask, zeroinitializer - %mul = shl <2 x i32> %x, - %cond = select <2 x i1> %tobool.not, <2 x i32> %mul, <2 x i32> zeroinitializer - ret <2 x i32> %cond -} - define ptr @select_op_replacement_in_phi(ptr %head) { ; CHECK-LABEL: @select_op_replacement_in_phi( ; CHECK-NEXT: entry: