[PATCH] D32703: [InstCombine] check one-use before applying DeMorgan nor/nand folds
Sanjay Patel via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon May 1 10:08:51 PDT 2017
spatel created this revision.
Herald added a subscriber: mcrosier.
Splitting this off from https://reviews.llvm.org/D32665 to make sure I've thought it about correctly.
If we have:
~(~X & Y), it only makes sense to transform it to (X | ~Y) when we do not need the intermediate (~X & Y) value. In that case, we would need an extra instruction to generate ~Y + 'or' (as shown in the test changes).
It's ok if we have multiple uses of ~X or Y, however. In those cases, we won't reduce the instruction count or critical path, but we might improve throughput because we can generate ~X and ~Y in parallel. Whether that actually makes perf sense or not for a target is something we can't answer in IR.
https://reviews.llvm.org/D32703
Files:
lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
test/Transforms/InstCombine/demorgan.ll
Index: test/Transforms/InstCombine/demorgan.ll
===================================================================
--- test/Transforms/InstCombine/demorgan.ll
+++ test/Transforms/InstCombine/demorgan.ll
@@ -286,8 +286,7 @@
; CHECK-NEXT: [[NOTA:%.*]] = xor i8 %A, -1
; CHECK-NEXT: [[C:%.*]] = or i8 [[NOTA]], %B
; CHECK-NEXT: [[USE2C:%.*]] = mul i8 [[C]], 23
-; CHECK-NEXT: [[B_NOT:%.*]] = xor i8 %B, -1
-; CHECK-NEXT: [[NOTC:%.*]] = and i8 [[B_NOT]], %A
+; CHECK-NEXT: [[NOTC:%.*]] = xor i8 [[C]], -1
; CHECK-NEXT: [[R:%.*]] = sdiv i8 [[NOTC]], [[USE2C]]
; CHECK-NEXT: ret i8 [[R]]
;
@@ -330,8 +329,7 @@
; CHECK-NEXT: [[USE2A:%.*]] = mul i8 [[NOTA]], 17
; CHECK-NEXT: [[C:%.*]] = or i8 [[NOTA]], %B
; CHECK-NEXT: [[USE2C:%.*]] = mul i8 [[C]], 23
-; CHECK-NEXT: [[B_NOT:%.*]] = xor i8 %B, -1
-; CHECK-NEXT: [[NOTC:%.*]] = and i8 [[B_NOT]], %A
+; CHECK-NEXT: [[NOTC:%.*]] = xor i8 [[C]], -1
; CHECK-NEXT: [[R1:%.*]] = sdiv i8 [[NOTC]], [[USE2C]]
; CHECK-NEXT: [[R2:%.*]] = sdiv i8 [[R1]], [[USE2A]]
; CHECK-NEXT: ret i8 [[R2]]
@@ -354,8 +352,7 @@
; CHECK-NEXT: [[NOTA:%.*]] = xor i8 %A, -1
; CHECK-NEXT: [[C:%.*]] = or i8 [[NOTA]], %B
; CHECK-NEXT: [[USE2C:%.*]] = mul i8 [[C]], 23
-; CHECK-NEXT: [[B_NOT:%.*]] = xor i8 %B, -1
-; CHECK-NEXT: [[NOTC:%.*]] = and i8 [[B_NOT]], %A
+; CHECK-NEXT: [[NOTC:%.*]] = xor i8 [[C]], -1
; CHECK-NEXT: [[R1:%.*]] = sdiv i8 [[NOTC]], [[USE2C]]
; CHECK-NEXT: [[R2:%.*]] = sdiv i8 [[R1]], [[USE2B]]
; CHECK-NEXT: ret i8 [[R2]]
Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2438,16 +2438,20 @@
if (match(&I, m_Not(m_BinOp(NotOp)))) {
if (NotOp->getOpcode() == Instruction::And ||
NotOp->getOpcode() == Instruction::Or) {
- // ~(~X & Y) --> (X | ~Y) - De Morgan's Law
- // ~(~X | Y) === (X & ~Y) - De Morgan's Law
- if (dyn_castNotVal(NotOp->getOperand(1)))
- NotOp->swapOperands();
- if (Value *Op0NotVal = dyn_castNotVal(NotOp->getOperand(0))) {
- Value *NotY = Builder->CreateNot(
- NotOp->getOperand(1), NotOp->getOperand(1)->getName() + ".not");
- if (NotOp->getOpcode() == Instruction::And)
- return BinaryOperator::CreateOr(Op0NotVal, NotY);
- return BinaryOperator::CreateAnd(Op0NotVal, NotY);
+ // We must eliminate the and/or for this transform to not increase the
+ // instruction count.
+ if (NotOp->hasOneUse()) {
+ // ~(~X & Y) --> (X | ~Y) - De Morgan's Law
+ // ~(~X | Y) === (X & ~Y) - De Morgan's Law
+ if (dyn_castNotVal(NotOp->getOperand(1)))
+ NotOp->swapOperands();
+ if (Value *Op0NotVal = dyn_castNotVal(NotOp->getOperand(0))) {
+ Value *NotY = Builder->CreateNot(
+ NotOp->getOperand(1), NotOp->getOperand(1)->getName() + ".not");
+ if (NotOp->getOpcode() == Instruction::And)
+ return BinaryOperator::CreateOr(Op0NotVal, NotY);
+ return BinaryOperator::CreateAnd(Op0NotVal, NotY);
+ }
}
// ~(X & Y) --> (~X | ~Y) - De Morgan's Law
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D32703.97304.patch
Type: text/x-patch
Size: 3288 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170501/40c13bc4/attachment.bin>
More information about the llvm-commits
mailing list