summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/constant_folding.cc20
-rw-r--r--test/442-checker-constant-folding/src/Main.java17
2 files changed, 37 insertions, 0 deletions
diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc
index 09e7cabfa4..2031707759 100644
--- a/compiler/optimizing/constant_folding.cc
+++ b/compiler/optimizing/constant_folding.cc
@@ -217,6 +217,7 @@ void InstructionWithAbsorbingInputSimplifier::VisitBelowOrEqual(HBelowOrEqual* i
}
void InstructionWithAbsorbingInputSimplifier::VisitAnd(HAnd* instruction) {
+ DataType::Type type = instruction->GetType();
HConstant* input_cst = instruction->GetConstantRight();
if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) {
// Replace code looking like
@@ -226,6 +227,25 @@ void InstructionWithAbsorbingInputSimplifier::VisitAnd(HAnd* instruction) {
instruction->ReplaceWith(input_cst);
instruction->GetBlock()->RemoveInstruction(instruction);
}
+
+ HInstruction* left = instruction->GetLeft();
+ HInstruction* right = instruction->GetRight();
+
+ if (left->IsNot() ^ right->IsNot()) {
+ // Replace code looking like
+ // NOT notsrc, src
+ // AND dst, notsrc, src
+ // with
+ // CONSTANT 0
+ HInstruction* hnot = (left->IsNot() ? left : right);
+ HInstruction* hother = (left->IsNot() ? right : left);
+ HInstruction* src = hnot->AsNot()->GetInput();
+
+ if (src == hother) {
+ instruction->ReplaceWith(GetGraph()->GetConstant(type, 0));
+ instruction->GetBlock()->RemoveInstruction(instruction);
+ }
+ }
}
void InstructionWithAbsorbingInputSimplifier::VisitCompare(HCompare* instruction) {
diff --git a/test/442-checker-constant-folding/src/Main.java b/test/442-checker-constant-folding/src/Main.java
index 3d9294304d..45157abf1a 100644
--- a/test/442-checker-constant-folding/src/Main.java
+++ b/test/442-checker-constant-folding/src/Main.java
@@ -864,6 +864,23 @@ public class Main {
return lhs & rhs;
}
+ /// CHECK-START: int Main.AndSelfNegated(int) constant_folding (before)
+ /// CHECK-DAG: <<Arg:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Not:i\d+>> Not [<<Arg>>]
+ /// CHECK-DAG: <<And:i\d+>> And [<<Not>>,<<Arg>>]
+ /// CHECK-DAG: Return [<<And>>]
+
+ /// CHECK-START: int Main.AndSelfNegated(int) constant_folding (after)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+ /// CHECK-DAG: Return [<<Const0>>]
+
+ /// CHECK-START: int Main.AndSelfNegated(int) constant_folding (after)
+ /// CHECK-NOT: And
+
+ public static int AndSelfNegated(int arg) {
+ return arg & ~arg;
+ }
+
/**
* Exercise constant folding on logical or.