From: David Majnemer Date: Thu, 31 Jul 2014 04:49:18 +0000 (+0000) Subject: InstSimplify: Simplify (X - (0 - Y)) if the second sub is NUW X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ec7ee070369dd4074f7ad3ac4555ebb9421b8c1a;p=oota-llvm.git InstSimplify: Simplify (X - (0 - Y)) if the second sub is NUW If the NUW bit is set for 0 - Y, we know that all values for Y other than 0 would produce a poison value. This allows us to replace (0 - Y) with 0 in the expression (X - (0 - Y)) which will ultimately leave us with X. This partially fixes PR20189. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@214384 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 7a820a58f6f..459fc92bce1 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -676,6 +676,18 @@ static Value *SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, if (Op0 == Op1) return Constant::getNullValue(Op0->getType()); + // X - (0 - Y) -> X if the second sub is NUW. + // If Y != 0, 0 - Y is a poison value. + // If Y == 0, 0 - Y simplifies to 0. + if (BinaryOperator::isNeg(Op1)) { + if (const auto *BO = dyn_cast(Op1)) { + assert(BO->getOpcode() == Instruction::Sub && + "Expected a subtraction operator!"); + if (BO->hasNoUnsignedWrap()) + return Op0; + } + } + // (X + Y) - Z -> X + (Y - Z) or Y + (X - Z) if everything simplifies. // For example, (X + Y) - Y -> X; (Y + X) - Y -> X Value *X = nullptr, *Y = nullptr, *Z = Op1; diff --git a/test/Transforms/InstSimplify/AndOrXor.ll b/test/Transforms/InstSimplify/AndOrXor.ll index c59d6c916a6..0277d39b1fc 100644 --- a/test/Transforms/InstSimplify/AndOrXor.ll +++ b/test/Transforms/InstSimplify/AndOrXor.ll @@ -20,3 +20,11 @@ define i64 @pow2b(i32 %x) { ret i64 %e2 ; CHECK: ret i64 %e } + +define i32 @sub_neg_nuw(i32 %x, i32 %y) { +; CHECK-LABEL: @sub_neg_nuw( + %neg = sub nuw i32 0, %y + %sub = sub i32 %x, %neg + ret i32 %sub +; CHECK: ret i32 %x +}