2018-04-28 12:38:21 +08:00
|
|
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
|
|
; Various patterns of three-ways comparison that are not currently recognized.
|
|
|
|
|
|
|
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
|
|
|
|
|
|
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
|
|
|
|
|
|
|
declare void @foo(i32 %x)
|
|
|
|
|
|
|
|
define i32 @compare_against_arbitrary_value(i32 %x, i32 %c) {
|
|
|
|
; TODO: We can prove that if %x s> %c then %x != c, so there should be no actual
|
|
|
|
; calculations in callfoo block. @foo can be invoked with 1. We only do it
|
|
|
|
; for constants that are not 0 currently while it could be generalized.
|
|
|
|
; CHECK-LABEL: @compare_against_arbitrary_value(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], [[C:%.*]]
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
|
|
|
; CHECK: callfoo:
|
|
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[X]], [[C]]
|
|
|
|
; CHECK-NEXT: [[SELECT2:%.*]] = zext i1 [[CMP1]] to i32
|
|
|
|
; CHECK-NEXT: call void @foo(i32 [[SELECT2]])
|
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i32 %x, %c
|
|
|
|
%cmp2 = icmp slt i32 %x, %c
|
|
|
|
%select1 = select i1 %cmp2, i32 -1, i32 1
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @compare_against_zero(i32 %x) {
|
|
|
|
; CHECK-LABEL: @compare_against_zero(
|
|
|
|
; CHECK-NEXT: entry:
|
[InstCombine] refine select-of-constants to bitwise ops
Add logic for the special case when a cmp+select can clearly be
reduced to just a bitwise logic instruction, and remove an
over-reaching chunk of general purpose bit magic. The primary goal
is to remove cases where we are not improving the IR instruction
count when doing these select transforms, and in all cases here that
is true.
In the motivating 3-way compare tests, there are further improvements
because we can combine/propagate select values (not sure if that
belongs in instcombine, but it's there for now).
DAGCombiner has folds to turn some of these selects into bit magic,
so there should be no difference in the end result in those cases.
Not all constant combinations are handled there yet, however, so it
is possible that some targets will see more cmov/csel codegen with
this change in IR canonicalization.
Ideally, we'll go further to *not* turn selects into multiple
logic/math ops in instcombine, and we'll canonicalize to selects.
But we should make sure that this step does not result in regressions
first (and if it does, we should fix those in the backend).
The general direction for this change was discussed here:
http://lists.llvm.org/pipermail/llvm-dev/2016-September/105373.html
http://lists.llvm.org/pipermail/llvm-dev/2017-July/114885.html
Alive proofs for the new bit magic:
https://rise4fun.com/Alive/XG7
Differential Revision: https://reviews.llvm.org/D46086
llvm-svn: 331486
2018-05-04 05:58:44 +08:00
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
2018-04-28 12:38:21 +08:00
|
|
|
; CHECK: callfoo:
|
[InstCombine] refine select-of-constants to bitwise ops
Add logic for the special case when a cmp+select can clearly be
reduced to just a bitwise logic instruction, and remove an
over-reaching chunk of general purpose bit magic. The primary goal
is to remove cases where we are not improving the IR instruction
count when doing these select transforms, and in all cases here that
is true.
In the motivating 3-way compare tests, there are further improvements
because we can combine/propagate select values (not sure if that
belongs in instcombine, but it's there for now).
DAGCombiner has folds to turn some of these selects into bit magic,
so there should be no difference in the end result in those cases.
Not all constant combinations are handled there yet, however, so it
is possible that some targets will see more cmov/csel codegen with
this change in IR canonicalization.
Ideally, we'll go further to *not* turn selects into multiple
logic/math ops in instcombine, and we'll canonicalize to selects.
But we should make sure that this step does not result in regressions
first (and if it does, we should fix those in the backend).
The general direction for this change was discussed here:
http://lists.llvm.org/pipermail/llvm-dev/2016-September/105373.html
http://lists.llvm.org/pipermail/llvm-dev/2017-July/114885.html
Alive proofs for the new bit magic:
https://rise4fun.com/Alive/XG7
Differential Revision: https://reviews.llvm.org/D46086
llvm-svn: 331486
2018-05-04 05:58:44 +08:00
|
|
|
; CHECK-NEXT: call void @foo(i32 1)
|
2018-04-28 12:38:21 +08:00
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i32 %x, 0
|
|
|
|
%cmp2 = icmp slt i32 %x, 0
|
|
|
|
%select1 = select i1 %cmp2, i32 -1, i32 1
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @compare_against_one(i32 %x) {
|
|
|
|
; CHECK-LABEL: @compare_against_one(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], 1
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
|
|
|
; CHECK: callfoo:
|
|
|
|
; CHECK-NEXT: call void @foo(i32 1)
|
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i32 %x, 1
|
|
|
|
%cmp2 = icmp slt i32 %x, 1
|
|
|
|
%select1 = select i1 %cmp2, i32 -1, i32 1
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @compare_against_two(i32 %x) {
|
|
|
|
; CHECK-LABEL: @compare_against_two(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], 2
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
|
|
|
; CHECK: callfoo:
|
|
|
|
; CHECK-NEXT: call void @foo(i32 1)
|
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i32 %x, 2
|
|
|
|
%cmp2 = icmp slt i32 %x, 2
|
|
|
|
%select1 = select i1 %cmp2, i32 -1, i32 1
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @compare_against_three(i32 %x) {
|
|
|
|
; CHECK-LABEL: @compare_against_three(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], 3
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
|
|
|
; CHECK: callfoo:
|
|
|
|
; CHECK-NEXT: call void @foo(i32 1)
|
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i32 %x, 3
|
|
|
|
%cmp2 = icmp slt i32 %x, 3
|
|
|
|
%select1 = select i1 %cmp2, i32 -1, i32 1
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @compare_against_four(i32 %x) {
|
|
|
|
; CHECK-LABEL: @compare_against_four(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], 4
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
|
|
|
; CHECK: callfoo:
|
|
|
|
; CHECK-NEXT: call void @foo(i32 1)
|
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i32 %x, 4
|
|
|
|
%cmp2 = icmp slt i32 %x, 4
|
|
|
|
%select1 = select i1 %cmp2, i32 -1, i32 1
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @compare_against_five(i32 %x) {
|
|
|
|
; CHECK-LABEL: @compare_against_five(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], 5
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
|
|
|
; CHECK: callfoo:
|
|
|
|
; CHECK-NEXT: call void @foo(i32 1)
|
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i32 %x, 5
|
|
|
|
%cmp2 = icmp slt i32 %x, 5
|
|
|
|
%select1 = select i1 %cmp2, i32 -1, i32 1
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @compare_against_six(i32 %x) {
|
|
|
|
; CHECK-LABEL: @compare_against_six(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], 6
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
|
|
|
; CHECK: callfoo:
|
|
|
|
; CHECK-NEXT: call void @foo(i32 1)
|
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i32 %x, 6
|
|
|
|
%cmp2 = icmp slt i32 %x, 6
|
|
|
|
%select1 = select i1 %cmp2, i32 -1, i32 1
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
; Same as @compare_against_arbitrary_value, but now the three-way comparison
|
|
|
|
; returns not idiomatic comparator's result (-1, 0, 1) but some other constants.
|
|
|
|
define i32 @compare_against_arbitrary_value_non_idiomatic_1(i32 %x, i32 %c) {
|
|
|
|
; CHECK-LABEL: @compare_against_arbitrary_value_non_idiomatic_1(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], [[C:%.*]]
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
|
|
|
; CHECK: callfoo:
|
|
|
|
; CHECK-NEXT: call void @foo(i32 425)
|
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i32 %x, %c
|
|
|
|
%cmp2 = icmp slt i32 %x, %c
|
|
|
|
%select1 = select i1 %cmp2, i32 -6, i32 425
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @compare_against_zero_non_idiomatic_add(i32 %x) {
|
|
|
|
; CHECK-LABEL: @compare_against_zero_non_idiomatic_add(
|
|
|
|
; CHECK-NEXT: entry:
|
[InstCombine] refine select-of-constants to bitwise ops
Add logic for the special case when a cmp+select can clearly be
reduced to just a bitwise logic instruction, and remove an
over-reaching chunk of general purpose bit magic. The primary goal
is to remove cases where we are not improving the IR instruction
count when doing these select transforms, and in all cases here that
is true.
In the motivating 3-way compare tests, there are further improvements
because we can combine/propagate select values (not sure if that
belongs in instcombine, but it's there for now).
DAGCombiner has folds to turn some of these selects into bit magic,
so there should be no difference in the end result in those cases.
Not all constant combinations are handled there yet, however, so it
is possible that some targets will see more cmov/csel codegen with
this change in IR canonicalization.
Ideally, we'll go further to *not* turn selects into multiple
logic/math ops in instcombine, and we'll canonicalize to selects.
But we should make sure that this step does not result in regressions
first (and if it does, we should fix those in the backend).
The general direction for this change was discussed here:
http://lists.llvm.org/pipermail/llvm-dev/2016-September/105373.html
http://lists.llvm.org/pipermail/llvm-dev/2017-July/114885.html
Alive proofs for the new bit magic:
https://rise4fun.com/Alive/XG7
Differential Revision: https://reviews.llvm.org/D46086
llvm-svn: 331486
2018-05-04 05:58:44 +08:00
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
2018-04-28 12:38:21 +08:00
|
|
|
; CHECK: callfoo:
|
[InstCombine] refine select-of-constants to bitwise ops
Add logic for the special case when a cmp+select can clearly be
reduced to just a bitwise logic instruction, and remove an
over-reaching chunk of general purpose bit magic. The primary goal
is to remove cases where we are not improving the IR instruction
count when doing these select transforms, and in all cases here that
is true.
In the motivating 3-way compare tests, there are further improvements
because we can combine/propagate select values (not sure if that
belongs in instcombine, but it's there for now).
DAGCombiner has folds to turn some of these selects into bit magic,
so there should be no difference in the end result in those cases.
Not all constant combinations are handled there yet, however, so it
is possible that some targets will see more cmov/csel codegen with
this change in IR canonicalization.
Ideally, we'll go further to *not* turn selects into multiple
logic/math ops in instcombine, and we'll canonicalize to selects.
But we should make sure that this step does not result in regressions
first (and if it does, we should fix those in the backend).
The general direction for this change was discussed here:
http://lists.llvm.org/pipermail/llvm-dev/2016-September/105373.html
http://lists.llvm.org/pipermail/llvm-dev/2017-July/114885.html
Alive proofs for the new bit magic:
https://rise4fun.com/Alive/XG7
Differential Revision: https://reviews.llvm.org/D46086
llvm-svn: 331486
2018-05-04 05:58:44 +08:00
|
|
|
; CHECK-NEXT: call void @foo(i32 425)
|
2018-04-28 12:38:21 +08:00
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i32 %x, 0
|
|
|
|
%cmp2 = icmp slt i32 %x, 0
|
|
|
|
%select1 = select i1 %cmp2, i32 -6, i32 425
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
; Same as @compare_against_arbitrary_value, but now the three-way comparison
|
|
|
|
; returns not idiomatic comparator's result (-1, 0, 1) but some other constants.
|
|
|
|
define i32 @compare_against_arbitrary_value_non_idiomatic_2(i32 %x, i32 %c) {
|
|
|
|
; CHECK-LABEL: @compare_against_arbitrary_value_non_idiomatic_2(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], [[C:%.*]]
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
|
|
|
; CHECK: callfoo:
|
|
|
|
; CHECK-NEXT: call void @foo(i32 425)
|
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i32 %x, %c
|
|
|
|
%cmp2 = icmp slt i32 %x, %c
|
|
|
|
%select1 = select i1 %cmp2, i32 -5, i32 425
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @compare_against_zero_non_idiomatic_or(i32 %x) {
|
|
|
|
; CHECK-LABEL: @compare_against_zero_non_idiomatic_or(
|
|
|
|
; CHECK-NEXT: entry:
|
[InstCombine] refine select-of-constants to bitwise ops
Add logic for the special case when a cmp+select can clearly be
reduced to just a bitwise logic instruction, and remove an
over-reaching chunk of general purpose bit magic. The primary goal
is to remove cases where we are not improving the IR instruction
count when doing these select transforms, and in all cases here that
is true.
In the motivating 3-way compare tests, there are further improvements
because we can combine/propagate select values (not sure if that
belongs in instcombine, but it's there for now).
DAGCombiner has folds to turn some of these selects into bit magic,
so there should be no difference in the end result in those cases.
Not all constant combinations are handled there yet, however, so it
is possible that some targets will see more cmov/csel codegen with
this change in IR canonicalization.
Ideally, we'll go further to *not* turn selects into multiple
logic/math ops in instcombine, and we'll canonicalize to selects.
But we should make sure that this step does not result in regressions
first (and if it does, we should fix those in the backend).
The general direction for this change was discussed here:
http://lists.llvm.org/pipermail/llvm-dev/2016-September/105373.html
http://lists.llvm.org/pipermail/llvm-dev/2017-July/114885.html
Alive proofs for the new bit magic:
https://rise4fun.com/Alive/XG7
Differential Revision: https://reviews.llvm.org/D46086
llvm-svn: 331486
2018-05-04 05:58:44 +08:00
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
2018-04-28 12:38:21 +08:00
|
|
|
; CHECK: callfoo:
|
[InstCombine] refine select-of-constants to bitwise ops
Add logic for the special case when a cmp+select can clearly be
reduced to just a bitwise logic instruction, and remove an
over-reaching chunk of general purpose bit magic. The primary goal
is to remove cases where we are not improving the IR instruction
count when doing these select transforms, and in all cases here that
is true.
In the motivating 3-way compare tests, there are further improvements
because we can combine/propagate select values (not sure if that
belongs in instcombine, but it's there for now).
DAGCombiner has folds to turn some of these selects into bit magic,
so there should be no difference in the end result in those cases.
Not all constant combinations are handled there yet, however, so it
is possible that some targets will see more cmov/csel codegen with
this change in IR canonicalization.
Ideally, we'll go further to *not* turn selects into multiple
logic/math ops in instcombine, and we'll canonicalize to selects.
But we should make sure that this step does not result in regressions
first (and if it does, we should fix those in the backend).
The general direction for this change was discussed here:
http://lists.llvm.org/pipermail/llvm-dev/2016-September/105373.html
http://lists.llvm.org/pipermail/llvm-dev/2017-July/114885.html
Alive proofs for the new bit magic:
https://rise4fun.com/Alive/XG7
Differential Revision: https://reviews.llvm.org/D46086
llvm-svn: 331486
2018-05-04 05:58:44 +08:00
|
|
|
; CHECK-NEXT: call void @foo(i32 425)
|
2018-04-28 12:38:21 +08:00
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i32 %x, 0
|
|
|
|
%cmp2 = icmp slt i32 %x, 0
|
|
|
|
%select1 = select i1 %cmp2, i32 -5, i32 425
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @compare_against_arbitrary_value_type_mismatch(i64 %x, i64 %c) {
|
|
|
|
; TODO: We can prove that if %x s> %c then %x != c, so there should be no actual
|
|
|
|
; calculations in callfoo block. @foo can be invoked with 1. We only do it
|
|
|
|
; for constants that are not 0 currently while it could be generalized.
|
|
|
|
; CHECK-LABEL: @compare_against_arbitrary_value_type_mismatch(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[X:%.*]], [[C:%.*]]
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
|
|
|
; CHECK: callfoo:
|
|
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i64 [[X]], [[C]]
|
|
|
|
; CHECK-NEXT: [[SELECT2:%.*]] = zext i1 [[CMP1]] to i32
|
|
|
|
; CHECK-NEXT: call void @foo(i32 [[SELECT2]])
|
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i64 %x, %c
|
|
|
|
%cmp2 = icmp slt i64 %x, %c
|
|
|
|
%select1 = select i1 %cmp2, i32 -1, i32 1
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @compare_against_zero_type_mismatch_idiomatic(i64 %x) {
|
|
|
|
; CHECK-LABEL: @compare_against_zero_type_mismatch_idiomatic(
|
|
|
|
; CHECK-NEXT: entry:
|
[InstCombine] refine select-of-constants to bitwise ops
Add logic for the special case when a cmp+select can clearly be
reduced to just a bitwise logic instruction, and remove an
over-reaching chunk of general purpose bit magic. The primary goal
is to remove cases where we are not improving the IR instruction
count when doing these select transforms, and in all cases here that
is true.
In the motivating 3-way compare tests, there are further improvements
because we can combine/propagate select values (not sure if that
belongs in instcombine, but it's there for now).
DAGCombiner has folds to turn some of these selects into bit magic,
so there should be no difference in the end result in those cases.
Not all constant combinations are handled there yet, however, so it
is possible that some targets will see more cmov/csel codegen with
this change in IR canonicalization.
Ideally, we'll go further to *not* turn selects into multiple
logic/math ops in instcombine, and we'll canonicalize to selects.
But we should make sure that this step does not result in regressions
first (and if it does, we should fix those in the backend).
The general direction for this change was discussed here:
http://lists.llvm.org/pipermail/llvm-dev/2016-September/105373.html
http://lists.llvm.org/pipermail/llvm-dev/2017-July/114885.html
Alive proofs for the new bit magic:
https://rise4fun.com/Alive/XG7
Differential Revision: https://reviews.llvm.org/D46086
llvm-svn: 331486
2018-05-04 05:58:44 +08:00
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
2018-04-28 12:38:21 +08:00
|
|
|
; CHECK: callfoo:
|
[InstCombine] refine select-of-constants to bitwise ops
Add logic for the special case when a cmp+select can clearly be
reduced to just a bitwise logic instruction, and remove an
over-reaching chunk of general purpose bit magic. The primary goal
is to remove cases where we are not improving the IR instruction
count when doing these select transforms, and in all cases here that
is true.
In the motivating 3-way compare tests, there are further improvements
because we can combine/propagate select values (not sure if that
belongs in instcombine, but it's there for now).
DAGCombiner has folds to turn some of these selects into bit magic,
so there should be no difference in the end result in those cases.
Not all constant combinations are handled there yet, however, so it
is possible that some targets will see more cmov/csel codegen with
this change in IR canonicalization.
Ideally, we'll go further to *not* turn selects into multiple
logic/math ops in instcombine, and we'll canonicalize to selects.
But we should make sure that this step does not result in regressions
first (and if it does, we should fix those in the backend).
The general direction for this change was discussed here:
http://lists.llvm.org/pipermail/llvm-dev/2016-September/105373.html
http://lists.llvm.org/pipermail/llvm-dev/2017-July/114885.html
Alive proofs for the new bit magic:
https://rise4fun.com/Alive/XG7
Differential Revision: https://reviews.llvm.org/D46086
llvm-svn: 331486
2018-05-04 05:58:44 +08:00
|
|
|
; CHECK-NEXT: call void @foo(i32 1)
|
2018-04-28 12:38:21 +08:00
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i64 %x, 0
|
|
|
|
%cmp2 = icmp slt i64 %x, 0
|
|
|
|
%select1 = select i1 %cmp2, i32 -1, i32 1
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @compare_against_zero_type_mismatch_non_idiomatic_1(i64 %x) {
|
|
|
|
; CHECK-LABEL: @compare_against_zero_type_mismatch_non_idiomatic_1(
|
|
|
|
; CHECK-NEXT: entry:
|
[InstCombine] refine select-of-constants to bitwise ops
Add logic for the special case when a cmp+select can clearly be
reduced to just a bitwise logic instruction, and remove an
over-reaching chunk of general purpose bit magic. The primary goal
is to remove cases where we are not improving the IR instruction
count when doing these select transforms, and in all cases here that
is true.
In the motivating 3-way compare tests, there are further improvements
because we can combine/propagate select values (not sure if that
belongs in instcombine, but it's there for now).
DAGCombiner has folds to turn some of these selects into bit magic,
so there should be no difference in the end result in those cases.
Not all constant combinations are handled there yet, however, so it
is possible that some targets will see more cmov/csel codegen with
this change in IR canonicalization.
Ideally, we'll go further to *not* turn selects into multiple
logic/math ops in instcombine, and we'll canonicalize to selects.
But we should make sure that this step does not result in regressions
first (and if it does, we should fix those in the backend).
The general direction for this change was discussed here:
http://lists.llvm.org/pipermail/llvm-dev/2016-September/105373.html
http://lists.llvm.org/pipermail/llvm-dev/2017-July/114885.html
Alive proofs for the new bit magic:
https://rise4fun.com/Alive/XG7
Differential Revision: https://reviews.llvm.org/D46086
llvm-svn: 331486
2018-05-04 05:58:44 +08:00
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
2018-04-28 12:38:21 +08:00
|
|
|
; CHECK: callfoo:
|
[InstCombine] refine select-of-constants to bitwise ops
Add logic for the special case when a cmp+select can clearly be
reduced to just a bitwise logic instruction, and remove an
over-reaching chunk of general purpose bit magic. The primary goal
is to remove cases where we are not improving the IR instruction
count when doing these select transforms, and in all cases here that
is true.
In the motivating 3-way compare tests, there are further improvements
because we can combine/propagate select values (not sure if that
belongs in instcombine, but it's there for now).
DAGCombiner has folds to turn some of these selects into bit magic,
so there should be no difference in the end result in those cases.
Not all constant combinations are handled there yet, however, so it
is possible that some targets will see more cmov/csel codegen with
this change in IR canonicalization.
Ideally, we'll go further to *not* turn selects into multiple
logic/math ops in instcombine, and we'll canonicalize to selects.
But we should make sure that this step does not result in regressions
first (and if it does, we should fix those in the backend).
The general direction for this change was discussed here:
http://lists.llvm.org/pipermail/llvm-dev/2016-September/105373.html
http://lists.llvm.org/pipermail/llvm-dev/2017-July/114885.html
Alive proofs for the new bit magic:
https://rise4fun.com/Alive/XG7
Differential Revision: https://reviews.llvm.org/D46086
llvm-svn: 331486
2018-05-04 05:58:44 +08:00
|
|
|
; CHECK-NEXT: call void @foo(i32 1)
|
2018-04-28 12:38:21 +08:00
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i64 %x, 0
|
|
|
|
%cmp2 = icmp slt i64 %x, 0
|
|
|
|
%select1 = select i1 %cmp2, i32 -7, i32 1
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @compare_against_zero_type_mismatch_non_idiomatic_2(i64 %x) {
|
|
|
|
; CHECK-LABEL: @compare_against_zero_type_mismatch_non_idiomatic_2(
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[X:%.*]], 0
|
|
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
|
|
|
|
; CHECK: callfoo:
|
|
|
|
; CHECK-NEXT: call void @foo(i32 1)
|
|
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
|
|
; CHECK: exit:
|
|
|
|
; CHECK-NEXT: ret i32 42
|
|
|
|
;
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%cmp1 = icmp eq i64 %x, 0
|
|
|
|
%cmp2 = icmp slt i64 %x, 0
|
|
|
|
%select1 = select i1 %cmp2, i32 -6, i32 1
|
|
|
|
%select2 = select i1 %cmp1, i32 0, i32 %select1
|
|
|
|
%cond = icmp sgt i32 %select2, 0
|
|
|
|
br i1 %cond, label %callfoo, label %exit
|
|
|
|
|
|
|
|
callfoo:
|
|
|
|
call void @foo(i32 %select2)
|
|
|
|
br label %exit
|
|
|
|
|
|
|
|
exit:
|
|
|
|
ret i32 42
|
|
|
|
}
|
|
|
|
|