
Motivating case: https://godbolt.org/z/Wxcc51jcj Alive2: https://alive2.llvm.org/ce/z/-bPPAg
635 lines
19 KiB
LLVM
635 lines
19 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
|
|
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
|
|
|
|
declare void @use(i32)
|
|
|
|
; These exercise all combinations of signed comparison
|
|
; for each of the three values produced by your typical
|
|
; 3way compare function (-1, 0, 1)
|
|
|
|
define void @test_low_sgt(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_low_sgt
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP_NOT]], label [[NORMAL:%.*]], label [[UNREACHED:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]])
|
|
; CHECK-NEXT: call void @use(i32 [[RESULT]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp sgt i32 %result, -1
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_low_slt(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_low_slt
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: br i1 false, label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp slt i32 %result, -1
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_low_sge(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_low_sge
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: br i1 true, label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]])
|
|
; CHECK-NEXT: call void @use(i32 [[RESULT]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp sge i32 %result, -1
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_low_sle(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_low_sle
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: call void @use(i32 -1)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp sle i32 %result, -1
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_low_ne(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_low_ne
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP_NOT]], label [[NORMAL:%.*]], label [[UNREACHED:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]])
|
|
; CHECK-NEXT: call void @use(i32 [[RESULT]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp ne i32 %result, -1
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_low_eq(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_low_eq
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: call void @use(i32 -1)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp eq i32 %result, -1
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_mid_sgt(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_mid_sgt
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: call void @use(i32 1)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp sgt i32 %result, 0
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_mid_slt(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_mid_slt
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: call void @use(i32 -1)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp slt i32 %result, 0
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_mid_sge(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_mid_sge
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP_NOT]], label [[NORMAL:%.*]], label [[UNREACHED:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]])
|
|
; CHECK-NEXT: call void @use(i32 [[RESULT]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp sge i32 %result, 0
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_mid_sle(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_mid_sle
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP_NOT]], label [[NORMAL:%.*]], label [[UNREACHED:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]])
|
|
; CHECK-NEXT: call void @use(i32 [[RESULT]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp sle i32 %result, 0
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_mid_ne(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_mid_ne
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP_NOT]], label [[NORMAL:%.*]], label [[UNREACHED:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]])
|
|
; CHECK-NEXT: call void @use(i32 [[RESULT]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp ne i32 %result, 0
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_mid_eq(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_mid_eq
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: call void @use(i32 0)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp eq i32 %result, 0
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_high_sgt(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_high_sgt
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: br i1 false, label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp sgt i32 %result, 1
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_high_slt(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_high_slt
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP_NOT]], label [[NORMAL:%.*]], label [[UNREACHED:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]])
|
|
; CHECK-NEXT: call void @use(i32 [[RESULT]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp slt i32 %result, 1
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_high_sge(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_high_sge
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: call void @use(i32 1)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp sge i32 %result, 1
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_high_sle(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_high_sle
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: br i1 true, label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]])
|
|
; CHECK-NEXT: call void @use(i32 [[RESULT]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp sle i32 %result, 1
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_high_ne(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_high_ne
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP_NOT]], label [[NORMAL:%.*]], label [[UNREACHED:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]])
|
|
; CHECK-NEXT: call void @use(i32 [[RESULT]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp ne i32 %result, 1
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @test_high_eq(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @test_high_eq
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: call void @use(i32 1)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -1, i32 1
|
|
%result = select i1 %eq, i32 0, i32 %.
|
|
%cmp = icmp eq i32 %result, 1
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
; These five make sure we didn't accidentally hard code one of the
|
|
; produced values
|
|
|
|
define void @non_standard_low(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @non_standard_low
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[TMP1]], label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: call void @use(i32 -3)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -3, i32 -1
|
|
%result = select i1 %eq, i32 -2, i32 %.
|
|
%cmp = icmp eq i32 %result, -3
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @non_standard_mid(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @non_standard_mid
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[EQ:%.*]] = icmp eq i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[EQ]], label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: call void @use(i32 -2)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -3, i32 -1
|
|
%result = select i1 %eq, i32 -2, i32 %.
|
|
%cmp = icmp eq i32 %result, -2
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @non_standard_high(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @non_standard_high
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[A]], [[B]]
|
|
; CHECK-NEXT: br i1 [[TMP1]], label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: call void @use(i32 -1)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -3, i32 -1
|
|
%result = select i1 %eq, i32 -2, i32 %.
|
|
%cmp = icmp eq i32 %result, -1
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @non_standard_bound1(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @non_standard_bound1
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: br i1 false, label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -3, i32 -1
|
|
%result = select i1 %eq, i32 -2, i32 %.
|
|
%cmp = icmp eq i32 %result, -20
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define void @non_standard_bound2(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: define void @non_standard_bound2
|
|
; CHECK-SAME: (i64 [[A:%.*]], i64 [[B:%.*]]) {
|
|
; CHECK-NEXT: br i1 false, label [[UNREACHED:%.*]], label [[NORMAL:%.*]]
|
|
; CHECK: normal:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: unreached:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%eq = icmp eq i64 %a, %b
|
|
%slt = icmp slt i64 %a, %b
|
|
%. = select i1 %slt, i32 -3, i32 -1
|
|
%result = select i1 %eq, i32 -2, i32 %.
|
|
%cmp = icmp eq i32 %result, 0
|
|
br i1 %cmp, label %unreached, label %normal
|
|
normal:
|
|
ret void
|
|
unreached:
|
|
call void @use(i32 %result)
|
|
ret void
|
|
}
|
|
|
|
define i32 @smax_smin_to_scmp(i32 %x) {
|
|
; CHECK-LABEL: define i32 @smax_smin_to_scmp
|
|
; CHECK-SAME: (i32 [[X:%.*]]) {
|
|
; CHECK-NEXT: [[COND5:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 0)
|
|
; CHECK-NEXT: ret i32 [[COND5]]
|
|
;
|
|
%cond = call i32 @llvm.smax.i32(i32 %x, i32 -1)
|
|
%cond5 = call i32 @llvm.smin.i32(i32 %cond, i32 1)
|
|
ret i32 %cond5
|
|
}
|
|
|
|
define i16 @smax_smin_to_scmp_i16(i16 %x) {
|
|
; CHECK-LABEL: define i16 @smax_smin_to_scmp_i16
|
|
; CHECK-SAME: (i16 [[X:%.*]]) {
|
|
; CHECK-NEXT: [[COND5:%.*]] = call i16 @llvm.scmp.i16.i16(i16 [[X]], i16 0)
|
|
; CHECK-NEXT: ret i16 [[COND5]]
|
|
;
|
|
%cond = call i16 @llvm.smax.i16(i16 %x, i16 -1)
|
|
%cond5 = call i16 @llvm.smin.i16(i16 %cond, i16 1)
|
|
ret i16 %cond5
|
|
}
|
|
|
|
; Test the reversed pattern: smax(smin(X, 1), -1) -> scmp(X, 0)
|
|
define i32 @smin_smax_to_scmp(i32 %x) {
|
|
; CHECK-LABEL: define i32 @smin_smax_to_scmp
|
|
; CHECK-SAME: (i32 [[X:%.*]]) {
|
|
; CHECK-NEXT: [[COND5:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 0)
|
|
; CHECK-NEXT: ret i32 [[COND5]]
|
|
;
|
|
%cond = call i32 @llvm.smin.i32(i32 %x, i32 1)
|
|
%cond5 = call i32 @llvm.smax.i32(i32 %cond, i32 -1)
|
|
ret i32 %cond5
|
|
}
|
|
|
|
define i32 @test_max_min_neg(i32 %x) {
|
|
; CHECK-LABEL: define i32 @test_max_min_neg
|
|
; CHECK-SAME: (i32 [[X:%.*]]) {
|
|
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 -2)
|
|
; CHECK-NEXT: [[COND5:%.*]] = call i32 @llvm.smin.i32(i32 [[COND]], i32 1)
|
|
; CHECK-NEXT: ret i32 [[COND5]]
|
|
;
|
|
%cond = call i32 @llvm.smax.i32(i32 %x, i32 -2)
|
|
%cond5 = call i32 @llvm.smin.i32(i32 %cond, i32 1)
|
|
ret i32 %cond5
|
|
}
|
|
|
|
define i32 @test_max_min_neg_2(i32 %x) {
|
|
; CHECK-LABEL: define i32 @test_max_min_neg_2
|
|
; CHECK-SAME: (i32 [[X:%.*]]) {
|
|
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 -1)
|
|
; CHECK-NEXT: [[COND5:%.*]] = call i32 @llvm.smin.i32(i32 [[COND]], i32 2)
|
|
; CHECK-NEXT: ret i32 [[COND5]]
|
|
;
|
|
%cond = call i32 @llvm.smax.i32(i32 %x, i32 -1)
|
|
%cond5 = call i32 @llvm.smin.i32(i32 %cond, i32 2)
|
|
ret i32 %cond5
|
|
}
|
|
|
|
define i32 @test_multiple_uses(i32 %x) {
|
|
; CHECK-LABEL: define i32 @test_multiple_uses
|
|
; CHECK-SAME: (i32 [[X:%.*]]) {
|
|
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 -1)
|
|
; CHECK-NEXT: [[COND5:%.*]] = call i32 @llvm.smin.i32(i32 [[COND]], i32 1)
|
|
; CHECK-NEXT: [[SUM:%.*]] = add i32 [[COND]], [[COND5]]
|
|
; CHECK-NEXT: ret i32 [[SUM]]
|
|
;
|
|
%cond = call i32 @llvm.smax.i32(i32 %x, i32 -1)
|
|
%cond5 = call i32 @llvm.smin.i32(i32 %cond, i32 1)
|
|
%sum = add i32 %cond, %cond5
|
|
ret i32 %sum
|
|
}
|