[llvm-branch-commits] [llvm] 38ca7fa - [InstSimplify] reduce logic with inverted add/sub ops
Sanjay Patel via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Dec 21 06:19:09 PST 2020
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
More information about the llvm-branch-commits
mailing list