| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt < %s -passes=instcombine -S | FileCheck %s |
| |
| target datalayout = "n32" |
| |
| define i1 @is_rem2_neg_i8(i8 %x) { |
| ; CHECK-LABEL: @is_rem2_neg_i8( |
| ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -127 |
| ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP1]], -127 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %s = srem i8 %x, 2 |
| %r = icmp slt i8 %s, 0 |
| ret i1 %r |
| } |
| |
| define <2 x i1> @is_rem2_pos_v2i8(<2 x i8> %x) { |
| ; CHECK-LABEL: @is_rem2_pos_v2i8( |
| ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], splat (i8 -127) |
| ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[TMP1]], splat (i8 1) |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %s = srem <2 x i8> %x, <i8 2, i8 2> |
| %r = icmp sgt <2 x i8> %s, zeroinitializer |
| ret <2 x i1> %r |
| } |
| |
| ; i8 -97 == 159 == 0b10011111 |
| |
| define i1 @is_rem32_pos_i8(i8 %x) { |
| ; CHECK-LABEL: @is_rem32_pos_i8( |
| ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -97 |
| ; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[TMP1]], 0 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %s = srem i8 %x, 32 |
| %r = icmp sgt i8 %s, 0 |
| ret i1 %r |
| } |
| |
| ; i16 -32765 == 32771 == 0b1000000000000011 |
| |
| define i1 @is_rem4_neg_i16(i16 %x) { |
| ; CHECK-LABEL: @is_rem4_neg_i16( |
| ; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[X:%.*]], -32765 |
| ; CHECK-NEXT: [[R:%.*]] = icmp ugt i16 [[TMP1]], -32768 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %s = srem i16 %x, 4 |
| %r = icmp slt i16 %s, 0 |
| ret i1 %r |
| } |
| |
| declare void @use(i32) |
| |
| ; TODO: This is still worth folding because srem is difficult? |
| |
| define i1 @is_rem32_neg_i32_extra_use(i32 %x) { |
| ; CHECK-LABEL: @is_rem32_neg_i32_extra_use( |
| ; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 32 |
| ; CHECK-NEXT: call void @use(i32 [[S]]) |
| ; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[S]], 0 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %s = srem i32 %x, 32 |
| call void @use(i32 %s) |
| %r = icmp slt i32 %s, 0 |
| ret i1 %r |
| } |
| |
| ; Negative test - wrong compare constant |
| |
| define i1 @is_rem8_nonneg_i16(i16 %x) { |
| ; CHECK-LABEL: @is_rem8_nonneg_i16( |
| ; CHECK-NEXT: [[S:%.*]] = srem i16 [[X:%.*]], 8 |
| ; CHECK-NEXT: [[R:%.*]] = icmp sgt i16 [[S]], -1 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %s = srem i16 %x, 8 |
| %r = icmp sgt i16 %s, -1 |
| ret i1 %r |
| } |
| |
| ; Negative test - wrong remainder constant |
| |
| define i1 @is_rem3_neg_i8(i8 %x) { |
| ; CHECK-LABEL: @is_rem3_neg_i8( |
| ; CHECK-NEXT: [[S:%.*]] = srem i8 [[X:%.*]], 3 |
| ; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[S]], 0 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %s = srem i8 %x, 3 |
| %r = icmp slt i8 %s, 0 |
| ret i1 %r |
| } |
| |
| ; Negative test - wrong compare constant |
| |
| define i1 @is_rem16_something_i8(i8 %x) { |
| ; CHECK-LABEL: @is_rem16_something_i8( |
| ; CHECK-NEXT: [[S:%.*]] = srem i8 [[X:%.*]], 16 |
| ; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[S]], 7 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %s = srem i8 %x, 16 |
| %r = icmp slt i8 %s, 7 |
| ret i1 %r |
| } |
| |
| ; PR30281 - https://llvm.org/bugs/show_bug.cgi?id=30281 |
| |
| ; All of these tests contain foldable division-by-constant instructions, but we |
| ; can't assert that those folds have occurred before we process the later icmp. |
| |
| define i32 @icmp_div(i16 %a, i16 %c) { |
| ; CHECK-LABEL: @icmp_div( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 |
| ; CHECK-NEXT: br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i16 [[C:%.*]], 0 |
| ; CHECK-NEXT: [[TMP0:%.*]] = sext i1 [[CMP_NOT]] to i32 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[TMP0]], [[THEN]] ] |
| ; CHECK-NEXT: ret i32 [[PHI]] |
| ; |
| entry: |
| %tobool = icmp eq i16 %a, 0 |
| br i1 %tobool, label %then, label %exit |
| |
| then: |
| %div = sdiv i16 %c, -1 |
| %cmp = icmp ne i16 %div, 0 |
| br label %exit |
| |
| exit: |
| %phi = phi i1 [ false, %entry ], [ %cmp, %then ] |
| %zext = zext i1 %phi to i32 |
| %add = add nsw i32 %zext, -1 |
| ret i32 %add |
| } |
| |
| define i32 @icmp_div2(i16 %a, i16 %c) { |
| ; CHECK-LABEL: @icmp_div2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 |
| ; CHECK-NEXT: br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: ret i32 -1 |
| ; |
| entry: |
| %tobool = icmp eq i16 %a, 0 |
| br i1 %tobool, label %then, label %exit |
| |
| then: |
| %div = sdiv i16 %c, 0 |
| %cmp = icmp ne i16 %div, 0 |
| br label %exit |
| |
| exit: |
| %phi = phi i1 [ false, %entry ], [ %cmp, %then ] |
| %zext = zext i1 %phi to i32 |
| %add = add nsw i32 %zext, -1 |
| ret i32 %add |
| } |
| |
| define i32 @icmp_div3(i16 %a, i16 %c) { |
| ; CHECK-LABEL: @icmp_div3( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 |
| ; CHECK-NEXT: br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i16 [[C:%.*]], 0 |
| ; CHECK-NEXT: [[TMP0:%.*]] = sext i1 [[CMP_NOT]] to i32 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[TMP0]], [[THEN]] ] |
| ; CHECK-NEXT: ret i32 [[PHI]] |
| ; |
| entry: |
| %tobool = icmp eq i16 %a, 0 |
| br i1 %tobool, label %then, label %exit |
| |
| then: |
| %div = sdiv i16 %c, 1 |
| %cmp = icmp ne i16 %div, 0 |
| br label %exit |
| |
| exit: |
| %phi = phi i1 [ false, %entry ], [ %cmp, %then ] |
| %zext = zext i1 %phi to i32 |
| %add = add nsw i32 %zext, -1 |
| ret i32 %add |
| } |
| |
| define i1 @udiv_eq_umax(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @udiv_eq_umax( |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], -1 |
| ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[Y:%.*]], 1 |
| ; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP1]], [[TMP2]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %d = udiv i8 %x, %y |
| %r = icmp eq i8 %d, 255 |
| ret i1 %r |
| } |
| |
| define <2 x i1> @udiv_ne_umax(<2 x i5> %x, <2 x i5> %y) { |
| ; CHECK-LABEL: @udiv_ne_umax( |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i5> [[X:%.*]], splat (i5 -1) |
| ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i5> [[Y:%.*]], splat (i5 1) |
| ; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[TMP1]], [[TMP2]] |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %d = udiv <2 x i5> %x, %y |
| %r = icmp ne <2 x i5> %d, <i5 -1, i5 -1> |
| ret <2 x i1> %r |
| } |
| |
| define i1 @udiv_eq_big(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @udiv_eq_big( |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], -128 |
| ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[Y:%.*]], 1 |
| ; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP1]], [[TMP2]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %d = udiv i8 %x, %y |
| %r = icmp eq i8 %d, 128 |
| ret i1 %r |
| } |
| |
| define i1 @udiv_ne_big(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @udiv_ne_big( |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8 [[X:%.*]], -128 |
| ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[Y:%.*]], 1 |
| ; CHECK-NEXT: [[R:%.*]] = or i1 [[TMP1]], [[TMP2]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %d = udiv i8 %x, %y |
| %r = icmp ne i8 %d, 128 |
| ret i1 %r |
| } |
| |
| ; negative test - must have negative compare constant |
| |
| define i1 @udiv_eq_not_big(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @udiv_eq_not_big( |
| ; CHECK-NEXT: [[D:%.*]] = udiv i8 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[D]], 127 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %d = udiv i8 %x, %y |
| %r = icmp eq i8 %d, 127 |
| ret i1 %r |
| } |
| |
| ; negative test - must be equality predicate |
| |
| define i1 @udiv_slt_umax(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @udiv_slt_umax( |
| ; CHECK-NEXT: [[D:%.*]] = udiv i8 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[D]], -1 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %d = udiv i8 %x, %y |
| %r = icmp slt i8 %d, 255 |
| ret i1 %r |
| } |
| |
| ; negative test - extra use |
| |
| define i1 @udiv_eq_umax_use(i32 %x, i32 %y) { |
| ; CHECK-LABEL: @udiv_eq_umax_use( |
| ; CHECK-NEXT: [[D:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: call void @use(i32 [[D]]) |
| ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[D]], -1 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %d = udiv i32 %x, %y |
| call void @use(i32 %d) |
| %r = icmp eq i32 %d, -1 |
| ret i1 %r |
| } |
| |
| define i1 @sdiv_eq_smin(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sdiv_eq_smin( |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], -128 |
| ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[Y:%.*]], 1 |
| ; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP1]], [[TMP2]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %d = sdiv i8 %x, %y |
| %r = icmp eq i8 %d, -128 |
| ret i1 %r |
| } |
| |
| define <2 x i1> @sdiv_ne_smin(<2 x i5> %x, <2 x i5> %y) { |
| ; CHECK-LABEL: @sdiv_ne_smin( |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i5> [[X:%.*]], splat (i5 -16) |
| ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i5> [[Y:%.*]], splat (i5 1) |
| ; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[TMP1]], [[TMP2]] |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %d = sdiv <2 x i5> %x, %y |
| %r = icmp ne <2 x i5> %d, <i5 -16, i5 -16> |
| ret <2 x i1> %r |
| } |
| |
| ; negative test - must be SMIN |
| |
| define i1 @sdiv_eq_small(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sdiv_eq_small( |
| ; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[D]], -127 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %d = sdiv i8 %x, %y |
| %r = icmp eq i8 %d, -127 |
| ret i1 %r |
| } |
| |
| ; negative test - must be SMIN |
| |
| define i1 @sdiv_ne_big(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sdiv_ne_big( |
| ; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[D]], 127 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %d = sdiv i8 %x, %y |
| %r = icmp ne i8 %d, 127 |
| ret i1 %r |
| } |
| |
| ; negative test - must be SMIN |
| |
| define i1 @sdiv_eq_not_big(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sdiv_eq_not_big( |
| ; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[D]], 100 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %d = sdiv i8 %x, %y |
| %r = icmp eq i8 %d, 100 |
| ret i1 %r |
| } |
| |
| ; negative test - must be equality predicate |
| |
| define i1 @sdiv_ult_smin(i8 %x, i8 %y) { |
| ; CHECK-LABEL: @sdiv_ult_smin( |
| ; CHECK-NEXT: [[D:%.*]] = sdiv i8 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[D]], -1 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %d = sdiv i8 %x, %y |
| %r = icmp ult i8 %d, 128 |
| ret i1 %r |
| } |
| |
| ; negative test - extra use |
| |
| define i1 @sdiv_eq_smin_use(i32 %x, i32 %y) { |
| ; CHECK-LABEL: @sdiv_eq_smin_use( |
| ; CHECK-NEXT: [[D:%.*]] = sdiv i32 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: call void @use(i32 [[D]]) |
| ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[D]], -2147483648 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %d = sdiv i32 %x, %y |
| call void @use(i32 %d) |
| %r = icmp eq i32 %d, -2147483648 |
| ret i1 %r |
| } |
| |
| ; Fold (X / C) cmp X into X ~cmp 0 (~cmp is the inverse predicate of cmp), for some C != 1 |
| ; Alternative form of this fold is when division is replaced with logic right shift |
| |
| define i1 @sdiv_x_by_const_cmp_x(i32 %x) { |
| ; CHECK-LABEL: @sdiv_x_by_const_cmp_x( |
| ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X:%.*]], 0 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %v = sdiv i32 %x, 13 |
| %r = icmp eq i32 %v, %x |
| ret i1 %r |
| } |
| |
| define i1 @udiv_x_by_const_cmp_x(i32 %x) { |
| ; CHECK-LABEL: @udiv_x_by_const_cmp_x( |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[X:%.*]], 0 |
| ; CHECK-NEXT: ret i1 [[TMP1]] |
| ; |
| %1 = udiv i32 %x, 123 |
| %2 = icmp slt i32 %1, %x |
| ret i1 %2 |
| } |
| |
| define <2 x i1> @udiv_x_by_const_cmp_x_non_splat(<2 x i32> %x) { |
| ; CHECK-LABEL: @udiv_x_by_const_cmp_x_non_splat( |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <2 x i32> [[X:%.*]], zeroinitializer |
| ; CHECK-NEXT: ret <2 x i1> [[TMP1]] |
| ; |
| %1 = udiv <2 x i32> %x, <i32 123, i32 -123> |
| %2 = icmp slt <2 x i32> %1, %x |
| ret <2 x i1> %2 |
| } |
| |
| |
| define <2 x i1> @sdiv_x_by_const_cmp_x_non_splat(<2 x i32> %x) { |
| ; CHECK-LABEL: @sdiv_x_by_const_cmp_x_non_splat( |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i32> [[X:%.*]], zeroinitializer |
| ; CHECK-NEXT: ret <2 x i1> [[TMP1]] |
| ; |
| %1 = sdiv <2 x i32> %x, <i32 2, i32 3> |
| %2 = icmp eq <2 x i32> %1, %x |
| ret <2 x i1> %2 |
| } |
| |
| ; Same as above but with right shift instead of division (C != 0) |
| |
| define i1 @lshr_x_by_const_cmp_x(i32 %x) { |
| ; CHECK-LABEL: @lshr_x_by_const_cmp_x( |
| ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X:%.*]], 0 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %v = lshr i32 %x, 1 |
| %r = icmp eq i32 %v, %x |
| ret i1 %r |
| } |
| |
| define <4 x i1> @lshr_by_const_cmp_sle_value(<4 x i32> %x) { |
| ; CHECK-LABEL: @lshr_by_const_cmp_sle_value( |
| ; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[X:%.*]], splat (i32 -1) |
| ; CHECK-NEXT: ret <4 x i1> [[R]] |
| ; |
| %v = lshr <4 x i32> %x, <i32 3, i32 3, i32 3, i32 3> |
| %r = icmp sle <4 x i32> %v, %x |
| ret <4 x i1> %r |
| } |
| |
| define <4 x i1> @lshr_by_const_cmp_sle_value_non_splat(<4 x i32> %x) { |
| ; CHECK-LABEL: @lshr_by_const_cmp_sle_value_non_splat( |
| ; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[X:%.*]], splat (i32 -1) |
| ; CHECK-NEXT: ret <4 x i1> [[R]] |
| ; |
| %v = lshr <4 x i32> %x, <i32 3, i32 3, i32 3, i32 5> |
| %r = icmp sle <4 x i32> %v, %x |
| ret <4 x i1> %r |
| } |
| |
| |
| define <4 x i1> @ashr_by_const_cmp_sge_value_non_splat(<4 x i32> %x) { |
| ; CHECK-LABEL: @ashr_by_const_cmp_sge_value_non_splat( |
| ; CHECK-NEXT: [[R:%.*]] = icmp slt <4 x i32> [[X:%.*]], splat (i32 1) |
| ; CHECK-NEXT: ret <4 x i1> [[R]] |
| ; |
| %v = ashr <4 x i32> %x, <i32 1, i32 2, i32 3, i32 4> |
| %r = icmp sge <4 x i32> %v, %x |
| ret <4 x i1> %r |
| } |
| |
| |
| define i1 @lshr_by_const_cmp_sge_value(i32 %x) { |
| ; CHECK-LABEL: @lshr_by_const_cmp_sge_value( |
| ; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[X:%.*]], 1 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %v = lshr i32 %x, 3 |
| %r = icmp sge i32 %v, %x |
| ret i1 %r |
| } |
| |
| define i1 @ashr_x_by_const_cmp_sge_x(i32 %x) { |
| ; CHECK-LABEL: @ashr_x_by_const_cmp_sge_x( |
| ; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[X:%.*]], 1 |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %v = ashr i32 %x, 5 |
| %r = icmp sge i32 %v, %x |
| ret i1 %r |
| } |
| |
| ; Negative test - constant is 1 |
| |
| define <2 x i1> @udiv_x_by_const_cmp_eq_value_neg(<2 x i32> %x) { |
| ; CHECK-LABEL: @udiv_x_by_const_cmp_eq_value_neg( |
| ; CHECK-NEXT: [[V:%.*]] = udiv <2 x i32> [[X:%.*]], <i32 1, i32 3> |
| ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i32> [[V]], [[X]] |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %v = udiv <2 x i32> %x, <i32 1, i32 3> |
| %r = icmp eq <2 x i32> %v, %x |
| ret <2 x i1> %r |
| } |
| |
| define <2 x i1> @sdiv_x_by_const_cmp_eq_value_neg(<2 x i32> %x) { |
| ; CHECK-LABEL: @sdiv_x_by_const_cmp_eq_value_neg( |
| ; CHECK-NEXT: [[V:%.*]] = sdiv <2 x i32> [[X:%.*]], <i32 1, i32 3> |
| ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i32> [[V]], [[X]] |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %v = sdiv <2 x i32> %x, <i32 1, i32 3> |
| %r = icmp eq <2 x i32> %v, %x |
| ret <2 x i1> %r |
| } |
| |
| ; Negative test - constant is 0 |
| |
| define <2 x i1> @lshr_x_by_const_cmp_slt_value_neg(<2 x i32> %x) { |
| ; CHECK-LABEL: @lshr_x_by_const_cmp_slt_value_neg( |
| ; CHECK-NEXT: [[V:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 0, i32 2> |
| ; CHECK-NEXT: [[R:%.*]] = icmp slt <2 x i32> [[V]], [[X]] |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %v = lshr <2 x i32> %x, <i32 0, i32 2> |
| %r = icmp slt <2 x i32> %v, %x |
| ret <2 x i1> %r |
| } |
| |
| ; Negative test - unsigned predicate with sdiv |
| |
| define i1 @sdiv_x_by_const_cmp_ult_value_neg(i32 %x) { |
| ; CHECK-LABEL: @sdiv_x_by_const_cmp_ult_value_neg( |
| ; CHECK-NEXT: [[V:%.*]] = sdiv i32 [[X:%.*]], 3 |
| ; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[V]], [[X]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %v = sdiv i32 %x, 3 |
| %r = icmp ult i32 %v, %x |
| ret i1 %r |
| } |
| |
| ; Negative case - one of the components of a vector is 1 |
| |
| define <4 x i1> @sdiv_x_by_const_cmp_sgt_value_neg(<4 x i32> %x) { |
| ; CHECK-LABEL: @sdiv_x_by_const_cmp_sgt_value_neg( |
| ; CHECK-NEXT: [[V:%.*]] = sdiv <4 x i32> [[X:%.*]], <i32 1, i32 2, i32 3, i32 4> |
| ; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[V]], [[X]] |
| ; CHECK-NEXT: ret <4 x i1> [[R]] |
| ; |
| %v = sdiv <4 x i32> %x, <i32 1, i32 2, i32 3, i32 4> |
| %r = icmp sgt <4 x i32> %v, %x |
| ret <4 x i1> %r |
| } |
| |
| ; Negative case - ashr only allows sge/slt predicates |
| |
| define i1 @ashr_x_by_const_cmp_sle_value_neg(i32 %x) { |
| ; CHECK-LABEL: @ashr_x_by_const_cmp_sle_value_neg( |
| ; CHECK-NEXT: [[V:%.*]] = ashr i32 [[X:%.*]], 3 |
| ; CHECK-NEXT: [[R:%.*]] = icmp sle i32 [[V]], [[X]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %v = ashr i32 %x, 3 |
| %r = icmp sle i32 %v, %x |
| ret i1 %r |
| } |