forked from OSchip/llvm-project
[InstSimplify] shl nuw C, %x -> C iff signbit is set on C.
Summary: `%r = shl nuw i8 C, %x` As per langref: ``` If the nuw keyword is present, then the shift produces a poison value if it shifts out any non-zero bits. ``` Thus, if the sign bit is set on `C`, then `%x` can only be `0`, which means that `%r` can only be `C`. Or in other words, set sign bit means that the signed value is negative, so the constant is `<= 0`. https://rise4fun.com/Alive/WMk https://rise4fun.com/Alive/udv Was mentioned in D47428 review. We already handle the `0` constant, https://godbolt.org/g/UZq1sJ, so this only handles negative constants. Could use computeKnownBits() / LazyValueInfo, but the cost-benefit analysis (https://reviews.llvm.org/D47891) suggests it isn't worth it. Reviewers: spatel, craig.topper Reviewed By: spatel Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D47883 llvm-svn: 334222
This commit is contained in:
parent
1f67a3cba9
commit
2683802ba0
|
@ -1226,6 +1226,13 @@ static Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
|
|||
Value *X;
|
||||
if (match(Op0, m_Exact(m_Shr(m_Value(X), m_Specific(Op1)))))
|
||||
return X;
|
||||
|
||||
// shl nuw i8 C, %x -> C iff C has sign bit set.
|
||||
if (isNUW && match(Op0, m_Negative()))
|
||||
return Op0;
|
||||
// NOTE: could use computeKnownBits() / LazyValueInfo,
|
||||
// but the cost-benefit analysis suggests it isn't worth it.
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,9 +39,7 @@ define i32 @shl_add_nsw(i32 %NBits) {
|
|||
|
||||
define i32 @shl_add_nuw(i32 %NBits) {
|
||||
; CHECK-LABEL: @shl_add_nuw(
|
||||
; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%setbit = shl i32 1, %NBits
|
||||
%ret = add nuw i32 %setbit, -1
|
||||
|
@ -50,9 +48,7 @@ define i32 @shl_add_nuw(i32 %NBits) {
|
|||
|
||||
define i32 @shl_add_nsw_nuw(i32 %NBits) {
|
||||
; CHECK-LABEL: @shl_add_nsw_nuw(
|
||||
; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%setbit = shl i32 1, %NBits
|
||||
%ret = add nuw nsw i32 %setbit, -1
|
||||
|
@ -85,9 +81,7 @@ define i32 @shl_nsw_add_nsw(i32 %NBits) {
|
|||
|
||||
define i32 @shl_nsw_add_nuw(i32 %NBits) {
|
||||
; CHECK-LABEL: @shl_nsw_add_nuw(
|
||||
; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%setbit = shl nsw i32 1, %NBits
|
||||
%ret = add nuw i32 %setbit, -1
|
||||
|
@ -96,9 +90,7 @@ define i32 @shl_nsw_add_nuw(i32 %NBits) {
|
|||
|
||||
define i32 @shl_nsw_add_nsw_nuw(i32 %NBits) {
|
||||
; CHECK-LABEL: @shl_nsw_add_nsw_nuw(
|
||||
; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%setbit = shl nsw i32 1, %NBits
|
||||
%ret = add nuw nsw i32 %setbit, -1
|
||||
|
@ -131,9 +123,7 @@ define i32 @shl_nuw_add_nsw(i32 %NBits) {
|
|||
|
||||
define i32 @shl_nuw_add_nuw(i32 %NBits) {
|
||||
; CHECK-LABEL: @shl_nuw_add_nuw(
|
||||
; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%setbit = shl nuw i32 1, %NBits
|
||||
%ret = add nuw i32 %setbit, -1
|
||||
|
@ -142,9 +132,7 @@ define i32 @shl_nuw_add_nuw(i32 %NBits) {
|
|||
|
||||
define i32 @shl_nuw_add_nsw_nuw(i32 %NBits) {
|
||||
; CHECK-LABEL: @shl_nuw_add_nsw_nuw(
|
||||
; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%setbit = shl nuw i32 1, %NBits
|
||||
%ret = add nuw nsw i32 %setbit, -1
|
||||
|
@ -177,9 +165,7 @@ define i32 @shl_nsw_nuw_add_nsw(i32 %NBits) {
|
|||
|
||||
define i32 @shl_nsw_nuw_add_nuw(i32 %NBits) {
|
||||
; CHECK-LABEL: @shl_nsw_nuw_add_nuw(
|
||||
; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%setbit = shl nuw nsw i32 1, %NBits
|
||||
%ret = add nuw i32 %setbit, -1
|
||||
|
@ -188,9 +174,7 @@ define i32 @shl_nsw_nuw_add_nuw(i32 %NBits) {
|
|||
|
||||
define i32 @shl_nsw_nuw_add_nsw_nuw(i32 %NBits) {
|
||||
; CHECK-LABEL: @shl_nsw_nuw_add_nsw_nuw(
|
||||
; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%setbit = shl nuw nsw i32 1, %NBits
|
||||
%ret = add nuw nsw i32 %setbit, -1
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
|
||||
define i8 @shl_nuw (i8 %x) {
|
||||
; CHECK-LABEL: @shl_nuw(
|
||||
; CHECK-NEXT: [[RET:%.*]] = shl nuw i8 -1, [[X:%.*]]
|
||||
; CHECK-NEXT: ret i8 [[RET]]
|
||||
; CHECK-NEXT: ret i8 -1
|
||||
;
|
||||
%ret = shl nuw i8 -1, %x
|
||||
; nuw here means that %x can only be 0
|
||||
|
@ -19,8 +18,7 @@ define i8 @shl_nuw (i8 %x) {
|
|||
|
||||
define i8 @shl_nuw_nsw (i8 %x) {
|
||||
; CHECK-LABEL: @shl_nuw_nsw(
|
||||
; CHECK-NEXT: [[RET:%.*]] = shl nuw nsw i8 -1, [[X:%.*]]
|
||||
; CHECK-NEXT: ret i8 [[RET]]
|
||||
; CHECK-NEXT: ret i8 -1
|
||||
;
|
||||
%ret = shl nuw nsw i8 -1, %x
|
||||
; nuw here means that %x can only be 0
|
||||
|
@ -29,8 +27,7 @@ define i8 @shl_nuw_nsw (i8 %x) {
|
|||
|
||||
define i8 @shl_128 (i8 %x) {
|
||||
; CHECK-LABEL: @shl_128(
|
||||
; CHECK-NEXT: [[RET:%.*]] = shl nuw i8 -128, [[X:%.*]]
|
||||
; CHECK-NEXT: ret i8 [[RET]]
|
||||
; CHECK-NEXT: ret i8 -128
|
||||
;
|
||||
%ret = shl nuw i8 128, %x
|
||||
; 128 == 1<<7 == just the sign bit is set
|
||||
|
@ -75,8 +72,7 @@ define i8 @knownbits_negativeorzero(i8 %x, i8 %y) {
|
|||
|
||||
define <2 x i8> @shl_vec(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @shl_vec(
|
||||
; CHECK-NEXT: [[RET:%.*]] = shl nuw <2 x i8> <i8 -1, i8 -1>, [[X:%.*]]
|
||||
; CHECK-NEXT: ret <2 x i8> [[RET]]
|
||||
; CHECK-NEXT: ret <2 x i8> <i8 -1, i8 -1>
|
||||
;
|
||||
%ret = shl nuw <2 x i8> <i8 -1, i8 -1>, %x
|
||||
ret <2 x i8> %ret
|
||||
|
@ -84,8 +80,7 @@ define <2 x i8> @shl_vec(<2 x i8> %x) {
|
|||
|
||||
define <3 x i8> @shl_vec_undef(<3 x i8> %x) {
|
||||
; CHECK-LABEL: @shl_vec_undef(
|
||||
; CHECK-NEXT: [[RET:%.*]] = shl nuw <3 x i8> <i8 -1, i8 undef, i8 -1>, [[X:%.*]]
|
||||
; CHECK-NEXT: ret <3 x i8> [[RET]]
|
||||
; CHECK-NEXT: ret <3 x i8> <i8 -1, i8 undef, i8 -1>
|
||||
;
|
||||
%ret = shl nuw <3 x i8> <i8 -1, i8 undef, i8 -1>, %x
|
||||
ret <3 x i8> %ret
|
||||
|
@ -93,8 +88,7 @@ define <3 x i8> @shl_vec_undef(<3 x i8> %x) {
|
|||
|
||||
define <2 x i8> @shl_vec_nonsplat(<2 x i8> %x) {
|
||||
; CHECK-LABEL: @shl_vec_nonsplat(
|
||||
; CHECK-NEXT: [[RET:%.*]] = shl nuw <2 x i8> <i8 -1, i8 -2>, [[X:%.*]]
|
||||
; CHECK-NEXT: ret <2 x i8> [[RET]]
|
||||
; CHECK-NEXT: ret <2 x i8> <i8 -1, i8 -2>
|
||||
;
|
||||
%ret = shl nuw <2 x i8> <i8 -1, i8 -2>, %x
|
||||
ret <2 x i8> %ret
|
||||
|
|
Loading…
Reference in New Issue