summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Anton Romanov <anton.romanov@syntacore.com> 2024-05-30 17:05:54 +0500
committer VladimĂ­r Marko <vmarko@google.com> 2024-06-12 10:42:45 +0000
commitb658a268e2e76e429702c2929d24ebbbf909e947 (patch)
tree2366f34aecd290dcc988dbb3d1923e9471d8370e
parent05e428dacb0b4877960e3b1c0d50cb9c90f378d5 (diff)
riscv: Expand BitwiseNegatedRight to riscv64, optimize
Add BitwiseNegatedRight optimization for riscv: And + Not -> AndNot Or + Not -> OrNot Xor + Not -> XorNot By compiling facebook app using dex2oat I got: 169 cases of And + Not pattern 9 cases of Or + Not pattern 1 case of Xor + Not pattern. Test: art/test/testrunner/testrunner.py --target --64 --ndebug --optimizing Change-Id: Icc2db96770378005d2fb01176298a067e1a0e4ad
-rw-r--r--compiler/optimizing/code_generator_riscv64.cc31
-rw-r--r--compiler/optimizing/code_generator_x86.cc10
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc10
-rw-r--r--compiler/optimizing/graph_visualizer.cc6
-rw-r--r--compiler/optimizing/instruction_simplifier.cc72
-rw-r--r--compiler/optimizing/instruction_simplifier.h13
-rw-r--r--compiler/optimizing/instruction_simplifier_arm.cc1
-rw-r--r--compiler/optimizing/instruction_simplifier_arm64.cc1
-rw-r--r--compiler/optimizing/instruction_simplifier_riscv64.cc26
-rw-r--r--compiler/optimizing/instruction_simplifier_shared.cc73
-rw-r--r--compiler/optimizing/instruction_simplifier_shared.h12
-rw-r--r--compiler/optimizing/nodes.h59
-rw-r--r--compiler/optimizing/nodes_shared.h70
-rw-r--r--test/564-checker-negbitwise/src/Main.java134
14 files changed, 359 insertions, 159 deletions
diff --git a/compiler/optimizing/code_generator_riscv64.cc b/compiler/optimizing/code_generator_riscv64.cc
index 75d5db83a0..8581c38895 100644
--- a/compiler/optimizing/code_generator_riscv64.cc
+++ b/compiler/optimizing/code_generator_riscv64.cc
@@ -5440,6 +5440,37 @@ void InstructionCodeGeneratorRISCV64::VisitRiscv64ShiftAdd(HRiscv64ShiftAdd* ins
}
}
+void LocationsBuilderRISCV64::VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) {
+ DCHECK(codegen_->GetInstructionSetFeatures().HasZbb());
+ DCHECK(DataType::IsIntegralType(instruction->GetType())) << instruction->GetType();
+
+ LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
+ locations->SetInAt(0, Location::RequiresRegister());
+ locations->SetInAt(1, Location::RequiresRegister());
+ locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+}
+
+void InstructionCodeGeneratorRISCV64::VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) {
+ LocationSummary* locations = instruction->GetLocations();
+ XRegister lhs = locations->InAt(0).AsRegister<XRegister>();
+ XRegister rhs = locations->InAt(1).AsRegister<XRegister>();
+ XRegister dst = locations->Out().AsRegister<XRegister>();
+
+ switch (instruction->GetOpKind()) {
+ case HInstruction::kAnd:
+ __ Andn(dst, lhs, rhs);
+ break;
+ case HInstruction::kOr:
+ __ Orn(dst, lhs, rhs);
+ break;
+ case HInstruction::kXor:
+ __ Xnor(dst, lhs, rhs);
+ break;
+ default:
+ LOG(FATAL) << "Unreachable";
+ }
+}
+
void LocationsBuilderRISCV64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
UNUSED(instruction);
LOG(FATAL) << "Unimplemented";
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 2f6dde3df7..f549da189f 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -9302,6 +9302,16 @@ bool InstructionCodeGeneratorX86::CpuHasAvx2FeatureFlag() {
return codegen_->GetInstructionSetFeatures().HasAVX2();
}
+void LocationsBuilderX86::VisitBitwiseNegatedRight(
+ [[maybe_unused]] HBitwiseNegatedRight* instruction) {
+ LOG(FATAL) << "Unimplemented";
+}
+
+void InstructionCodeGeneratorX86::VisitBitwiseNegatedRight(
+ [[maybe_unused]] HBitwiseNegatedRight* instruction) {
+ LOG(FATAL) << "Unimplemented";
+}
+
#undef __
} // namespace x86
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 5c9ee8fea4..e2b4344be9 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -8561,6 +8561,16 @@ bool InstructionCodeGeneratorX86_64::CpuHasAvx2FeatureFlag() {
return codegen_->GetInstructionSetFeatures().HasAVX2();
}
+void LocationsBuilderX86_64::VisitBitwiseNegatedRight(
+ [[maybe_unused]] HBitwiseNegatedRight* instruction) {
+ LOG(FATAL) << "Unimplemented";
+}
+
+void InstructionCodeGeneratorX86_64::VisitBitwiseNegatedRight(
+ [[maybe_unused]] HBitwiseNegatedRight* instruction) {
+ LOG(FATAL) << "Unimplemented";
+}
+
#undef __
} // namespace x86_64
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index bc8ebb5917..46db4489d6 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -628,12 +628,12 @@ class HGraphVisualizerPrinter final : public HGraphDelegateVisitor {
DataType::ToSigned(arg_type));
}
-#if defined(ART_ENABLE_CODEGEN_arm) || defined(ART_ENABLE_CODEGEN_arm64)
- void VisitMultiplyAccumulate(HMultiplyAccumulate* instruction) override {
+ void VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) override {
StartAttributeStream("kind") << instruction->GetOpKind();
}
- void VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) override {
+#if defined(ART_ENABLE_CODEGEN_arm) || defined(ART_ENABLE_CODEGEN_arm64)
+ void VisitMultiplyAccumulate(HMultiplyAccumulate* instruction) override {
StartAttributeStream("kind") << instruction->GetOpKind();
}
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 56bbd8017f..e972e4795e 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -3405,4 +3405,76 @@ void InstructionSimplifierVisitor::VisitVecMul(HVecMul* instruction) {
}
}
+bool TryMergeNegatedInput(HBinaryOperation* op) {
+ DCHECK(op->IsAnd() || op->IsOr() || op->IsXor()) << op->DebugName();
+ HInstruction* left = op->GetLeft();
+ HInstruction* right = op->GetRight();
+
+ // Only consider the case where there is exactly one Not, with 2 Not's De
+ // Morgan's laws should be applied instead.
+ if (left->IsNot() ^ right->IsNot()) {
+ HInstruction* hnot = (left->IsNot() ? left : right);
+ HInstruction* hother = (left->IsNot() ? right : left);
+
+ // Only do the simplification if the Not has only one use and can thus be
+ // safely removed. Even though ARM64 negated bitwise operations do not have
+ // an immediate variant (only register), we still do the simplification when
+ // `hother` is a constant, because it removes an instruction if the constant
+ // cannot be encoded as an immediate:
+ // mov r0, #large_constant
+ // neg r2, r1
+ // and r0, r0, r2
+ // becomes:
+ // mov r0, #large_constant
+ // bic r0, r0, r1
+ if (hnot->HasOnlyOneNonEnvironmentUse()) {
+ // Replace code looking like
+ // NOT tmp, mask
+ // AND dst, src, tmp (respectively ORR, EOR)
+ // with
+ // BIC dst, src, mask (respectively ORN, EON)
+ HInstruction* src = hnot->AsNot()->GetInput();
+
+ HBitwiseNegatedRight* neg_op = new (hnot->GetBlock()->GetGraph()->GetAllocator())
+ HBitwiseNegatedRight(op->GetType(), op->GetKind(), hother, src, op->GetDexPc());
+
+ op->GetBlock()->ReplaceAndRemoveInstructionWith(op, neg_op);
+ hnot->GetBlock()->RemoveInstruction(hnot);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool TryMergeWithAnd(HSub* instruction) {
+ HAnd* and_instr = instruction->GetRight()->AsAndOrNull();
+ if (and_instr == nullptr) {
+ return false;
+ }
+
+ HInstruction* value = instruction->GetLeft();
+
+ HInstruction* left = and_instr->GetLeft();
+ const bool left_is_equal = left == value;
+ HInstruction* right = and_instr->GetRight();
+ const bool right_is_equal = right == value;
+ if (!left_is_equal && !right_is_equal) {
+ return false;
+ }
+
+ HBitwiseNegatedRight* bnr = new (instruction->GetBlock()->GetGraph()->GetAllocator())
+ HBitwiseNegatedRight(instruction->GetType(),
+ HInstruction::InstructionKind::kAnd,
+ value,
+ left_is_equal ? right : left,
+ instruction->GetDexPc());
+ instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, bnr);
+ // Since we don't run DCE after this phase, try to manually remove the And instruction.
+ if (!and_instr->HasUses()) {
+ and_instr->GetBlock()->RemoveInstruction(and_instr);
+ }
+ return true;
+}
+
} // namespace art
diff --git a/compiler/optimizing/instruction_simplifier.h b/compiler/optimizing/instruction_simplifier.h
index 98ebaafebc..6f9e1f334e 100644
--- a/compiler/optimizing/instruction_simplifier.h
+++ b/compiler/optimizing/instruction_simplifier.h
@@ -60,6 +60,19 @@ class InstructionSimplifier : public HOptimization {
DISALLOW_COPY_AND_ASSIGN(InstructionSimplifier);
};
+// For bitwise operations (And/Or/Xor) with a negated input, try to use
+// a negated bitwise instruction.
+bool TryMergeNegatedInput(HBinaryOperation* op);
+
+// Convert
+// i1: AND a, b
+// SUB a, i1
+// into:
+// BIC a, a, b
+//
+// It also works if `i1` is AND b, a
+bool TryMergeWithAnd(HSub* instruction);
+
} // namespace art
#endif // ART_COMPILER_OPTIMIZING_INSTRUCTION_SIMPLIFIER_H_
diff --git a/compiler/optimizing/instruction_simplifier_arm.cc b/compiler/optimizing/instruction_simplifier_arm.cc
index aefa27628b..a050f86363 100644
--- a/compiler/optimizing/instruction_simplifier_arm.cc
+++ b/compiler/optimizing/instruction_simplifier_arm.cc
@@ -18,6 +18,7 @@
#include "code_generator.h"
#include "common_arm.h"
+#include "instruction_simplifier.h"
#include "instruction_simplifier_shared.h"
#include "mirror/array-inl.h"
#include "mirror/string.h"
diff --git a/compiler/optimizing/instruction_simplifier_arm64.cc b/compiler/optimizing/instruction_simplifier_arm64.cc
index d0fbe1382b..f57448d70f 100644
--- a/compiler/optimizing/instruction_simplifier_arm64.cc
+++ b/compiler/optimizing/instruction_simplifier_arm64.cc
@@ -17,6 +17,7 @@
#include "instruction_simplifier_arm64.h"
#include "common_arm64.h"
+#include "instruction_simplifier.h"
#include "instruction_simplifier_shared.h"
#include "mirror/array-inl.h"
#include "mirror/string.h"
diff --git a/compiler/optimizing/instruction_simplifier_riscv64.cc b/compiler/optimizing/instruction_simplifier_riscv64.cc
index 0b9f8c58b1..8f47f66d8b 100644
--- a/compiler/optimizing/instruction_simplifier_riscv64.cc
+++ b/compiler/optimizing/instruction_simplifier_riscv64.cc
@@ -16,6 +16,8 @@
#include "instruction_simplifier_riscv64.h"
+#include "instruction_simplifier.h"
+
namespace art HIDDEN {
namespace riscv64 {
@@ -86,6 +88,30 @@ class InstructionSimplifierRiscv64Visitor final : public HGraphVisitor {
}
}
+ void VisitAnd(HAnd* inst) override {
+ if (TryMergeNegatedInput(inst)) {
+ RecordSimplification();
+ }
+ }
+
+ void VisitOr(HOr* inst) override {
+ if (TryMergeNegatedInput(inst)) {
+ RecordSimplification();
+ }
+ }
+
+ void VisitSub(HSub* inst) override {
+ if (TryMergeWithAnd(inst)) {
+ RecordSimplification();
+ }
+ }
+
+ void VisitXor(HXor* inst) override {
+ if (TryMergeNegatedInput(inst)) {
+ RecordSimplification();
+ }
+ }
+
OptimizingCompilerStats* stats_ = nullptr;
};
diff --git a/compiler/optimizing/instruction_simplifier_shared.cc b/compiler/optimizing/instruction_simplifier_shared.cc
index deb8f93492..b7d76da548 100644
--- a/compiler/optimizing/instruction_simplifier_shared.cc
+++ b/compiler/optimizing/instruction_simplifier_shared.cc
@@ -187,79 +187,6 @@ bool TryCombineMultiplyAccumulate(HMul* mul, InstructionSet isa) {
return false;
}
-
-bool TryMergeNegatedInput(HBinaryOperation* op) {
- DCHECK(op->IsAnd() || op->IsOr() || op->IsXor()) << op->DebugName();
- HInstruction* left = op->GetLeft();
- HInstruction* right = op->GetRight();
-
- // Only consider the case where there is exactly one Not, with 2 Not's De
- // Morgan's laws should be applied instead.
- if (left->IsNot() ^ right->IsNot()) {
- HInstruction* hnot = (left->IsNot() ? left : right);
- HInstruction* hother = (left->IsNot() ? right : left);
-
- // Only do the simplification if the Not has only one use and can thus be
- // safely removed. Even though ARM64 negated bitwise operations do not have
- // an immediate variant (only register), we still do the simplification when
- // `hother` is a constant, because it removes an instruction if the constant
- // cannot be encoded as an immediate:
- // mov r0, #large_constant
- // neg r2, r1
- // and r0, r0, r2
- // becomes:
- // mov r0, #large_constant
- // bic r0, r0, r1
- if (hnot->HasOnlyOneNonEnvironmentUse()) {
- // Replace code looking like
- // NOT tmp, mask
- // AND dst, src, tmp (respectively ORR, EOR)
- // with
- // BIC dst, src, mask (respectively ORN, EON)
- HInstruction* src = hnot->AsNot()->GetInput();
-
- HBitwiseNegatedRight* neg_op = new (hnot->GetBlock()->GetGraph()->GetAllocator())
- HBitwiseNegatedRight(op->GetType(), op->GetKind(), hother, src, op->GetDexPc());
-
- op->GetBlock()->ReplaceAndRemoveInstructionWith(op, neg_op);
- hnot->GetBlock()->RemoveInstruction(hnot);
- return true;
- }
- }
-
- return false;
-}
-
-bool TryMergeWithAnd(HSub* instruction) {
- HAnd* and_instr = instruction->GetRight()->AsAndOrNull();
- if (and_instr == nullptr) {
- return false;
- }
-
- HInstruction* value = instruction->GetLeft();
-
- HInstruction* left = and_instr->GetLeft();
- const bool left_is_equal = left == value;
- HInstruction* right = and_instr->GetRight();
- const bool right_is_equal = right == value;
- if (!left_is_equal && !right_is_equal) {
- return false;
- }
-
- HBitwiseNegatedRight* bnr = new (instruction->GetBlock()->GetGraph()->GetAllocator())
- HBitwiseNegatedRight(instruction->GetType(),
- HInstruction::InstructionKind::kAnd,
- value,
- left_is_equal ? right : left,
- instruction->GetDexPc());
- instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, bnr);
- // Since we don't run DCE after this phase, try to manually remove the And instruction.
- if (!and_instr->HasUses()) {
- and_instr->GetBlock()->RemoveInstruction(and_instr);
- }
- return true;
-}
-
bool TryExtractArrayAccessAddress(CodeGenerator* codegen,
HInstruction* access,
HInstruction* array,
diff --git a/compiler/optimizing/instruction_simplifier_shared.h b/compiler/optimizing/instruction_simplifier_shared.h
index ca6d5286c5..de70ec5a8a 100644
--- a/compiler/optimizing/instruction_simplifier_shared.h
+++ b/compiler/optimizing/instruction_simplifier_shared.h
@@ -62,18 +62,6 @@ inline bool IsSubRightSubLeftShl(HSub *sub) {
} // namespace helpers
bool TryCombineMultiplyAccumulate(HMul* mul, InstructionSet isa);
-// For bitwise operations (And/Or/Xor) with a negated input, try to use
-// a negated bitwise instruction.
-bool TryMergeNegatedInput(HBinaryOperation* op);
-
-// Convert
-// i1: AND a, b
-// SUB a, i1
-// into:
-// BIC a, a, b
-//
-// It also works if `i1` is AND b, a
-bool TryMergeWithAnd(HSub* instruction);
bool TryExtractArrayAccessAddress(CodeGenerator* codegen,
HInstruction* access,
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 89369f59f1..1e3aca64db 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1527,6 +1527,7 @@ class HLoopInformationOutwardIterator : public ValueObject {
M(ArraySet, Instruction) \
M(Below, Condition) \
M(BelowOrEqual, Condition) \
+ M(BitwiseNegatedRight, BinaryOperation) \
M(BooleanNot, UnaryOperation) \
M(BoundsCheck, Instruction) \
M(BoundType, Instruction) \
@@ -1657,7 +1658,6 @@ class HLoopInformationOutwardIterator : public ValueObject {
#define FOR_EACH_CONCRETE_INSTRUCTION_SHARED(M)
#else
#define FOR_EACH_CONCRETE_INSTRUCTION_SHARED(M) \
- M(BitwiseNegatedRight, Instruction) \
M(DataProcWithShifterOp, Instruction) \
M(MultiplyAccumulate, Instruction) \
M(IntermediateAddressIndex, Instruction)
@@ -8389,6 +8389,63 @@ class HParallelMove final : public HExpression<0> {
ArenaVector<MoveOperands> moves_;
};
+class HBitwiseNegatedRight final : public HBinaryOperation {
+ public:
+ HBitwiseNegatedRight(DataType::Type result_type,
+ InstructionKind op,
+ HInstruction* left,
+ HInstruction* right,
+ uint32_t dex_pc = kNoDexPc)
+ : HBinaryOperation(
+ kBitwiseNegatedRight, result_type, left, right, SideEffects::None(), dex_pc),
+ op_kind_(op) {
+ DCHECK(op == HInstruction::kAnd || op == HInstruction::kOr || op == HInstruction::kXor) << op;
+ }
+
+ template <typename T, typename U>
+ auto Compute(T x, U y) const -> decltype(x & ~y) {
+ static_assert(std::is_same<decltype(x & ~y), decltype(x | ~y)>::value &&
+ std::is_same<decltype(x & ~y), decltype(x ^ ~y)>::value,
+ "Inconsistent negated bitwise types");
+ switch (op_kind_) {
+ case HInstruction::kAnd:
+ return x & ~y;
+ case HInstruction::kOr:
+ return x | ~y;
+ case HInstruction::kXor:
+ return x ^ ~y;
+ default:
+ LOG(FATAL) << "Unreachable";
+ UNREACHABLE();
+ }
+ }
+
+ bool InstructionDataEquals(const HInstruction* other) const override {
+ return op_kind_ == other->AsBitwiseNegatedRight()->op_kind_;
+ }
+
+ HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()),
+ GetDexPc());
+ }
+
+ HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()),
+ GetDexPc());
+ }
+
+ InstructionKind GetOpKind() const { return op_kind_; }
+
+ DECLARE_INSTRUCTION(BitwiseNegatedRight);
+
+ protected:
+ DEFAULT_COPY_CONSTRUCTOR(BitwiseNegatedRight);
+
+ private:
+ // Specifies the bitwise operation, which will be then negated.
+ const InstructionKind op_kind_;
+};
+
// This instruction computes an intermediate address pointing in the 'middle' of an object. The
// result pointer cannot be handled by GC, so extra care is taken to make sure that this value is
// never used across anything that can trigger GC.
diff --git a/compiler/optimizing/nodes_shared.h b/compiler/optimizing/nodes_shared.h
index d627c6daee..abb9f959c0 100644
--- a/compiler/optimizing/nodes_shared.h
+++ b/compiler/optimizing/nodes_shared.h
@@ -62,76 +62,6 @@ class HMultiplyAccumulate final : public HExpression<3> {
const InstructionKind op_kind_;
};
-class HBitwiseNegatedRight final : public HBinaryOperation {
- public:
- HBitwiseNegatedRight(DataType::Type result_type,
- InstructionKind op,
- HInstruction* left,
- HInstruction* right,
- uint32_t dex_pc = kNoDexPc)
- : HBinaryOperation(kBitwiseNegatedRight,
- result_type,
- left,
- right,
- SideEffects::None(),
- dex_pc),
- op_kind_(op) {
- DCHECK(op == HInstruction::kAnd || op == HInstruction::kOr || op == HInstruction::kXor) << op;
- }
-
- template <typename T, typename U>
- auto Compute(T x, U y) const -> decltype(x & ~y) {
- static_assert(std::is_same<decltype(x & ~y), decltype(x | ~y)>::value &&
- std::is_same<decltype(x & ~y), decltype(x ^ ~y)>::value,
- "Inconsistent negated bitwise types");
- switch (op_kind_) {
- case HInstruction::kAnd:
- return x & ~y;
- case HInstruction::kOr:
- return x | ~y;
- case HInstruction::kXor:
- return x ^ ~y;
- default:
- LOG(FATAL) << "Unreachable";
- UNREACHABLE();
- }
- }
-
- bool InstructionDataEquals(const HInstruction* other) const override {
- return op_kind_ == other->AsBitwiseNegatedRight()->op_kind_;
- }
-
- HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
- return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
- }
- HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
- return GetBlock()->GetGraph()->GetLongConstant(
- Compute(x->GetValue(), y->GetValue()), GetDexPc());
- }
- HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
- [[maybe_unused]] HFloatConstant* y) const override {
- LOG(FATAL) << DebugName() << " is not defined for float values";
- UNREACHABLE();
- }
- HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
- [[maybe_unused]] HDoubleConstant* y) const override {
- LOG(FATAL) << DebugName() << " is not defined for double values";
- UNREACHABLE();
- }
-
- InstructionKind GetOpKind() const { return op_kind_; }
-
- DECLARE_INSTRUCTION(BitwiseNegatedRight);
-
- protected:
- DEFAULT_COPY_CONSTRUCTOR(BitwiseNegatedRight);
-
- private:
- // Specifies the bitwise operation, which will be then negated.
- const InstructionKind op_kind_;
-};
-
// This instruction computes part of the array access offset (data and index offset).
//
// For array accesses the element address has the following structure:
diff --git a/test/564-checker-negbitwise/src/Main.java b/test/564-checker-negbitwise/src/Main.java
index 0387af48e4..6f38542b0c 100644
--- a/test/564-checker-negbitwise/src/Main.java
+++ b/test/564-checker-negbitwise/src/Main.java
@@ -73,6 +73,27 @@ public class Main {
/// CHECK-START-ARM: int Main.$opt$noinline$notAnd(int, int) disassembly (after)
/// CHECK: bic r{{\d+}}, r{{\d+}}, r{{\d+}}
+
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_riscv64 (before)
+ /// CHECK: <<Base:i\d+>> ParameterValue
+ /// CHECK: <<Mask:i\d+>> ParameterValue
+ /// CHECK: <<Not:i\d+>> Not [<<Mask>>]
+ /// CHECK: <<Op:i\d+>> And [<<Base>>,<<Not>>]
+ /// CHECK: Return [<<Op>>]
+
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_riscv64 (after)
+ /// CHECK: <<Base:i\d+>> ParameterValue
+ /// CHECK: <<Mask:i\d+>> ParameterValue
+ /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:And
+ /// CHECK: Return [<<NegOp>>]
+
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_riscv64 (after)
+ /// CHECK-NOT: Not
+ /// CHECK-NOT: And
+
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$notAnd(int, int) disassembly (after)
+ /// CHECK: andn a{{\d+}}, a{{\d+}}, a{{\d+}}
+
public static int $opt$noinline$notAnd(int base, int mask) {
return base & ~mask;
}
@@ -122,6 +143,27 @@ public class Main {
/// CHECK-START-ARM: long Main.$opt$noinline$notOr(long, long) disassembly (after)
/// CHECK: orn r{{\d+}}, r{{\d+}}, r{{\d+}}
+
+ /// CHECK-START-RISCV64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_riscv64 (before)
+ /// CHECK: <<Base:j\d+>> ParameterValue
+ /// CHECK: <<Mask:j\d+>> ParameterValue
+ /// CHECK: <<Not:j\d+>> Not [<<Mask>>]
+ /// CHECK: <<Op:j\d+>> Or [<<Base>>,<<Not>>]
+ /// CHECK: Return [<<Op>>]
+
+ /// CHECK-START-RISCV64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_riscv64 (after)
+ /// CHECK: <<Base:j\d+>> ParameterValue
+ /// CHECK: <<Mask:j\d+>> ParameterValue
+ /// CHECK: <<NegOp:j\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Or
+ /// CHECK: Return [<<NegOp>>]
+
+ /// CHECK-START-RISCV64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_riscv64 (after)
+ /// CHECK-NOT: Not
+ /// CHECK-NOT: Or
+
+ /// CHECK-START-RISCV64: long Main.$opt$noinline$notOr(long, long) disassembly (after)
+ /// CHECK: orn a{{\d+}}, a{{\d+}}, a{{\d+}}
+
public static long $opt$noinline$notOr(long base, long mask) {
return base | ~mask;
}
@@ -168,6 +210,27 @@ public class Main {
/// CHECK-START-ARM: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (after)
/// CHECK-NOT: BitwiseNegatedRight
+
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_riscv64 (before)
+ /// CHECK: <<Base:i\d+>> ParameterValue
+ /// CHECK: <<Mask:i\d+>> ParameterValue
+ /// CHECK: <<Not:i\d+>> Not [<<Mask>>]
+ /// CHECK: <<Op:i\d+>> Xor [<<Base>>,<<Not>>]
+ /// CHECK: Return [<<Op>>]
+
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_riscv64 (after)
+ /// CHECK: <<Base:i\d+>> ParameterValue
+ /// CHECK: <<Mask:i\d+>> ParameterValue
+ /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Xor
+ /// CHECK: Return [<<NegOp>>]
+
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_riscv64 (after)
+ /// CHECK-NOT: Not
+ /// CHECK-NOT: Xor
+
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$notXor(int, int) disassembly (after)
+ /// CHECK: xnor a{{\d+}}, a{{\d+}}, a{{\d+}}
+
public static int $opt$noinline$notXor(int base, int mask) {
return base ^ ~mask;
}
@@ -203,6 +266,20 @@ public class Main {
/// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Constant>>,<<Base>>] kind:And
/// CHECK: Return [<<NegOp>>]
+
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_riscv64 (before)
+ /// CHECK: <<Base:i\d+>> ParameterValue
+ /// CHECK: <<Constant:i\d+>> IntConstant
+ /// CHECK: <<Not:i\d+>> Not [<<Base>>]
+ /// CHECK: <<Op:i\d+>> And [<<Not>>,<<Constant>>]
+ /// CHECK: Return [<<Op>>]
+
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_riscv64 (after)
+ /// CHECK: <<Base:i\d+>> ParameterValue
+ /// CHECK: <<Constant:i\d+>> IntConstant
+ /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Constant>>,<<Base>>] kind:And
+ /// CHECK: Return [<<NegOp>>]
+
public static int $opt$noinline$notAndConstant(int mask) {
return 0xf & ~mask;
}
@@ -258,6 +335,30 @@ public class Main {
/// CHECK-START-ARM: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (after)
/// CHECK-NOT: BitwiseNegatedRight
+
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_riscv64 (before)
+ /// CHECK: <<Base:i\d+>> ParameterValue
+ /// CHECK: <<Mask:i\d+>> ParameterValue
+ /// CHECK: <<One:i\d+>> IntConstant
+ /// CHECK: <<Not:i\d+>> Not [<<Mask>>]
+ /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>]
+ /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>]
+ /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>]
+ /// CHECK: Return [<<Add>>]
+
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_riscv64 (after)
+ /// CHECK: <<Base:i\d+>> ParameterValue
+ /// CHECK: <<Mask:i\d+>> ParameterValue
+ /// CHECK: <<One:i\d+>> IntConstant
+ /// CHECK: <<Not:i\d+>> Not [<<Mask>>]
+ /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>]
+ /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>]
+ /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>]
+ /// CHECK: Return [<<Add>>]
+
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_riscv64 (after)
+ /// CHECK-NOT: BitwiseNegatedRight
+
public static int $opt$noinline$notAndMultipleUses(int base, int mask) {
int tmp = ~mask;
return (tmp & 0x1) + (base & tmp);
@@ -276,6 +377,9 @@ public class Main {
/// CHECK-START-ARM: int Main.$opt$noinline$deMorganOr(int, int) instruction_simplifier_arm (after)
/// CHECK-NOT: BitwiseNegatedRight
+ /// CHECK-START-RISCV64: int Main.$opt$noinline$deMorganOr(int, int) instruction_simplifier_riscv64 (after)
+ /// CHECK-NOT: BitwiseNegatedRight
+
public static int $opt$noinline$deMorganOr(int a, int b) {
return ~a | ~b;
}
@@ -309,6 +413,21 @@ public class Main {
/// CHECK-START-ARM64: int Main.$noinline$AndSubIntoBic(int, int) instruction_simplifier_arm64 (after)
/// CHECK: BitwiseNegatedRight kind:And
+
+
+ /// CHECK-START-RISCV64: int Main.$noinline$AndSubIntoBic(int, int) instruction_simplifier_riscv64 (before)
+ /// CHECK: <<HAnd:i\d+>> And [<<Left:i\d+>>,<<Right:i\d+>>]
+ /// CHECK: Sub [<<Left>>,<<HAnd>>]
+
+ /// CHECK-START-RISCV64: int Main.$noinline$AndSubIntoBic(int, int) instruction_simplifier_riscv64 (after)
+ /// CHECK-NOT: And
+
+ /// CHECK-START-RISCV64: int Main.$noinline$AndSubIntoBic(int, int) instruction_simplifier_riscv64 (after)
+ /// CHECK-NOT: Sub
+
+ /// CHECK-START-RISCV64: int Main.$noinline$AndSubIntoBic(int, int) instruction_simplifier_riscv64 (after)
+ /// CHECK: BitwiseNegatedRight kind:And
+
public static int $noinline$AndSubIntoBic(int a, int b) {
return a - (a & b);
}
@@ -342,6 +461,21 @@ public class Main {
/// CHECK-START-ARM64: int Main.$noinline$AndSubIntoBic_v2(int, int) instruction_simplifier_arm64 (after)
/// CHECK: BitwiseNegatedRight kind:And
+
+
+ /// CHECK-START-RISCV64: int Main.$noinline$AndSubIntoBic_v2(int, int) instruction_simplifier_riscv64 (before)
+ /// CHECK: <<HAnd:i\d+>> And [<<Left:i\d+>>,<<Right:i\d+>>]
+ /// CHECK: Sub [<<Right>>,<<HAnd>>]
+
+ /// CHECK-START-RISCV64: int Main.$noinline$AndSubIntoBic_v2(int, int) instruction_simplifier_riscv64 (after)
+ /// CHECK-NOT: And
+
+ /// CHECK-START-RISCV64: int Main.$noinline$AndSubIntoBic_v2(int, int) instruction_simplifier_riscv64 (after)
+ /// CHECK-NOT: Sub
+
+ /// CHECK-START-RISCV64: int Main.$noinline$AndSubIntoBic_v2(int, int) instruction_simplifier_riscv64 (after)
+ /// CHECK: BitwiseNegatedRight kind:And
+
public static int $noinline$AndSubIntoBic_v2(int a, int b) {
return b - (a & b);
}