378 lines
9.9 KiB
LLVM
378 lines
9.9 KiB
LLVM
; 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:%.*]], <i8 -127, i8 -127>
|
|
; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[TMP1]], <i8 1, 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:%.*]] = icmp eq i16 [[C:%.*]], 0
|
|
; CHECK-NEXT: [[PHI_BO:%.*]] = sext i1 [[CMP]] to i32
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[PHI_BO]], [[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:%.*]] = icmp eq i16 [[C:%.*]], 0
|
|
; CHECK-NEXT: [[PHI_BO:%.*]] = sext i1 [[CMP]] to i32
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[PHI_BO]], [[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:%.*]], <i5 -1, i5 -1>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i5> [[Y:%.*]], <i5 1, 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:%.*]], <i5 -16, i5 -16>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i5> [[Y:%.*]], <i5 1, 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
|
|
}
|