diff options
-rw-r--r-- | compiler/optimizing/constant_folding.cc | 51 | ||||
-rw-r--r-- | test/442-checker-constant-folding/src/Main.java | 85 |
2 files changed, 130 insertions, 6 deletions
diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc index f57d8ade16..52cbfe8322 100644 --- a/compiler/optimizing/constant_folding.cc +++ b/compiler/optimizing/constant_folding.cc @@ -876,18 +876,35 @@ void InstructionWithAbsorbingInputSimplifier::VisitMul(HMul* instruction) { void InstructionWithAbsorbingInputSimplifier::VisitOr(HOr* instruction) { HConstant* input_cst = instruction->GetConstantRight(); - - if (input_cst == nullptr) { - return; - } - - if (Int64FromConstant(input_cst) == -1) { + if (input_cst != nullptr && Int64FromConstant(input_cst) == -1) { // Replace code looking like // OR dst, src, 0xFFF...FF // with // CONSTANT 0xFFF...FF instruction->ReplaceWith(input_cst); instruction->GetBlock()->RemoveInstruction(instruction); + return; + } + + HInstruction* left = instruction->GetLeft(); + HInstruction* right = instruction->GetRight(); + if (left->IsNot() ^ right->IsNot()) { + // Replace code looking like + // NOT notsrc, src + // OR dst, notsrc, src + // with + // CONSTANT 0xFFF...FF + HInstruction* hnot = (left->IsNot() ? left : right); + HInstruction* hother = (left->IsNot() ? right : left); + HInstruction* src = hnot->AsNot()->GetInput(); + + if (src == hother) { + DCHECK(instruction->GetType() == DataType::Type::kInt32 || + instruction->GetType() == DataType::Type::kInt64); + instruction->ReplaceWith(GetGraph()->GetConstant(instruction->GetType(), -1)); + instruction->GetBlock()->RemoveInstruction(instruction); + return; + } } } @@ -974,6 +991,28 @@ void InstructionWithAbsorbingInputSimplifier::VisitXor(HXor* instruction) { HBasicBlock* block = instruction->GetBlock(); instruction->ReplaceWith(GetGraph()->GetConstant(type, 0)); block->RemoveInstruction(instruction); + return; + } + + HInstruction* left = instruction->GetLeft(); + HInstruction* right = instruction->GetRight(); + if (left->IsNot() ^ right->IsNot()) { + // Replace code looking like + // NOT notsrc, src + // XOR dst, notsrc, src + // with + // CONSTANT 0xFFF...FF + HInstruction* hnot = (left->IsNot() ? left : right); + HInstruction* hother = (left->IsNot() ? right : left); + HInstruction* src = hnot->AsNot()->GetInput(); + + if (src == hother) { + DCHECK(instruction->GetType() == DataType::Type::kInt32 || + instruction->GetType() == DataType::Type::kInt64); + instruction->ReplaceWith(GetGraph()->GetConstant(instruction->GetType(), -1)); + instruction->GetBlock()->RemoveInstruction(instruction); + return; + } } } diff --git a/test/442-checker-constant-folding/src/Main.java b/test/442-checker-constant-folding/src/Main.java index 7c6d6091ee..13c42d228d 100644 --- a/test/442-checker-constant-folding/src/Main.java +++ b/test/442-checker-constant-folding/src/Main.java @@ -886,6 +886,91 @@ public class Main { return arg & ~arg; } + /// CHECK-START: int Main.OrSelfNegated(int) constant_folding (before) + /// CHECK-DAG: <<Arg:i\d+>> ParameterValue + /// CHECK-DAG: <<Not:i\d+>> Not [<<Arg>>] + /// CHECK-DAG: <<Or:i\d+>> Or [<<Not>>,<<Arg>>] + /// CHECK-DAG: Return [<<Or>>] + + /// CHECK-START: int Main.OrSelfNegated(int) constant_folding (after) + /// CHECK-DAG: <<Const:i\d+>> IntConstant -1 + /// CHECK-DAG: Return [<<Const>>] + + /// CHECK-START: int Main.OrSelfNegated(int) constant_folding (after) + /// CHECK-NOT: Or + + public static int OrSelfNegated(int arg) { + return arg | ~arg; + } + + /// CHECK-START: int Main.XorSelfNegated(int) constant_folding (before) + /// CHECK-DAG: <<Arg:i\d+>> ParameterValue + /// CHECK-DAG: <<Not:i\d+>> Not [<<Arg>>] + /// CHECK-DAG: <<Xor:i\d+>> Xor [<<Not>>,<<Arg>>] + /// CHECK-DAG: Return [<<Xor>>] + + /// CHECK-START: int Main.XorSelfNegated(int) constant_folding (after) + /// CHECK-DAG: <<Const:i\d+>> IntConstant -1 + /// CHECK-DAG: Return [<<Const>>] + + /// CHECK-START: int Main.XorSelfNegated(int) constant_folding (after) + /// CHECK-NOT: Xor + + public static int XorSelfNegated(int arg) { + return arg ^ ~arg; + } + + /// CHECK-START: long Main.AndSelfNegated(long) constant_folding (before) + /// CHECK-DAG: <<Arg:j\d+>> ParameterValue + /// CHECK-DAG: <<Not:j\d+>> Not [<<Arg>>] + /// CHECK-DAG: <<And:j\d+>> And [<<Not>>,<<Arg>>] + /// CHECK-DAG: Return [<<And>>] + + /// CHECK-START: long Main.AndSelfNegated(long) constant_folding (after) + /// CHECK-DAG: <<Const0:j\d+>> LongConstant 0 + /// CHECK-DAG: Return [<<Const0>>] + + /// CHECK-START: long Main.AndSelfNegated(long) constant_folding (after) + /// CHECK-NOT: And + + public static long AndSelfNegated(long arg) { + return arg & ~arg; + } + + /// CHECK-START: long Main.OrSelfNegated(long) constant_folding (before) + /// CHECK-DAG: <<Arg:j\d+>> ParameterValue + /// CHECK-DAG: <<Not:j\d+>> Not [<<Arg>>] + /// CHECK-DAG: <<Or:j\d+>> Or [<<Not>>,<<Arg>>] + /// CHECK-DAG: Return [<<Or>>] + + /// CHECK-START: long Main.OrSelfNegated(long) constant_folding (after) + /// CHECK-DAG: <<Const:j\d+>> LongConstant -1 + /// CHECK-DAG: Return [<<Const>>] + + /// CHECK-START: long Main.OrSelfNegated(long) constant_folding (after) + /// CHECK-NOT: Or + + public static long OrSelfNegated(long arg) { + return arg | ~arg; + } + + /// CHECK-START: long Main.XorSelfNegated(long) constant_folding (before) + /// CHECK-DAG: <<Arg:j\d+>> ParameterValue + /// CHECK-DAG: <<Not:j\d+>> Not [<<Arg>>] + /// CHECK-DAG: <<Xor:j\d+>> Xor [<<Not>>,<<Arg>>] + /// CHECK-DAG: Return [<<Xor>>] + + /// CHECK-START: long Main.XorSelfNegated(long) constant_folding (after) + /// CHECK-DAG: <<Const:j\d+>> LongConstant -1 + /// CHECK-DAG: Return [<<Const>>] + + /// CHECK-START: long Main.XorSelfNegated(long) constant_folding (after) + /// CHECK-NOT: Xor + + public static long XorSelfNegated(long arg) { + return arg ^ ~arg; + } + /** * Exercise constant folding on logical or. |