2020-07-18 03:28:36 +08:00
|
|
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
|
|
; RUN: opt %s -instcombine -S | FileCheck %s
|
|
|
|
|
|
|
|
; Fold
|
|
|
|
; x s/ (-1 << y)
|
|
|
|
; to
|
|
|
|
; -(x >> y)
|
|
|
|
; iff x is known non-negative.
|
|
|
|
|
|
|
|
declare void @llvm.assume(i1)
|
|
|
|
|
|
|
|
define i8 @t0(i8 %x, i8 %y) {
|
|
|
|
; CHECK-LABEL: @t0(
|
|
|
|
; CHECK-NEXT: [[X_IS_NONNEGATIVE:%.*]] = icmp sgt i8 [[X:%.*]], -1
|
|
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[X_IS_NONNEGATIVE]])
|
[InstCombine] Fold X sdiv (-1 << C) -> -(X u>> Y) iff X is non-negative
This is the one i'm seeing as missed optimization,
although there are likely other possibilities, as usual.
There are 4 variants of a general sdiv->udiv fold:
https://rise4fun.com/Alive/VS6
Name: v0
Pre: C0 >= 0 && C1 >= 0
%r = sdiv i8 C0, C1
=>
%r = udiv i8 C0, C1
Name: v1
Pre: C0 <= 0 && C1 >= 0
%r = sdiv i8 C0, C1
=>
%t0 = udiv i8 -C0, C1
%r = sub i8 0, %t0
Name: v2
Pre: C0 >= 0 && C1 <= 0
%r = sdiv i8 C0, C1
=>
%t0 = udiv i8 C0, -C1
%r = sub i8 0, %t0
Name: v3
Pre: C0 <= 0 && C1 <= 0
%r = sdiv i8 C0, C1
=>
%r = udiv i8 -C0, -C1
If we really don't like sdiv (more than udiv that is),
and are okay with increasing instruction count (2 new negations),
and we ensure that we don't undo the fold,
then we could just implement these..
2020-07-18 03:35:21 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[X]], 5
|
|
|
|
; CHECK-NEXT: [[DIV:%.*]] = sub nsw i8 0, [[TMP1]]
|
2020-07-18 03:28:36 +08:00
|
|
|
; CHECK-NEXT: ret i8 [[DIV]]
|
|
|
|
;
|
|
|
|
%x_is_nonnegative = icmp sge i8 %x, 0
|
|
|
|
call void @llvm.assume(i1 %x_is_nonnegative)
|
|
|
|
%div = sdiv i8 %x, -32
|
|
|
|
ret i8 %div
|
|
|
|
}
|
|
|
|
define i8 @n1(i8 %x, i8 %y) {
|
|
|
|
; CHECK-LABEL: @n1(
|
|
|
|
; CHECK-NEXT: [[X_IS_NONNEGATIVE:%.*]] = icmp sgt i8 [[X:%.*]], -2
|
|
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[X_IS_NONNEGATIVE]])
|
|
|
|
; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[X]], -32
|
|
|
|
; CHECK-NEXT: ret i8 [[DIV]]
|
|
|
|
;
|
|
|
|
%x_is_nonnegative = icmp sge i8 %x, -1 ; could be negative
|
|
|
|
call void @llvm.assume(i1 %x_is_nonnegative)
|
|
|
|
%div = sdiv i8 %x, -32
|
|
|
|
ret i8 %div
|
|
|
|
}
|
|
|
|
define i8 @n2(i8 %x, i8 %y) {
|
|
|
|
; CHECK-LABEL: @n2(
|
|
|
|
; CHECK-NEXT: [[X_IS_NONNEGATIVE:%.*]] = icmp sgt i8 [[X:%.*]], -1
|
|
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[X_IS_NONNEGATIVE]])
|
|
|
|
; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[X]], -31
|
|
|
|
; CHECK-NEXT: ret i8 [[DIV]]
|
|
|
|
;
|
|
|
|
%x_is_nonnegative = icmp sge i8 %x, 0
|
|
|
|
call void @llvm.assume(i1 %x_is_nonnegative)
|
|
|
|
%div = sdiv i8 %x, -31 ; not a negative power of two
|
|
|
|
ret i8 %div
|
|
|
|
}
|