1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[InstCombine] enhance freelyNegateValue() by handling 'not'

This patch extends D77230. If we have a 'not' instruction inside a
negated expression, we can ignore extra uses of that op because the
negation has a one-to-one replacement: negate becomes increment.

Alive2 examples of the test cases:
http://volta.cs.utah.edu:8080/z/T5-u9P
http://volta.cs.utah.edu:8080/z/eT89L6

Differential Revision: https://reviews.llvm.org/D77459
This commit is contained in:
Sanjay Patel 2020-04-05 09:16:19 -04:00
parent e9fc5c66f0
commit 9a14d9afe1
2 changed files with 27 additions and 18 deletions

View File

@ -895,6 +895,27 @@ Value *InstCombiner::freelyNegateValue(Value *V) {
I->getName() + ".neg", cast<BinaryOperator>(I)->isExact());
return nullptr;
// Negation is equivalent to bitwise-not + 1.
case Instruction::Xor: {
// Special case for negate of 'not' - replace with increment:
// 0 - (~A) => ((A ^ -1) ^ -1) + 1 => A + 1
Value *A;
if (match(I, m_Not(m_Value(A))))
return Builder.CreateAdd(A, ConstantInt::get(A->getType(), 1),
I->getName() + ".neg");
// General case xor (not a 'not') requires creating a new xor, so this has a
// one-use limitation:
// 0 - (A ^ C) => ((A ^ C) ^ -1) + 1 => A ^ ~C + 1
Constant *C;
if (match(I, m_OneUse(m_Xor(m_Value(A), m_Constant(C))))) {
Value *Xor = Builder.CreateXor(A, ConstantExpr::getNot(C));
return Builder.CreateAdd(Xor, ConstantInt::get(Xor->getType(), 1),
I->getName() + ".neg");
}
return nullptr;
}
default:
break;
}
@ -910,18 +931,6 @@ Value *InstCombiner::freelyNegateValue(Value *V) {
return Builder.CreateSub(
I->getOperand(1), I->getOperand(0), I->getName() + ".neg");
// Negation is equivalent to bitwise-not + 1:
// 0 - (A ^ C) => ((A ^ C) ^ -1) + 1 => A ^ ~C + 1
case Instruction::Xor: {
Constant *C;
if (match(I->getOperand(1), m_Constant(C))) {
Value *Xor = Builder.CreateXor(I->getOperand(0), ConstantExpr::getNot(C));
return Builder.CreateAdd(Xor, ConstantInt::get(Xor->getType(), 1),
I->getName() + ".neg");
}
return nullptr;
}
// 0-(A sdiv C) => A sdiv (0-C) provided the negation doesn't overflow.
case Instruction::SDiv: {
Constant *C = dyn_cast<Constant>(I->getOperand(1));

View File

@ -429,9 +429,9 @@ define i8 @negate_shl_not_uses(i8 %x, i8 %y) {
; CHECK-LABEL: @negate_shl_not_uses(
; CHECK-NEXT: [[O:%.*]] = xor i8 [[X:%.*]], -1
; CHECK-NEXT: call void @use8(i8 [[O]])
; CHECK-NEXT: [[S:%.*]] = shl i8 [[O]], [[Y:%.*]]
; CHECK-NEXT: [[R:%.*]] = sub i8 0, [[S]]
; CHECK-NEXT: ret i8 [[R]]
; CHECK-NEXT: [[O_NEG:%.*]] = add i8 [[X]], 1
; CHECK-NEXT: [[S_NEG:%.*]] = shl i8 [[O_NEG]], [[Y:%.*]]
; CHECK-NEXT: ret i8 [[S_NEG]]
;
%o = xor i8 %x, -1
call void @use8(i8 %o)
@ -444,9 +444,9 @@ define <2 x i4> @negate_mul_not_uses_vec(<2 x i4> %x, <2 x i4> %y) {
; CHECK-LABEL: @negate_mul_not_uses_vec(
; CHECK-NEXT: [[O:%.*]] = xor <2 x i4> [[X:%.*]], <i4 -1, i4 -1>
; CHECK-NEXT: call void @use_v2i4(<2 x i4> [[O]])
; CHECK-NEXT: [[S:%.*]] = mul <2 x i4> [[O]], [[Y:%.*]]
; CHECK-NEXT: [[R:%.*]] = sub <2 x i4> zeroinitializer, [[S]]
; CHECK-NEXT: ret <2 x i4> [[R]]
; CHECK-NEXT: [[O_NEG:%.*]] = add <2 x i4> [[X]], <i4 1, i4 1>
; CHECK-NEXT: [[S_NEG:%.*]] = mul <2 x i4> [[O_NEG]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x i4> [[S_NEG]]
;
%o = xor <2 x i4> %x, <i4 -1, i4 -1>
call void @use_v2i4(<2 x i4> %o)