Author: Sanjay Patel Date: 2020-12-21T08:51:43-05:00 New Revision: 38ca7face67e8488d482b66a999d0a685806879f
URL: https://github.com/llvm/llvm-project/commit/38ca7face67e8488d482b66a999d0a685806879f DIFF: https://github.com/llvm/llvm-project/commit/38ca7face67e8488d482b66a999d0a685806879f.diff LOG: [InstSimplify] reduce logic with inverted add/sub ops https://llvm.org/PR48559 This could be part of a larger ValueTracking API, but I don't see that currently. https://rise4fun.com/Alive/gR0 Name: and Pre: C1 == ~C2 %sub = add i8 %x, C1 %sub1 = sub i8 C2, %x %r = and i8 %sub, %sub1 => %r = 0 Name: or Pre: C1 == ~C2 %sub = add i8 %x, C1 %sub1 = sub i8 C2, %x %r = or i8 %sub, %sub1 => %r = -1 Name: xor Pre: C1 == ~C2 %sub = add i8 %x, C1 %sub1 = sub i8 C2, %x %r = xor i8 %sub, %sub1 => %r = -1 Added: Modified: llvm/lib/Analysis/InstructionSimplify.cpp llvm/test/Transforms/InstSimplify/AndOrXor.ll Removed: ################################################################################ diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 55f3bc4f2923..27b73a5a8236 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -1999,6 +1999,30 @@ static Value *omitCheckForZeroBeforeInvertedMulWithOverflow(Value *Op0, return NotOp1; } +/// Given a bitwise logic op, check if the operands are add/sub with a common +/// source value and inverted constant (identity: C - X -> ~(X + ~C)). +static Value *simplifyLogicOfAddSub(Value *Op0, Value *Op1, + Instruction::BinaryOps Opcode) { + assert(Op0->getType() == Op1->getType() && "Mismatched binop types"); + assert(BinaryOperator::isBitwiseLogicOp(Opcode) && "Expected logic op"); + Value *X; + Constant *C1, *C2; + if ((match(Op0, m_Add(m_Value(X), m_Constant(C1))) && + match(Op1, m_Sub(m_Constant(C2), m_Specific(X)))) || + (match(Op1, m_Add(m_Value(X), m_Constant(C1))) && + match(Op0, m_Sub(m_Constant(C2), m_Specific(X))))) { + if (ConstantExpr::getNot(C1) == C2) { + // (X + C) & (~C - X) --> (X + C) & ~(X + C) --> 0 + // (X + C) | (~C - X) --> (X + C) | ~(X + C) --> -1 + // (X + C) ^ (~C - X) --> (X + C) ^ ~(X + C) --> -1 + Type *Ty = Op0->getType(); + return Opcode == Instruction::And ? ConstantInt::getNullValue(Ty) + : ConstantInt::getAllOnesValue(Ty); + } + } + return nullptr; +} + /// Given operands for an And, see if we can fold the result. /// If not, this returns null. static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, @@ -2035,6 +2059,9 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, if (match(Op1, m_c_Or(m_Specific(Op0), m_Value()))) return Op0; + if (Value *V = simplifyLogicOfAddSub(Op0, Op1, Instruction::And)) + return V; + // A mask that only clears known zeros of a shifted value is a no-op. Value *X; const APInt *Mask; @@ -2194,6 +2221,9 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, if (match(Op1, m_Not(m_c_And(m_Specific(Op0), m_Value())))) return Constant::getAllOnesValue(Op0->getType()); + if (Value *V = simplifyLogicOfAddSub(Op0, Op1, Instruction::Or)) + return V; + Value *A, *B; // (A & ~B) | (A ^ B) -> (A ^ B) // (~B & A) | (A ^ B) -> (A ^ B) @@ -2323,6 +2353,9 @@ static Value *SimplifyXorInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, match(Op1, m_Not(m_Specific(Op0)))) return Constant::getAllOnesValue(Op0->getType()); + if (Value *V = simplifyLogicOfAddSub(Op0, Op1, Instruction::Xor)) + return V; + // Try some generic simplifications for associative operations. if (Value *V = SimplifyAssociativeBinOp(Instruction::Xor, Op0, Op1, Q, MaxRecurse)) diff --git a/llvm/test/Transforms/InstSimplify/AndOrXor.ll b/llvm/test/Transforms/InstSimplify/AndOrXor.ll index 9e549ebefc6b..e23262835c3c 100644 --- a/llvm/test/Transforms/InstSimplify/AndOrXor.ll +++ b/llvm/test/Transforms/InstSimplify/AndOrXor.ll @@ -1053,10 +1053,7 @@ define <2 x i32> @shl_or_and3v(<2 x i16> %a, <2 x i16> %b) { define i8 @and_add_sub(i8 %x) { ; CHECK-LABEL: @and_add_sub( -; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], -1 -; CHECK-NEXT: [[S:%.*]] = sub i8 0, [[X]] -; CHECK-NEXT: [[R:%.*]] = and i8 [[A]], [[S]] -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 0 ; %a = add i8 %x, -1 %s = sub i8 0, %x @@ -1066,10 +1063,7 @@ define i8 @and_add_sub(i8 %x) { define <2 x i8> @and_sub_add(<2 x i8> %x) { ; CHECK-LABEL: @and_sub_add( -; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[X:%.*]], <i8 -4, i8 -4> -; CHECK-NEXT: [[S:%.*]] = sub <2 x i8> <i8 3, i8 3>, [[X]] -; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[S]], [[A]] -; CHECK-NEXT: ret <2 x i8> [[R]] +; CHECK-NEXT: ret <2 x i8> zeroinitializer ; %a = add <2 x i8> %x, <i8 -4, i8 -4> %s = sub <2 x i8> <i8 3, i8 3>, %x @@ -1079,10 +1073,7 @@ define <2 x i8> @and_sub_add(<2 x i8> %x) { define i89 @or_add_sub(i89 %x) { ; CHECK-LABEL: @or_add_sub( -; CHECK-NEXT: [[A:%.*]] = add i89 [[X:%.*]], 5 -; CHECK-NEXT: [[S:%.*]] = sub i89 -6, [[X]] -; CHECK-NEXT: [[R:%.*]] = or i89 [[A]], [[S]] -; CHECK-NEXT: ret i89 [[R]] +; CHECK-NEXT: ret i89 -1 ; %a = add i89 %x, 5 %s = sub i89 -6, %x @@ -1092,10 +1083,7 @@ define i89 @or_add_sub(i89 %x) { define <3 x i8> @or_sub_add(<3 x i8> %x) { ; CHECK-LABEL: @or_sub_add( -; CHECK-NEXT: [[A:%.*]] = add <3 x i8> [[X:%.*]], <i8 42, i8 -12, i8 0> -; CHECK-NEXT: [[S:%.*]] = sub <3 x i8> <i8 -43, i8 11, i8 -1>, [[X]] -; CHECK-NEXT: [[R:%.*]] = or <3 x i8> [[S]], [[A]] -; CHECK-NEXT: ret <3 x i8> [[R]] +; CHECK-NEXT: ret <3 x i8> <i8 -1, i8 -1, i8 -1> ; %a = add <3 x i8> %x, <i8 42, i8 -12, i8 0> %s = sub <3 x i8> <i8 -43, i8 11, i8 -1>, %x @@ -1106,10 +1094,7 @@ define <3 x i8> @or_sub_add(<3 x i8> %x) { define <2 x i17> @xor_add_sub(<2 x i17> %x) { ; CHECK-LABEL: @xor_add_sub( -; CHECK-NEXT: [[A:%.*]] = add <2 x i17> [[X:%.*]], <i17 3000, i17 23> -; CHECK-NEXT: [[S:%.*]] = sub <2 x i17> <i17 -3001, i17 -24>, [[X]] -; CHECK-NEXT: [[R:%.*]] = xor <2 x i17> [[A]], [[S]] -; CHECK-NEXT: ret <2 x i17> [[R]] +; CHECK-NEXT: ret <2 x i17> <i17 -1, i17 -1> ; %a = add <2 x i17> %x, <i17 3000, i17 23> %s = sub <2 x i17> <i17 -3001, i17 -24>, %x @@ -1119,10 +1104,7 @@ define <2 x i17> @xor_add_sub(<2 x i17> %x) { define i8 @xor_sub_add(i8 %x) { ; CHECK-LABEL: @xor_sub_add( -; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], 33 -; CHECK-NEXT: [[S:%.*]] = sub i8 -34, [[X]] -; CHECK-NEXT: [[R:%.*]] = xor i8 [[S]], [[A]] -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 -1 ; %a = add i8 %x, 33 %s = sub i8 -34, %x @@ -1130,6 +1112,8 @@ define i8 @xor_sub_add(i8 %x) { ret i8 %r } +; Negative test + define i8 @and_add_sub_wrong_const(i8 %x) { ; CHECK-LABEL: @and_add_sub_wrong_const( ; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], 6 @@ -1143,6 +1127,8 @@ define i8 @and_add_sub_wrong_const(i8 %x) { ret i8 %r } +; Negative test + define i8 @or_add_sub_wrong_var(i8 %x, i8 %y) { ; CHECK-LABEL: @or_add_sub_wrong_var( ; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], 5 @@ -1156,6 +1142,8 @@ define i8 @or_add_sub_wrong_var(i8 %x, i8 %y) { ret i8 %r } +; Negative test + define i8 @xor_add_sub_wrong_op(i8 %x) { ; CHECK-LABEL: @xor_add_sub_wrong_op( ; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], 5 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits