mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +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:
parent
e9fc5c66f0
commit
9a14d9afe1
@ -895,6 +895,27 @@ Value *InstCombiner::freelyNegateValue(Value *V) {
|
|||||||
I->getName() + ".neg", cast<BinaryOperator>(I)->isExact());
|
I->getName() + ".neg", cast<BinaryOperator>(I)->isExact());
|
||||||
return nullptr;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -910,18 +931,6 @@ Value *InstCombiner::freelyNegateValue(Value *V) {
|
|||||||
return Builder.CreateSub(
|
return Builder.CreateSub(
|
||||||
I->getOperand(1), I->getOperand(0), I->getName() + ".neg");
|
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.
|
// 0-(A sdiv C) => A sdiv (0-C) provided the negation doesn't overflow.
|
||||||
case Instruction::SDiv: {
|
case Instruction::SDiv: {
|
||||||
Constant *C = dyn_cast<Constant>(I->getOperand(1));
|
Constant *C = dyn_cast<Constant>(I->getOperand(1));
|
||||||
|
@ -429,9 +429,9 @@ define i8 @negate_shl_not_uses(i8 %x, i8 %y) {
|
|||||||
; CHECK-LABEL: @negate_shl_not_uses(
|
; CHECK-LABEL: @negate_shl_not_uses(
|
||||||
; CHECK-NEXT: [[O:%.*]] = xor i8 [[X:%.*]], -1
|
; CHECK-NEXT: [[O:%.*]] = xor i8 [[X:%.*]], -1
|
||||||
; CHECK-NEXT: call void @use8(i8 [[O]])
|
; CHECK-NEXT: call void @use8(i8 [[O]])
|
||||||
; CHECK-NEXT: [[S:%.*]] = shl i8 [[O]], [[Y:%.*]]
|
; CHECK-NEXT: [[O_NEG:%.*]] = add i8 [[X]], 1
|
||||||
; CHECK-NEXT: [[R:%.*]] = sub i8 0, [[S]]
|
; CHECK-NEXT: [[S_NEG:%.*]] = shl i8 [[O_NEG]], [[Y:%.*]]
|
||||||
; CHECK-NEXT: ret i8 [[R]]
|
; CHECK-NEXT: ret i8 [[S_NEG]]
|
||||||
;
|
;
|
||||||
%o = xor i8 %x, -1
|
%o = xor i8 %x, -1
|
||||||
call void @use8(i8 %o)
|
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-LABEL: @negate_mul_not_uses_vec(
|
||||||
; CHECK-NEXT: [[O:%.*]] = xor <2 x i4> [[X:%.*]], <i4 -1, i4 -1>
|
; CHECK-NEXT: [[O:%.*]] = xor <2 x i4> [[X:%.*]], <i4 -1, i4 -1>
|
||||||
; CHECK-NEXT: call void @use_v2i4(<2 x i4> [[O]])
|
; CHECK-NEXT: call void @use_v2i4(<2 x i4> [[O]])
|
||||||
; CHECK-NEXT: [[S:%.*]] = mul <2 x i4> [[O]], [[Y:%.*]]
|
; CHECK-NEXT: [[O_NEG:%.*]] = add <2 x i4> [[X]], <i4 1, i4 1>
|
||||||
; CHECK-NEXT: [[R:%.*]] = sub <2 x i4> zeroinitializer, [[S]]
|
; CHECK-NEXT: [[S_NEG:%.*]] = mul <2 x i4> [[O_NEG]], [[Y:%.*]]
|
||||||
; CHECK-NEXT: ret <2 x i4> [[R]]
|
; CHECK-NEXT: ret <2 x i4> [[S_NEG]]
|
||||||
;
|
;
|
||||||
%o = xor <2 x i4> %x, <i4 -1, i4 -1>
|
%o = xor <2 x i4> %x, <i4 -1, i4 -1>
|
||||||
call void @use_v2i4(<2 x i4> %o)
|
call void @use_v2i4(<2 x i4> %o)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user