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:
parent
e9fc5c66f0
commit
9a14d9afe1
@ -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));
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user