diff --git a/llvm/test/Transforms/InstCombine/binop-select.ll b/llvm/test/Transforms/InstCombine/binop-select.ll --- a/llvm/test/Transforms/InstCombine/binop-select.ll +++ b/llvm/test/Transforms/InstCombine/binop-select.ll @@ -1,6 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s +declare void @llvm.assume(i1) declare void @use(i32) declare void @use_f32(float) declare void @use_v2f16(<2 x half>) @@ -403,3 +404,264 @@ %r = ashr i32 -2, %s ret i32 %r } + +define <2 x i32> @test_udiv_to_const_shr(i1 %c, <2 x i32> %x, <2 x i32> %yy) { +; CHECK-LABEL: @test_udiv_to_const_shr( +; CHECK-NEXT: [[Y:%.*]] = shl nuw <2 x i32> , [[YY:%.*]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C:%.*]], <2 x i32> , <2 x i32> [[Y]] +; CHECK-NEXT: [[DIV:%.*]] = udiv <2 x i32> , [[COND]] +; CHECK-NEXT: ret <2 x i32> [[DIV]] +; + %y = shl <2 x i32> , %yy + %cond = select i1 %c, <2 x i32> , <2 x i32> %y + %div = udiv <2 x i32> , %cond + ret <2 x i32> %div +} + +define i32 @test_udiv_to_const_shr_fail_multiuse(i1 %c, i32 %x, i32 %yy) { +; CHECK-LABEL: @test_udiv_to_const_shr_fail_multiuse( +; CHECK-NEXT: [[Y:%.*]] = shl nuw i32 1, [[YY:%.*]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C:%.*]], i32 7, i32 [[Y]] +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 42, [[COND]] +; CHECK-NEXT: call void @use(i32 [[COND]]) +; CHECK-NEXT: ret i32 [[DIV]] +; + %y = shl i32 1, %yy + %cond = select i1 %c, i32 7, i32 %y + %div = udiv i32 42, %cond + call void @use(i32 %cond) + ret i32 %div +} + +define i32 @test_udiv_to_const_Cudiv(i32 %x) { +; CHECK-LABEL: @test_udiv_to_const_Cudiv( +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 90 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], i32 7, i32 19 +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X]], [[COND]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %c = icmp eq i32 %x, 90 + %cond = select i1 %c, i32 7, i32 19 + %div = udiv i32 %x, %cond + ret i32 %div +} + +define i32 @test_udiv_no_consts(i32 %x, i32 %y) { +; CHECK-LABEL: @test_udiv_no_consts( +; CHECK-NEXT: [[YNZ:%.*]] = icmp ne i32 [[Y:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[YNZ]]) +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 90 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], i32 [[Y]], i32 19 +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X]], [[COND]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %ynz = icmp ne i32 %y, 0 + call void @llvm.assume(i1 %ynz) + %c = icmp eq i32 %x, 90 + %cond = select i1 %c, i32 %y, i32 19 + %div = udiv i32 %x, %cond + ret i32 %div +} + +define i32 @test_udiv_partial_const(i32 %x, i32 %y) { +; CHECK-LABEL: @test_udiv_partial_const( +; CHECK-NEXT: [[YNZ:%.*]] = icmp ne i32 [[Y:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[YNZ]]) +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 90 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], i32 19, i32 [[Y]] +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X]], [[COND]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %ynz = icmp ne i32 %y, 0 + call void @llvm.assume(i1 %ynz) + %c = icmp eq i32 %x, 90 + %cond = select i1 %c, i32 19, i32 %y + %div = udiv i32 %x, %cond + ret i32 %div +} + +define i32 @test_udiv_fail_no_speculation(i32 %x, i32 %y) { +; CHECK-LABEL: @test_udiv_fail_no_speculation( +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 90 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], i32 19, i32 [[Y:%.*]] +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X]], [[COND]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %c = icmp eq i32 %x, 90 + %cond = select i1 %c, i32 19, i32 %y + %div = udiv i32 %x, %cond + ret i32 %div +} + +define i32 @test_udiv_to_const_Cudiv_fail_non_equality(i32 %x) { +; CHECK-LABEL: @test_udiv_to_const_Cudiv_fail_non_equality( +; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[X:%.*]], 91 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], i32 7, i32 19 +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X]], [[COND]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %c = icmp ule i32 %x, 90 + %cond = select i1 %c, i32 7, i32 19 + %div = udiv i32 %x, %cond + ret i32 %div +} + +define <2 x i32> @test_sdiv_to_const_Csdiv(<2 x i32> %x) { +; CHECK-LABEL: @test_sdiv_to_const_Csdiv( +; CHECK-NEXT: [[C_NOT:%.*]] = icmp eq <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[C_NOT]], <2 x i32> , <2 x i32> +; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i32> [[X]], [[COND]] +; CHECK-NEXT: ret <2 x i32> [[DIV]] +; + %c = icmp ne <2 x i32> %x, + %cond = select <2 x i1> %c, <2 x i32> , <2 x i32> + %div = sdiv <2 x i32> %x, %cond + ret <2 x i32> %div +} + +define <2 x i32> @test_sdiv_to_const_Csdiv_todo_no_common_bit(<2 x i32> %x) { +; CHECK-LABEL: @test_sdiv_to_const_Csdiv_todo_no_common_bit( +; CHECK-NEXT: [[C_NOT:%.*]] = icmp eq <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[C_NOT]], <2 x i32> , <2 x i32> +; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i32> [[X]], [[COND]] +; CHECK-NEXT: ret <2 x i32> [[DIV]] +; + %c = icmp ne <2 x i32> %x, + %cond = select <2 x i1> %c, <2 x i32> , <2 x i32> + %div = sdiv <2 x i32> %x, %cond + ret <2 x i32> %div +} + +define i32 @test_srem_to_const_Csrem(i32 %x) { +; CHECK-LABEL: @test_srem_to_const_Csrem( +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 24 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], i32 18, i32 16 +; CHECK-NEXT: [[DIV:%.*]] = srem i32 [[X]], [[COND]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %c = icmp eq i32 %x, 24 + %cond = select i1 %c, i32 18, i32 16 + %div = srem i32 %x, %cond + ret i32 %div +} + +define i32 @test_srem_to_const_Csrem_todo_no_common_bits(i32 %x) { +; CHECK-LABEL: @test_srem_to_const_Csrem_todo_no_common_bits( +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 24 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], i32 7, i32 16 +; CHECK-NEXT: [[DIV:%.*]] = srem i32 [[X]], [[COND]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %c = icmp eq i32 %x, 24 + %cond = select i1 %c, i32 7, i32 16 + %div = srem i32 %x, %cond + ret i32 %div +} + +define i32 @test_srem_to_const_Csrem_fail_multiuse(i32 %x) { +; CHECK-LABEL: @test_srem_to_const_Csrem_fail_multiuse( +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 24 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], i32 7, i32 16 +; CHECK-NEXT: [[DIV:%.*]] = srem i32 [[X]], [[COND]] +; CHECK-NEXT: call void @use(i32 [[COND]]) +; CHECK-NEXT: ret i32 [[DIV]] +; + %c = icmp eq i32 %x, 24 + %cond = select i1 %c, i32 7, i32 16 + %div = srem i32 %x, %cond + call void @use(i32 %cond) + ret i32 %div +} + +define i32 @test_srem_fail_no_speculation(i32 %x) { +; CHECK-LABEL: @test_srem_fail_no_speculation( +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 24 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], i32 7, i32 -1 +; CHECK-NEXT: [[DIV:%.*]] = srem i32 [[X]], [[COND]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %c = icmp eq i32 %x, 24 + %cond = select i1 %c, i32 7, i32 -1 + %div = srem i32 %x, %cond + ret i32 %div +} + + +define i32 @test_urem_to_const_and_ind_x(i32 %x, i32 %yy) { +; CHECK-LABEL: @test_urem_to_const_and_ind_x( +; CHECK-NEXT: [[Y:%.*]] = shl nuw i32 1, [[YY:%.*]] +; CHECK-NEXT: [[C_NOT:%.*]] = icmp eq i32 [[X:%.*]], 24 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C_NOT]], i32 19, i32 [[Y]] +; CHECK-NEXT: [[DIV:%.*]] = urem i32 [[X]], [[COND]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %y = shl i32 1, %yy + %c = icmp ne i32 %x, 24 + %cond = select i1 %c, i32 %y, i32 19 + %div = urem i32 %x, %cond + ret i32 %div +} + +define i32 @test_urem_to_const_and(i1 %c, i32 %yy) { +; CHECK-LABEL: @test_urem_to_const_and( +; CHECK-NEXT: [[Y:%.*]] = shl nuw i32 1, [[YY:%.*]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C:%.*]], i32 [[Y]], i32 19 +; CHECK-NEXT: [[DIV:%.*]] = urem i32 44, [[COND]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %y = shl i32 1, %yy + %cond = select i1 %c, i32 %y, i32 19 + %div = urem i32 44, %cond + ret i32 %div +} + +define i32 @test_urem_to_const_and_fail_no_speculation(i1 %c, i32 %yy) { +; CHECK-LABEL: @test_urem_to_const_and_fail_no_speculation( +; CHECK-NEXT: [[Y:%.*]] = shl i32 2, [[YY:%.*]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C:%.*]], i32 [[Y]], i32 19 +; CHECK-NEXT: [[DIV:%.*]] = urem i32 44, [[COND]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %y = shl i32 2, %yy + %cond = select i1 %c, i32 %y, i32 19 + %div = urem i32 44, %cond + ret i32 %div +} + +define i32 @test_mul_to_const_Cmul(i32 %x) { +; CHECK-LABEL: @test_mul_to_const_Cmul( +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 61 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], i32 9, i32 14 +; CHECK-NEXT: [[DIV:%.*]] = mul i32 [[COND]], [[X]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %c = icmp eq i32 %x, 61 + %cond = select i1 %c, i32 9, i32 14 + %div = mul i32 %x, %cond + ret i32 %div +} + +define i32 @test_Cmul_const_folded_in(i32 %x) { +; CHECK-LABEL: @test_Cmul_const_folded_in( +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 61 +; CHECK-NEXT: [[DIV:%.*]] = select i1 [[C]], i32 854, i32 126 +; CHECK-NEXT: ret i32 [[DIV]] +; + %c = icmp eq i32 %x, 61 + %cond = select i1 %c, i32 %x, i32 9 + %div = mul i32 %cond, 14 + ret i32 %div +} + +define i32 @test_Cmul_expr_folded_in(i32 %x, i32 %y) { +; CHECK-LABEL: @test_Cmul_expr_folded_in( +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 61 +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[Y:%.*]], 14 +; CHECK-NEXT: [[DIV:%.*]] = select i1 [[C]], i32 [[TMP1]], i32 126 +; CHECK-NEXT: ret i32 [[DIV]] +; + %c = icmp eq i32 %x, 61 + %cond = select i1 %c, i32 %y, i32 9 + %div = mul i32 %cond, 14 + ret i32 %div +}