[InstSimplify] Fold degenerate abs of abs form

This addresses the remaining issue from D87188. Due to a series of
folds, we may end up with abs-of-abs represented as
x == 0 ? -abs(x) : abs(x). Rather than recognizing this as a special
abs pattern and doing an abs-of-abs fold on it afterwards,
I'm directly folding this to one of the select operands in InstSimplify.

The general pattern falls into the "select with operand replaced"
category, but that fold is not powerful enough to recognize that
both hands of the select are the same for value zero.

Differential Revision: https://reviews.llvm.org/D87197
This commit is contained in:
Nikita Popov 2020-09-05 21:30:55 +02:00
parent b11db3606c
commit ff218cbc84
2 changed files with 13 additions and 14 deletions

View File

@ -3965,6 +3965,15 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
if (match(FalseVal, isRotate) && TrueVal == X && CmpLHS == ShAmt &&
Pred == ICmpInst::ICMP_EQ)
return FalseVal;
// X == 0 ? abs(X) : -abs(X) --> -abs(X)
// X == 0 ? -abs(X) : abs(X) --> abs(X)
if (match(TrueVal, m_Intrinsic<Intrinsic::abs>(m_Value(X))) &&
match(FalseVal, m_Neg(m_Intrinsic<Intrinsic::abs>(m_Specific(X)))))
return FalseVal;
if (match(TrueVal, m_Neg(m_Intrinsic<Intrinsic::abs>(m_Value(X)))) &&
match(FalseVal, m_Intrinsic<Intrinsic::abs>(m_Specific(X))))
return FalseVal;
}
// Check for other compares that behave like bit test.

View File

@ -205,10 +205,7 @@ define i1 @abs_ule_int_min(i8 %x) {
define i32 @select_abs_of_abs_eq(i32 %x) {
; CHECK-LABEL: @select_abs_of_abs_eq(
; CHECK-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[ABS]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], 0
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[NEG]], i32 [[ABS]]
; CHECK-NEXT: ret i32 [[SEL]]
; CHECK-NEXT: ret i32 [[ABS]]
;
%abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
%neg = sub i32 0, %abs
@ -220,10 +217,7 @@ define i32 @select_abs_of_abs_eq(i32 %x) {
define i32 @select_abs_of_abs_ne(i32 %x) {
; CHECK-LABEL: @select_abs_of_abs_ne(
; CHECK-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[ABS]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X]], 0
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[ABS]], i32 [[NEG]]
; CHECK-NEXT: ret i32 [[SEL]]
; CHECK-NEXT: ret i32 [[ABS]]
;
%abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
%neg = sub i32 0, %abs
@ -236,9 +230,7 @@ define i32 @select_nabs_of_abs_eq(i32 %x) {
; CHECK-LABEL: @select_nabs_of_abs_eq(
; CHECK-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[ABS]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], 0
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[ABS]], i32 [[NEG]]
; CHECK-NEXT: ret i32 [[SEL]]
; CHECK-NEXT: ret i32 [[NEG]]
;
%abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
%neg = sub i32 0, %abs
@ -251,9 +243,7 @@ define i32 @select_nabs_of_abs_ne(i32 %x) {
; CHECK-LABEL: @select_nabs_of_abs_ne(
; CHECK-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[ABS]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X]], 0
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[NEG]], i32 [[ABS]]
; CHECK-NEXT: ret i32 [[SEL]]
; CHECK-NEXT: ret i32 [[NEG]]
;
%abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
%neg = sub i32 0, %abs