From fbe55325ddce51a7fc099e1efb0d326e7a2e1ed8 Mon Sep 17 00:00:00 2001 From: Ch1n-ch1nless Date: Thu, 21 Aug 2025 20:09:59 +0300 Subject: [PATCH] cmd/compile: replace conditions to CCMP instructions on ARM64 This change introduces a new SSA pass that converts conditionals with logical AND into CMP/CCMP instruction sequences on ARM64. Fixes #71268 Change-Id: I3eba9c05b88ed6eb70350d30f6e805e6a4dddbf1 Reviewed-on: https://go-review.googlesource.com/c/go/+/698099 Reviewed-by: Keith Randall Auto-Submit: Keith Randall LUCI-TryBot-Result: Go LUCI Reviewed-by: Keith Randall Reviewed-by: Junyang Shao --- src/cmd/compile/internal/ssa/compile.go | 3 +- .../ssa/merge_conditional_branches.go | 890 ++++ .../ssa/merge_conditional_branches_test.go | 282 ++ src/cmd/compile/internal/ssa/rewrite.go | 2 +- .../internal/test/conditionalCmpConst_test.go | 4408 +++++++++++++++++ .../testdata/gen/conditionalCmpConstGen.go | 231 + test/codegen/comparisons.go | 44 +- 7 files changed, 5852 insertions(+), 8 deletions(-) create mode 100644 src/cmd/compile/internal/ssa/merge_conditional_branches.go create mode 100644 src/cmd/compile/internal/ssa/merge_conditional_branches_test.go create mode 100644 src/cmd/compile/internal/test/conditionalCmpConst_test.go create mode 100644 src/cmd/compile/internal/test/testdata/gen/conditionalCmpConstGen.go diff --git a/src/cmd/compile/internal/ssa/compile.go b/src/cmd/compile/internal/ssa/compile.go index f8cbd1c9a4..8e02da746e 100644 --- a/src/cmd/compile/internal/ssa/compile.go +++ b/src/cmd/compile/internal/ssa/compile.go @@ -501,7 +501,8 @@ var passes = [...]pass{ {name: "lowered deadcode", fn: deadcode, required: true}, {name: "checkLower", fn: checkLower, required: true}, {name: "late phielim and copyelim", fn: copyelim}, - {name: "tighten", fn: tighten, required: true}, // move values closer to their uses + {name: "tighten", fn: tighten, required: true}, // move values closer to their uses + {name: "merge conditional branches", fn: mergeConditionalBranches}, // generate conditional comparison instructions on ARM64 architecture {name: "late deadcode", fn: deadcode}, {name: "critical", fn: critical, required: true}, // remove critical edges {name: "phi tighten", fn: phiTighten}, // place rematerializable phi args near uses to reduce value lifetimes diff --git a/src/cmd/compile/internal/ssa/merge_conditional_branches.go b/src/cmd/compile/internal/ssa/merge_conditional_branches.go new file mode 100644 index 0000000000..a057759309 --- /dev/null +++ b/src/cmd/compile/internal/ssa/merge_conditional_branches.go @@ -0,0 +1,890 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssa + +import ( + "cmd/compile/internal/types" +) + +const ( + InvalidIndex = -1 + iota + TrueConditionSuccIndex // Index for true condition successor in block's successor list + FalseConditionSuccIndex // Index for false condition successor in block's successor list +) + +// mergeConditionalBranches performs if-conversion optimization on ARM64 by +// transforming nested conditional branches into conditional comparison instructions. +// +// The optimization detects patterns where two consecutive conditional branches +// implement logical AND/OR operations and replaces them with CCMP/CCMN instructions +// that execute the second conditionally based on the first comparison result. +// +// Transformation Pattern: +// +// Original CFG: +// +// if1 (outer condition) +// / \ +// / \ +// / if2 (inner condition) +// | / \ +// | / \ +// | / \ +// b1 (common) b2 (target) +// +// Transformed CFG: +// +// new_if (conditional comparison) +// / \ +// / \ +// / p (empty plain block) +// | \ +// | \ +// | \ +// b1 (common) b2 (target) +// +// Transformation Conditions: +// - Both if1 and if2 must be ARM64 conditional blocks +// - if2 must have exactly one predecessor from if1 +// - if2 must not contain memory operations or side effects +// - The transformation must preserve phi node consistency in successor blocks +// +// This optimization eliminates branch mispredictions and improves instruction-level +// parallelism by leveraging ARM64's conditional execution capabilities. +// The resulting code uses conditional comparison instructions that test the second +// condition only if the first condition evaluates to a specific value. +func mergeConditionalBranches(f *Func) { + if f.Config.arch != "arm64" { + return + } + + // We iterate in postorder to ensure we process inner conditional blocks before + // their outer counterparts. This is crucial because: + // 1. Transformations create new conditional comparisons that combine inner and outer conditions + // 2. Processing inner blocks first ensures we don't miss nested patterns + // 3. It maintains the integrity of the CFG during transformations + // Reverse order (from leaves to root) allows safe modification without affecting + // yet-to-be-processed outer structures. + blocks := f.postorder() + + for _, block := range blocks { + // outerSuccIndex: index of the outedge from if1 to if2 + // innerSuccIndex: index of the outedge from if2 to b2 + outerSuccIndex, innerSuccIndex := detectNestedIfPattern(block) + + if outerSuccIndex != InvalidIndex && innerSuccIndex != InvalidIndex { + transformNestedIfPattern(block, outerSuccIndex, innerSuccIndex) + } + } +} + +// findFirstNonEmptyPlainBlock finds the first non-empty block in a chain of empty plain blocks +// starting from the specified child index of the parent block. It skips over empty blocks +// that serve only as pass-through nodes in the control flow graph. +func findFirstNonEmptyPlainBlock(parentBlock *Block, childIndex int) *Block { + childBlock := parentBlock.Succs[childIndex].Block() + for isEmptyPlainBlock(childBlock) { + childBlock = childBlock.Succs[0].Block() + } + return childBlock +} + +// isEmptyPlainBlock checks if a block is empty (contains no values), has exactly one +// predecessor and is of kind BlockPlain. Such blocks are typically +// artifacts of previous optimizations and can be safely removed or bypassed. +func isEmptyPlainBlock(block *Block) bool { + return block.Kind == BlockPlain && + len(block.Values) == 0 && + len(block.Preds) == 1 +} + +// removeEmptyPlainBlockChain removes a chain of empty plain blocks starting from +// the specified child index of the parent block. It traverses through consecutive +// empty blocks and deletes them from the control flow graph, connecting the parent +// directly to the first non-empty block in the chain. +func removeEmptyPlainBlockChain(parentBlock *Block, childIndex int) *Block { + childBlock := parentBlock.Succs[childIndex].Block() + for isEmptyPlainBlock(childBlock) { + nextBlock := childBlock.Succs[0].Block() + removeEmptyPlainBlock(childBlock) + childBlock = nextBlock + } + return childBlock +} + +// removeEmptyPlainBlock removes a single empty plain block from the control flow graph. +// It connects the block's predecessor directly to its successor, effectively bypassing +// the empty block, and then marks the block as invalid for future cleanup. +func removeEmptyPlainBlock(block *Block) { + prevEdge := block.Preds[0] + nextEdge := block.Succs[0] + + prevEdge.b.Succs[prevEdge.i] = nextEdge + nextEdge.b.Preds[nextEdge.i] = prevEdge + + block.removePred(0) + block.removeSucc(0) + block.Reset(BlockInvalid) +} + +// detectNestedIfPattern detects nested if patterns that can be transformed to conditional comparisons. +// It examines the outer block to see if it contains a nested conditional structure that matches +// the pattern for if-conversion. Returns the outer successor index (which branch contains the +// nested condition) and internal successor index (which branch of the nested condition leads to +// the common merge point), or InvalidIndex if no pattern is detected. +func detectNestedIfPattern(outerBlock *Block) (int, int) { + if !isIfBlock(outerBlock) { + // outerBlock doesn't contain comparison + return InvalidIndex, InvalidIndex + } + + // Skip empty blocks to find actual conditional targets + // Empty plain blocks are often inserted by previous optimizations + thenBlock := findFirstNonEmptyPlainBlock(outerBlock, TrueConditionSuccIndex) + elseBlock := findFirstNonEmptyPlainBlock(outerBlock, FalseConditionSuccIndex) + if thenBlock == elseBlock { + // Both branches lead to the same block, cannot transform + return InvalidIndex, InvalidIndex + } + + // Check for cyclic patterns where a condition refers back to the original block + if thenBlock == outerBlock { + // True branch forms a cycle back to outerBlock + return detectCyclePattern(outerBlock, FalseConditionSuccIndex) + } else if elseBlock == outerBlock { + // False branch forms a cycle back to outerBlock + return detectCyclePattern(outerBlock, TrueConditionSuccIndex) + } + + outerSuccIndex := InvalidIndex + + // Check if the true branch contains a nested conditional that can be moved + if len(thenBlock.Preds) == 1 && + isIfBlock(thenBlock) && + canValuesBeMoved(thenBlock) { + // True branch contains a valid nested condition + outerSuccIndex = TrueConditionSuccIndex + } else if len(elseBlock.Preds) == 1 && + isIfBlock(elseBlock) && + canValuesBeMoved(elseBlock) { + // False branch contains a valid nested condition + outerSuccIndex = FalseConditionSuccIndex + } else { + // This chain of blocks is not in pattern. + return InvalidIndex, InvalidIndex + } + + // Tree structure: + // + // outerBlock + // / \ + // / \ + // commonBothBlock innerBlock + // / \ + // / \ + // thenBlock elseBlock + // + // outerBlock: The outer conditional block being examined + // innerBlock: The inner conditional block (nested condition) + // commonBothBlock: The block reached when the outer condition is not met + // thenBlock/elseBlock: Successors of the inner conditional block + innerBlock := findFirstNonEmptyPlainBlock(outerBlock, outerSuccIndex) + commonBothBlock := findFirstNonEmptyPlainBlock(outerBlock, outerSuccIndex^1) + thenBlock = findFirstNonEmptyPlainBlock(innerBlock, TrueConditionSuccIndex) + elseBlock = findFirstNonEmptyPlainBlock(innerBlock, FalseConditionSuccIndex) + + // Determine which inner branch leads to the common merge point + // This identifies the index to NOT common merge point + var innerSuccIndex = InvalidIndex + switch commonBothBlock { + case elseBlock: + // Pattern: (if1 && if2) or (!if1 && if2) + // False branch of if2 leads to commonBothBlock, + // that means True branch leads to b2 (target) + innerSuccIndex = TrueConditionSuccIndex + case thenBlock: + // Pattern: (if1 && !if2) or (!if1 && !if2) + // True branch of if2 leads to commonBothBlock, + // that means False branch leads to b2 (target) + innerSuccIndex = FalseConditionSuccIndex + default: + // No pattern are matched + return InvalidIndex, InvalidIndex + } + + // Critical check: ensure phi nodes in merge blocks have consistent values + // This guarantees semantic preservation after transformation + outToCommonIndex := outerSuccIndex ^ 1 // index of the outedge from outerBlock to commonBothBlock + inToCommonIndex := innerSuccIndex ^ 1 // index of the outedge from innerBlock to commonBothBlock + if !checkSameValuesInPhiNodes(outerBlock, innerBlock, outToCommonIndex, inToCommonIndex) { + return InvalidIndex, InvalidIndex + } + + return outerSuccIndex, innerSuccIndex +} + +// detectCyclePattern detects cyclic patterns where a conditional block's successor +// refers back to the original block. This handles special cases where the control +// flow forms a loop-like structure that can still be optimized with conditional comparisons. +func detectCyclePattern(outerBlock *Block, outSuccIndex int) (int, int) { + secondCondBlock := findFirstNonEmptyPlainBlock(outerBlock, outSuccIndex) + + if len(secondCondBlock.Preds) != 1 || + len(secondCondBlock.Succs) != 2 || + !isIfBlock(secondCondBlock) || + !canValuesBeMoved(secondCondBlock) { + return InvalidIndex, InvalidIndex + } + + thenBlock := findFirstNonEmptyPlainBlock(secondCondBlock, TrueConditionSuccIndex) + elseBlock := findFirstNonEmptyPlainBlock(secondCondBlock, FalseConditionSuccIndex) + + if thenBlock == elseBlock { + // Both branches pointing to same block indicates degenerate case + return InvalidIndex, InvalidIndex + } + + // Check if the cycle connects back to the original block and verify phi consistency + switch outerBlock { + case thenBlock: + // True branch of inner condition leads back to outerBlock + if !checkSameValuesInPhiNodes(outerBlock, thenBlock, outSuccIndex^1, TrueConditionSuccIndex) { + return InvalidIndex, InvalidIndex + } + return outSuccIndex, FalseConditionSuccIndex + case elseBlock: + // False branch of inner condition leads back to outerBlock + if !checkSameValuesInPhiNodes(outerBlock, elseBlock, outSuccIndex^1, FalseConditionSuccIndex) { + return InvalidIndex, InvalidIndex + } + return outSuccIndex, TrueConditionSuccIndex + default: + // Pattern was not found + return InvalidIndex, InvalidIndex + } +} + +// checkSameValuesInPhiNodes checks if phi nodes in merge blocks have the same values +// for the given successor indices. This ensures that after transformation, phi nodes +// will receive the correct values from both paths. Returns true if all phi nodes +// have consistent arguments for the specified paths. +func checkSameValuesInPhiNodes(outerBlock, innerBlock *Block, outToCommonIndex, inToCommonIndex int) bool { + // Skip empty blocks to find actual phi-containing merge blocks + // Empty blocks don't affect phi nodes but complicate path tracking + for isEmptyPlainBlock(outerBlock.Succs[outToCommonIndex].Block()) { + outerBlock = outerBlock.Succs[outToCommonIndex].Block() + outToCommonIndex = 0 // After empty block, only one path exists + } + + for isEmptyPlainBlock(innerBlock.Succs[inToCommonIndex].Block()) { + innerBlock = innerBlock.Succs[inToCommonIndex].Block() + inToCommonIndex = 0 // After empty block, only one path exists + } + + // Both paths must lead to the same merge block for transformation to be valid + if outerBlock.Succs[outToCommonIndex].Block() != innerBlock.Succs[inToCommonIndex].Block() { + panic("checkSameValuesInPhiNodes: paths do not lead to the same merge block - invalid CFG pattern for if-conversion") + } + + argIndex1 := outerBlock.Succs[outToCommonIndex].Index() + argIndex2 := innerBlock.Succs[inToCommonIndex].Index() + + resultBlock := outerBlock.Succs[outToCommonIndex].Block() + for _, v := range resultBlock.Values { + if v.Op != OpPhi { + continue + } + + // If phi arguments from different paths don't match, + // merging the conditions would produce wrong values + if v.Args[argIndex1] != v.Args[argIndex2] { + return false + } + } + + return true +} + +// canValuesBeMoved checks if all values in a block can be safely moved to another block. +// This is necessary because during transformation, values from the inner conditional +// block are moved to the outer block. Values with side effects, memory operations, +// or phi nodes cannot be moved. +func canValuesBeMoved(b *Block) bool { + for _, v := range b.Values { + if !canValueBeMoved(v) { + return false + } + } + return true +} + +// canValueBeMoved checks if a single value can be safely moved to another block. +// Returns false for values that have side effects, are memory operations, phi nodes, +// or nil checks, as moving these could change program semantics. +func canValueBeMoved(v *Value) bool { + if v.Op == OpPhi { + return false + } + if v.Type.IsMemory() { + return false + } + if v.Op.HasSideEffects() { + return false + } + if opcodeTable[v.Op].nilCheck { + return false + } + if v.MemoryArg() != nil { + return false + } + return true +} + +// isIfBlock checks if a block is a conditional block that can participate in +// if-conversion. This includes all ARM64 conditional block kinds (EQ, NE, LT, etc.) +// and zero/non-zero test blocks (Z, NZ, ZW, NZW). +func isIfBlock(b *Block) bool { + switch b.Kind { + case BlockARM64EQ, + BlockARM64NE, + BlockARM64LT, + BlockARM64LE, + BlockARM64GT, + BlockARM64GE, + BlockARM64ULT, + BlockARM64ULE, + BlockARM64UGT, + BlockARM64UGE: + return isComparisonOperation(b.Controls[0]) + case BlockARM64Z, + BlockARM64NZ, + BlockARM64ZW, + BlockARM64NZW: + return true + default: + return false + } +} + +// isComparisonOperation checks if a value represents a comparison operation +// that can be used in conditional execution. Also ensures the value has only +// one use to prevent unexpected side effects from transformation. +func isComparisonOperation(value *Value) bool { + if value.Uses != 1 { + // This value can be transformed to another value. + // New value can get another results, not which are expected. + // That why we need to check this case. + return false + } + + switch value.Op { + case OpARM64CMP, + OpARM64CMPconst, + OpARM64CMN, + OpARM64CMNconst, + OpARM64CMPW, + OpARM64CMPWconst, + OpARM64CMNW, + OpARM64CMNWconst: + return true + default: + return false + } +} + +// transformNestedIfPattern transforms a detected nested if pattern into a +// conditional comparison. This is the main transformation function that +// coordinates all the steps needed to convert the nested conditionals into +// a single conditional comparison instruction. +func transformNestedIfPattern(outerBlock *Block, outSuccIndex, inSuccIndex int) { + clearPatternFromEmptyPlainBlocks(outerBlock, outSuccIndex) + innerBlock := outerBlock.Succs[outSuccIndex].Block() + + // Transform the control flow step by step: + // 1. Transform primary comparison to standard form if needed + // 2. Transform dependent comparison to work with conditional execution + // 3. Convert to conditional comparison operation (CCMP/CCMN) + // 4. Fix comparisons with constants to use constant forms when possible + // 5. Set the new control value for the transformed block + // 6. Move all values from inner block to outer block + // 7. Eliminate the now-redundant nested block + transformPrimaryComparisonValue(outerBlock) + transformDependentComparisonValue(innerBlock) + transformToConditionalComparisonValue(outerBlock, outSuccIndex, inSuccIndex) + fixComparisonWithConstant(innerBlock, outSuccIndex) + setNewControlValue(outerBlock, innerBlock, outSuccIndex, inSuccIndex) + moveAllValues(outerBlock, innerBlock) + elimNestedBlock(innerBlock, inSuccIndex) +} + +// clearPatternFromEmptyPlainBlocks removes all empty plain blocks from the +// detected pattern to simplify the control flow graph before transformation. +func clearPatternFromEmptyPlainBlocks(outerBlock *Block, outSuccIndex int) { + innerBlock := removeEmptyPlainBlockChain(outerBlock, outSuccIndex) + removeEmptyPlainBlockChain(outerBlock, outSuccIndex^1) + + removeEmptyPlainBlockChain(innerBlock, TrueConditionSuccIndex) + removeEmptyPlainBlockChain(innerBlock, FalseConditionSuccIndex) +} + +// moveAllValues moves all values from the source block to the destination block. +// This is used to consolidate the computations from the inner conditional block +// into the outer block as part of the if-conversion process. +func moveAllValues(dest, src *Block) { + for _, value := range src.Values { + value.Block = dest + dest.Values = append(dest.Values, value) + } + src.truncateValues(0) +} + +// elimNestedBlock eliminates a nested block that has been incorporated into +// the outer block through if-conversion. It removes the specified successor +// edge and updates phi nodes in the target block to remove the corresponding argument. +func elimNestedBlock(b *Block, index int) { + removedEdge := b.Succs[index^1] + + notBothMetBlock := removedEdge.Block() + i := removedEdge.Index() + + b.removeSucc(index ^ 1) + notBothMetBlock.removePred(i) + for _, v := range notBothMetBlock.Values { + if v.Op != OpPhi { + continue + } + notBothMetBlock.removePhiArg(v, i) + } + + b.Func.invalidateCFG() + b.Reset(BlockPlain) + b.Likely = BranchUnknown +} + +// setNewControlValue sets the new control value for the transformed block +// based on the inner block's control value. It also updates the branch +// likelihood based on the original block's branch prediction. +func setNewControlValue(outerBlock, innerBlock *Block, outSuccIndex, inSuccIndex int) { + outerBlock.resetWithControl(innerBlock.Kind, innerBlock.Controls[0]) + if !isBranchLikelyConsistentWithIndex(outerBlock, outSuccIndex) || + !isBranchLikelyConsistentWithIndex(innerBlock, inSuccIndex) { + outerBlock.Likely = BranchUnknown + } +} + +// isBranchLikelyConsistentWithIndex checks if the branch likelihood matches the expected +// index. Returns true if the likelihood is consistent with the branch direction. +func isBranchLikelyConsistentWithIndex(b *Block, index int) bool { + if index == TrueConditionSuccIndex && b.Likely == BranchLikely { + return true + } else if index == FalseConditionSuccIndex && b.Likely == BranchUnlikely { + return true + } + return false +} + +// transformPrimaryComparisonValue transforms special block kinds (Z, NZ, ZW, NZW) +// into standard comparison operations. These block kinds test for zero/non-zero +// and need to be converted to explicit comparisons with zero for conditional execution. +func transformPrimaryComparisonValue(block *Block) { + switch block.Kind { + case BlockARM64Z: + arg0 := block.Controls[0] + controlValue := block.NewValue1I(arg0.Pos, OpARM64CMPconst, types.TypeFlags, 0, arg0) + block.resetWithControl(BlockARM64EQ, controlValue) + case BlockARM64NZ: + arg0 := block.Controls[0] + controlValue := block.NewValue1I(arg0.Pos, OpARM64CMPconst, types.TypeFlags, 0, arg0) + block.resetWithControl(BlockARM64NE, controlValue) + case BlockARM64ZW: + arg0 := block.Controls[0] + controlValue := block.NewValue1I(arg0.Pos, OpARM64CMPWconst, types.TypeFlags, 0, arg0) + block.resetWithControl(BlockARM64EQ, controlValue) + case BlockARM64NZW: + arg0 := block.Controls[0] + controlValue := block.NewValue1I(arg0.Pos, OpARM64CMPWconst, types.TypeFlags, 0, arg0) + block.resetWithControl(BlockARM64NE, controlValue) + default: + return + } +} + +// transformDependentComparisonValue transforms the comparison in the dependent +// (inner) block to prepare it for conditional execution. This involves converting +// constant comparisons to register comparisons and handling special block kinds. +func transformDependentComparisonValue(block *Block) { + typ := &block.Func.Config.Types + + switch block.Kind { + case BlockARM64EQ, + BlockARM64NE, + BlockARM64LT, + BlockARM64LE, + BlockARM64GT, + BlockARM64GE, + BlockARM64ULT, + BlockARM64ULE, + BlockARM64UGT, + BlockARM64UGE: + value := block.Controls[0] + + switch value.Op { + case OpARM64CMPconst: + arg0 := value.Args[0] + auxConstant := auxIntToInt64(value.AuxInt) + value.reset(OpARM64CMP) + constantValue := block.Func.constVal(OpARM64MOVDconst, typ.UInt64, auxConstant, true) + value.AddArg2(arg0, constantValue) + case OpARM64CMNconst: + arg0 := value.Args[0] + auxConstant := auxIntToInt64(value.AuxInt) + value.reset(OpARM64CMN) + constantValue := block.Func.constVal(OpARM64MOVDconst, typ.UInt64, auxConstant, true) + value.AddArg2(arg0, constantValue) + case OpARM64CMPWconst: + arg0 := value.Args[0] + auxConstant := auxIntToInt32(value.AuxInt) + value.reset(OpARM64CMPW) + constantValue := block.Func.constVal(OpARM64MOVDconst, typ.UInt64, int64(auxConstant), true) + value.AddArg2(arg0, constantValue) + case OpARM64CMNWconst: + arg0 := value.Args[0] + auxConstant := auxIntToInt32(value.AuxInt) + value.reset(OpARM64CMNW) + constantValue := block.Func.constVal(OpARM64MOVDconst, typ.UInt64, int64(auxConstant), true) + value.AddArg2(arg0, constantValue) + default: + return + } + case BlockARM64Z: + arg0 := block.Controls[0] + arg1 := block.Func.constVal(OpARM64MOVDconst, typ.UInt64, 0, true) + comparisonValue := block.NewValue2(arg0.Pos, OpARM64CMP, types.TypeFlags, arg0, arg1) + block.resetWithControl(BlockARM64EQ, comparisonValue) + case BlockARM64NZ: + arg0 := block.Controls[0] + arg1 := block.Func.constVal(OpARM64MOVDconst, typ.UInt64, 0, true) + comparisonValue := block.NewValue2(arg0.Pos, OpARM64CMP, types.TypeFlags, arg0, arg1) + block.resetWithControl(BlockARM64NE, comparisonValue) + case BlockARM64ZW: + arg0 := block.Controls[0] + arg1 := block.Func.constVal(OpARM64MOVDconst, typ.UInt64, 0, true) + comparisonValue := block.NewValue2(arg0.Pos, OpARM64CMPW, types.TypeFlags, arg0, arg1) + block.resetWithControl(BlockARM64EQ, comparisonValue) + case BlockARM64NZW: + arg0 := block.Controls[0] + arg1 := block.Func.constVal(OpARM64MOVDconst, typ.UInt64, 0, true) + comparisonValue := block.NewValue2(arg0.Pos, OpARM64CMPW, types.TypeFlags, arg0, arg1) + block.resetWithControl(BlockARM64NE, comparisonValue) + default: + panic("Wrong block kind") + } +} + +// fixComparisonWithConstant optimizes conditional comparisons by converting +// them to constant forms when one operand is a small constant. This generates +// more efficient CCMPconst/CCMNconst instructions. +func fixComparisonWithConstant(block *Block, index int) { + // Helper function to extract 5-bit immediate from int64 constant (0-31 range) + getImm64 := func(auxInt int64) (uint8, bool) { + imm := auxIntToInt64(auxInt) + if imm&^0x1f == 0 { + return uint8(imm), true + } + return 0, false + } + + // Helper function to extract 5-bit immediate from int32 constant (0-31 range) + getImm32 := func(auxInt int64) (uint8, bool) { + imm := auxIntToInt32(auxInt) + if imm&^0x1f == 0 { + return uint8(imm), true + } + return 0, false + } + + // Helper function to convert conditional comparison to constant form if possible + // Algorithm: Check if either operand is a small 5-bit constant (0-31). If found: + // 1. Convert operation to constant form (CCMP -> CCMPconst, etc.) + // 2. Set the 'ind' flag for immediate mode + // 3. When constant is first operand (arg0), swap operands and invert condition + tryConvertToConstForm := func(value *Value, newOp Op, getImm func(int64) (uint8, bool)) { + params := value.AuxArm64ConditionalParams() + arg0 := value.Args[0] + arg1 := value.Args[1] + arg2 := value.Args[2] + // Check second operand for small constant + if arg1.Op == OpARM64MOVDconst { + if imm, ok := getImm(arg1.AuxInt); ok { + value.reset(newOp) + params.constValue = imm + params.ind = true + value.AuxInt = arm64ConditionalParamsToAuxInt(params) + value.AddArg2(arg0, arg2) + return + } + } + + // Check first operand for small constant + if arg0.Op == OpARM64MOVDconst { + if imm, ok := getImm(arg0.AuxInt); ok { + value.reset(newOp) + invertConditionsInBlock(block, ¶ms, index) + params.constValue = imm + params.ind = true + value.AuxInt = arm64ConditionalParamsToAuxInt(params) + value.AddArg2(arg1, arg2) + return + } + } + } + + // try to convert control value of block to constant form + controlValue := block.Controls[0] + switch controlValue.Op { + case OpARM64CCMP: + tryConvertToConstForm(controlValue, OpARM64CCMPconst, getImm64) + case OpARM64CCMN: + tryConvertToConstForm(controlValue, OpARM64CCMNconst, getImm64) + case OpARM64CCMPW: + tryConvertToConstForm(controlValue, OpARM64CCMPWconst, getImm32) + case OpARM64CCMNW: + tryConvertToConstForm(controlValue, OpARM64CCMNWconst, getImm32) + default: + return + } +} + +// invertConditionsInBlock inverts the condition in a block and returns updated +// conditional parameters. This is used when swapping operands in constant +// optimizations to maintain correct semantics. +func invertConditionsInBlock(block *Block, params *arm64ConditionalParams, index int) { + invertKind := invertBlockKind(block.Kind) + block.Kind = invertKind + if index == FalseConditionSuccIndex { + invertKind = negateBlockKind(invertKind) + } + params.nzcv = nzcvByBlockKind(invertKind) +} + +// transformToConditionalComparisonValue transforms the comparison operations +// to conditional comparison operations (CCMP/CCMN). This is the core transformation +// that creates the conditional execution pattern by combining the outer and inner +// conditions into a single conditional comparison instruction. +func transformToConditionalComparisonValue(outerBlock *Block, outSuccIndex, inSuccIndex int) { + innerBlock := outerBlock.Succs[outSuccIndex].Block() + + // Adjust block kinds and successors if needed to match expected pattern + if outSuccIndex != inSuccIndex { + outerBlock.Kind = negateBlockKind(outerBlock.Kind) + outerBlock.swapSuccessors() + outSuccIndex ^= 1 + } + + outerControl := outerBlock.Controls[0] + outerKind := outerBlock.Kind + + innerControl := innerBlock.Controls[0] + innerKind := innerBlock.Kind + + // Adjust conditions based on successor index + if outSuccIndex == FalseConditionSuccIndex { + outerKind = negateBlockKind(outerKind) + innerKind = negateBlockKind(innerKind) + } + + // Get conditional parameters and transform the operation + params := createConditionalParamsByBlockKind(outerKind, innerKind) + + innerControl.AddArg(outerControl) + innerControl.Op = transformOpToConditionalComparisonOperation(innerControl.Op) + innerControl.AuxInt = arm64ConditionalParamsToAuxInt(params) +} + +// transformOpToConditionalComparisonOperation maps standard comparison operations +// to their conditional comparison counterparts (e.g., CMP -> CCMP, CMN -> CCMN). +func transformOpToConditionalComparisonOperation(op Op) Op { + switch op { + case OpARM64CMP: + return OpARM64CCMP + case OpARM64CMN: + return OpARM64CCMN + case OpARM64CMPconst: + return OpARM64CCMPconst + case OpARM64CMNconst: + return OpARM64CCMNconst + case OpARM64CMPW: + return OpARM64CCMPW + case OpARM64CMNW: + return OpARM64CCMNW + case OpARM64CMPWconst: + return OpARM64CCMPWconst + case OpARM64CMNWconst: + return OpARM64CCMNWconst + default: + panic("Incorrect operation") + } +} + +// createConditionalParamsByBlockKind constructs conditional parameters for ARM64 conditional instructions. +// It combines two block kinds: +// - outerKind specifies the main condition (e.g., LT, GT) to be evaluated. +// - innerKind determines the NZCV flag pattern to be used when the main condition is FALSE. +// The resulting parameters are typically used by conditional comparison operations (CCMP, CCMN). +func createConditionalParamsByBlockKind(outerKind, innerKind BlockKind) arm64ConditionalParams { + cond := condByBlockKind(outerKind) // the condition code for the primary comparison + nzcv := nzcvByBlockKind(innerKind) // NZCV flags to apply when the condition is false + return arm64ConditionalParamsAuxInt(cond, nzcv) +} + +// condByBlockKind maps block kinds to their corresponding condition codes +// for ARM64 conditional execution. +func condByBlockKind(kind BlockKind) Op { + switch kind { + case BlockARM64EQ: + return OpARM64Equal + case BlockARM64NE: + return OpARM64NotEqual + case BlockARM64LT: + return OpARM64LessThan + case BlockARM64LE: + return OpARM64LessEqual + case BlockARM64GT: + return OpARM64GreaterThan + case BlockARM64GE: + return OpARM64GreaterEqual + case BlockARM64ULT: + return OpARM64LessThanU + case BlockARM64ULE: + return OpARM64LessEqualU + case BlockARM64UGT: + return OpARM64GreaterThanU + case BlockARM64UGE: + return OpARM64GreaterEqualU + default: + panic("Incorrect kind of Block") + } +} + +// nzcvByBlockKind returns NZCV flags encoding the *logical opposite* of the specified block condition. +// The returned flags represent the processor state to be used when the primary comparison condition +// evaluates to false. +// +// Each case constructs the flag pattern for the inverse condition: +// +// EQ -> NE, LT -> GE, GT -> LE, etc. +func nzcvByBlockKind(kind BlockKind) uint8 { + switch kind { + case BlockARM64EQ: + // Encode NE : Z == 0 + return packNZCV(false, false, false, false) // N=0,Z=0,C=0,V=0 + case BlockARM64NE: + // Encode EQ : Z == 1 + return packNZCV(false, true, false, false) // N=0,Z=1,C=0,V=0 + case BlockARM64LT: + // Encode GE : N == V + return packNZCV(false, false, false, false) // N=0,Z=0,C=0,V=0 + case BlockARM64LE: + // Encode GT : (Z == 0) && (N == V) + return packNZCV(false, false, false, false) // N=0,Z=0,C=0,V=0 + case BlockARM64GT: + // Encode LE : (Z == 1) || (N != V) + return packNZCV(false, true, false, false) // N=0,Z=1,C=0,V=0 + case BlockARM64GE: + // Encode LT : N != V + return packNZCV(false, false, false, true) // N=0,Z=0,C=0,V=1 + case BlockARM64ULT: + // Encode UGE : C == 1 + return packNZCV(false, false, true, false) // N=0,Z=0,C=1,V=0 + case BlockARM64ULE: + // Encode UGT : (C == 1) && (Z == 0) + return packNZCV(false, false, true, false) // N=0,Z=0,C=1,V=0 + case BlockARM64UGT: + // Encode ULE : (C == 0) || (Z == 1) + return packNZCV(false, false, false, false) // N=0,Z=0,C=0,V=0 + case BlockARM64UGE: + // Encode ULT : C == 0 + return packNZCV(false, false, false, false) // N=0,Z=0,C=0,V=0 + default: + panic("Incorrect kind of Block") + } +} + +// packNZCV packs boolean condition flags into a single byte representing +// the ARM64 NZCV condition flags: Negative, Zero, Carry, Overflow. +func packNZCV(N, Z, C, V bool) uint8 { + var NZCVFlags uint8 = 0 + if N { + NZCVFlags |= 1 << 3 + } + if Z { + NZCVFlags |= 1 << 2 + } + if C { + NZCVFlags |= 1 << 1 + } + if V { + NZCVFlags |= 1 + } + return NZCVFlags +} + +// negateBlockKind returns the logical negation of a block kind +// (e.g., EQ becomes NE, LT becomes GE). +func negateBlockKind(kind BlockKind) BlockKind { + switch kind { + case BlockARM64EQ: + return BlockARM64NE + case BlockARM64NE: + return BlockARM64EQ + case BlockARM64LT: + return BlockARM64GE + case BlockARM64LE: + return BlockARM64GT + case BlockARM64GT: + return BlockARM64LE + case BlockARM64GE: + return BlockARM64LT + case BlockARM64ULT: + return BlockARM64UGE + case BlockARM64ULE: + return BlockARM64UGT + case BlockARM64UGT: + return BlockARM64ULE + case BlockARM64UGE: + return BlockARM64ULT + default: + panic("Incorrect kind of Block") + } +} + +// invertBlockKind inverts the operands of a comparison block kind +// (e.g., LT becomes GT, LE becomes GE). +func invertBlockKind(kind BlockKind) BlockKind { + switch kind { + case BlockARM64EQ: + return BlockARM64EQ + case BlockARM64NE: + return BlockARM64NE + case BlockARM64LT: + return BlockARM64GT + case BlockARM64LE: + return BlockARM64GE + case BlockARM64GT: + return BlockARM64LT + case BlockARM64GE: + return BlockARM64LE + case BlockARM64ULT: + return BlockARM64UGT + case BlockARM64ULE: + return BlockARM64UGE + case BlockARM64UGT: + return BlockARM64ULT + case BlockARM64UGE: + return BlockARM64ULE + default: + panic("Incorrect kind of Block") + } +} diff --git a/src/cmd/compile/internal/ssa/merge_conditional_branches_test.go b/src/cmd/compile/internal/ssa/merge_conditional_branches_test.go new file mode 100644 index 0000000000..08925a3ce0 --- /dev/null +++ b/src/cmd/compile/internal/ssa/merge_conditional_branches_test.go @@ -0,0 +1,282 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssa + +import ( + "cmd/compile/internal/types" + "testing" +) + +// ARM64Lt specifies BlockARM64LT +func ARM64Lt(cond, sub, alt string) ctrl { + return ctrl{BlockARM64LT, cond, []string{sub, alt}} +} + +// ARM64Gt specifies BlockARM64GT +func ARM64Gt(cond, sub, alt string) ctrl { + return ctrl{BlockARM64GT, cond, []string{sub, alt}} +} + +// ARM64Ne specifies BlockARM64NE +func ARM64Ne(cond, sub, alt string) ctrl { + return ctrl{BlockARM64NE, cond, []string{sub, alt}} +} + +// ARM64Eq specifies BlockARM64EQ +func ARM64Eq(cond, sub, alt string) ctrl { + return ctrl{BlockARM64EQ, cond, []string{sub, alt}} +} + +// isNewConditionCorrect verifies that a block has been correctly transformed +// to use conditional comparison (CCMP) with the expected parameters. +// It checks: +// - The block kind is BlockARM64LT (less than condition) +// - The control operation is OpARM64CCMPconst (conditional comparison with constant) +// - The condition code is OpARM64GreaterThan +// - The NZCV flags are set to 1 +// - The constant value being compared is 4 +// Returns true if all conditions match the expected transformation pattern +func isNewConditionCorrect(b *Block) bool { + if b.Kind != BlockARM64LT { + return false + } + + v := b.Controls[0] + if v.Op != OpARM64CCMPconst { + return false + } + + params := v.AuxArm64ConditionalParams() + if params.Cond() != OpARM64GreaterThan { + return false + } + if params.Nzcv() != 1 { + // NZCV flags should be set to 1 for this specific transformation + return false + } + if imm, ok := params.ConstValue(); !ok || imm != 4 { + return false + } + + return true +} + +// containsOpARM64CCMP checks if a block contains any ARM64 conditional comparison +// operations (CCMP or CCMPconst). This is used in tests to verify that the +// if-conversion optimization successfully generated conditional comparison +// instructions or to ensure they were not generated when inappropriate. +func containsOpARM64CCMP(b *Block) bool { + for _, v := range b.Values { + if v.Op == OpARM64CCMP || v.Op == OpARM64CCMPconst { + return true + } + } + return false +} + +// TestMergeConditionalBranchesWithoutPointers tests the if-conversion optimization +// on a simple case of logical AND (cond1 && cond2) without pointer operations. +// The test verifies that: +// - The optimization correctly transforms nested conditionals into CCMP instructions +// - The block structure is properly simplified (inner block becomes plain and empty) +// - The resulting control flow uses conditional comparison with correct parameters +// - No important blocks are accidentally deleted during transformation +// This represents the ideal case where the optimization should apply successfully. +func TestMergeConditionalBranchesWithoutPointers(t *testing.T) { + t.Run("arm64", func(t *testing.T) { + c := testConfigArch(t, "arm64") + intType := c.config.Types.Int64 + fun := c.Fun("entry", + Bloc("entry", + Valu("mem", + OpInitMem, + types.TypeMem, + 0, nil, + ), + Valu("a", + OpArg, + intType, + 0, c.Temp(intType), + ), + Valu("b", + OpArg, + intType, + 1, c.Temp(intType), + ), + Valu("cond1", + OpARM64CMPconst, + types.TypeFlags, + 1, nil, + "a", + ), + ARM64Gt("cond1", "second_comparison", "ret_false"), + ), + Bloc("second_comparison", + Valu("cond2", + OpARM64CMPconst, + types.TypeFlags, + 4, nil, + "b", + ), + ARM64Lt("cond2", "ret_false", "ret_true"), + ), + Bloc("ret_true", + Valu("const1", + OpARM64MOVDconst, + intType, + 1, nil, + ), + Valu("true_result", + OpMakeResult, + types.TypeMem, + 0, nil, + "const1", "mem", + ), + Ret("true_result"), + ), + Bloc("ret_false", + Valu("const0", + OpARM64MOVDconst, + intType, + 0, nil, + ), + Valu("false_result", + OpMakeResult, + types.TypeMem, + 0, nil, + "const0", "mem", + ), + Ret("false_result"), + ), + ) + + CheckFunc(fun.f) + mergeConditionalBranches(fun.f) + CheckFunc(fun.f) + + if len(fun.blocks) != 4 { + t.Errorf("Important block was deleted") + } + + entryBlock := fun.blocks["entry"] + secondBlock := fun.blocks["second_comparison"] + + if secondBlock.Kind != BlockPlain || len(secondBlock.Values) != 0 { + t.Errorf("Block with second condition wasn't cleaned") + } + + if !isNewConditionCorrect(entryBlock) { + t.Errorf("Entry block doesn't contain CCMP opertation") + } + }) +} + +// Test that pointer comparison with memory load doesn't generate CCMP +func TestNoCCMPWithPointerAndMemoryLoad(t *testing.T) { + t.Run("arm64", func(t *testing.T) { + c := testConfigArch(t, "arm64") + intType := c.config.Types.Int64 + ptrType := c.config.Types.BytePtr + + fun := c.Fun("entry", + Bloc("entry", + Valu("mem", + OpInitMem, + types.TypeMem, + 0, nil, + ), + Valu("ptr", + OpArg, + ptrType, + 0, c.Temp(ptrType), + ), + Valu("cond1", + OpARM64CMPconst, + types.TypeFlags, + 0, nil, // Compare with nil (0) + "ptr", + ), + ARM64Ne("cond1", "second_comparison", "ret_false"), // ptr != nil + ), + Bloc("second_comparison", + Valu("load", + OpLoad, + intType, + 0, nil, + "ptr", "mem", + ), + Valu("cond2", + OpARM64CMPconst, + types.TypeFlags, + 3, nil, // Compare with 3 + "load", + ), + ARM64Eq("cond2", "ret_true", "ret_false"), // *ptr == 3 + ), + Bloc("ret_true", + Valu("const1", + OpARM64MOVDconst, + intType, + 1, nil, + ), + Valu("true_result", + OpMakeResult, + types.TypeMem, + 0, nil, + "const1", "mem", + ), + Ret("true_result"), + ), + Bloc("ret_false", + Valu("const0", + OpARM64MOVDconst, + intType, + 0, nil, + ), + Valu("false_result", + OpMakeResult, + types.TypeMem, + 0, nil, + "const0", "mem", + ), + Ret("false_result"), + ), + ) + + CheckFunc(fun.f) + mergeConditionalBranches(fun.f) + CheckFunc(fun.f) + + // Verify that the second_comparison block still exists (not optimized away) + if fun.blocks["second_comparison"] == nil { + t.Errorf("Second comparison block was incorrectly removed") + } + + entryBlock := fun.blocks["entry"] + secondBlock := fun.blocks["second_comparison"] + + // Verify that entry block doesn't contain CCMP operation + if containsOpARM64CCMP(entryBlock) { + t.Errorf("Entry block contains CCMP operation, but shouldn't due to memory load") + } + + // Verify that second block contains the load operation + hasLoad := false + for _, v := range secondBlock.Values { + if v.Op == OpLoad { + hasLoad = true + break + } + } + if !hasLoad { + t.Errorf("Second comparison block should contain load operation") + } + + // The optimization shouldn't merge these blocks because of the memory operation + if secondBlock.Kind == BlockPlain { + t.Errorf("Block with memory load was incorrectly cleaned") + } + }) +} diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 04989d93c1..b093081884 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -1954,7 +1954,7 @@ func arm64BFWidth(mask, rshift int64) int64 { return nto(shiftedMask) } -// encodes condition code and NZCV flags into auxint. +// encodes condition code and NZCV flags into result. func arm64ConditionalParamsAuxInt(cond Op, nzcv uint8) arm64ConditionalParams { if cond < OpARM64Equal || cond > OpARM64GreaterEqualU { panic("Wrong conditional operation") diff --git a/src/cmd/compile/internal/test/conditionalCmpConst_test.go b/src/cmd/compile/internal/test/conditionalCmpConst_test.go new file mode 100644 index 0000000000..2f384da715 --- /dev/null +++ b/src/cmd/compile/internal/test/conditionalCmpConst_test.go @@ -0,0 +1,4408 @@ +// Code generated by conditionalCmpConstGen.go; DO NOT EDIT. + +package test + +import "testing" + +type IntegerConstraint interface { + int | uint | int8 | uint8 | int16 | uint16 | int32 | uint32 | int64 | uint64 +} + +type TestCase[T IntegerConstraint] struct { + cmp1, cmp2 func(a, b T) bool + combine func(x, y bool) bool + targetFunc func(a, b, c, d T) bool + cmp1Expr, cmp2Expr, logicalExpr string // String representations for debugging +} + +type BoundaryValues[T IntegerConstraint] struct { + base T + variants [3]T +} + +func generateTestCases[T IntegerConstraint]() []TestCase[T] { + return []TestCase[T]{ + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) && (c == d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c == d", + logicalExpr: "(a == b) && (c == d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) && !(c == d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c == d", + logicalExpr: "(a == b) && !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) && (c == d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c == d", + logicalExpr: "!(a == b) && (c == d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) && !(c == d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c == d", + logicalExpr: "!(a == b) && !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) || (c == d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c == d", + logicalExpr: "(a == b) || (c == d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) || !(c == d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c == d", + logicalExpr: "(a == b) || !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) || (c == d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c == d", + logicalExpr: "!(a == b) || (c == d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) || !(c == d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c == d", + logicalExpr: "!(a == b) || !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) && (c <= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c <= d", + logicalExpr: "(a == b) && (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) && !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c <= d", + logicalExpr: "(a == b) && !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) && (c <= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c <= d", + logicalExpr: "!(a == b) && (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) && !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c <= d", + logicalExpr: "!(a == b) && !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) || (c <= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c <= d", + logicalExpr: "(a == b) || (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) || !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c <= d", + logicalExpr: "(a == b) || !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) || (c <= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c <= d", + logicalExpr: "!(a == b) || (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) || !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c <= d", + logicalExpr: "!(a == b) || !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) && (c < d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c < d", + logicalExpr: "(a == b) && (c < d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) && !(c < d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c < d", + logicalExpr: "(a == b) && !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) && (c < d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c < d", + logicalExpr: "!(a == b) && (c < d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) && !(c < d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c < d", + logicalExpr: "!(a == b) && !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) || (c < d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c < d", + logicalExpr: "(a == b) || (c < d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) || !(c < d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c < d", + logicalExpr: "(a == b) || !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) || (c < d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c < d", + logicalExpr: "!(a == b) || (c < d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) || !(c < d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c < d", + logicalExpr: "!(a == b) || !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) && (c != d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c != d", + logicalExpr: "(a == b) && (c != d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) && !(c != d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c != d", + logicalExpr: "(a == b) && !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) && (c != d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c != d", + logicalExpr: "!(a == b) && (c != d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) && !(c != d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c != d", + logicalExpr: "!(a == b) && !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) || (c != d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c != d", + logicalExpr: "(a == b) || (c != d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) || !(c != d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c != d", + logicalExpr: "(a == b) || !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) || (c != d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c != d", + logicalExpr: "!(a == b) || (c != d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) || !(c != d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c != d", + logicalExpr: "!(a == b) || !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) && (c >= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c >= d", + logicalExpr: "(a == b) && (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) && !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c >= d", + logicalExpr: "(a == b) && !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) && (c >= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c >= d", + logicalExpr: "!(a == b) && (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) && !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c >= d", + logicalExpr: "!(a == b) && !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) || (c >= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c >= d", + logicalExpr: "(a == b) || (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) || !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c >= d", + logicalExpr: "(a == b) || !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) || (c >= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c >= d", + logicalExpr: "!(a == b) || (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) || !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c >= d", + logicalExpr: "!(a == b) || !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) && (c > d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c > d", + logicalExpr: "(a == b) && (c > d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) && !(c > d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c > d", + logicalExpr: "(a == b) && !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) && (c > d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c > d", + logicalExpr: "!(a == b) && (c > d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) && !(c > d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c > d", + logicalExpr: "!(a == b) && !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) || (c > d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c > d", + logicalExpr: "(a == b) || (c > d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a == b) || !(c > d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c > d", + logicalExpr: "(a == b) || !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) || (c > d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c > d", + logicalExpr: "!(a == b) || (c > d)", + }, + { + cmp1: func(a, b T) bool { return a == b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a == b) || !(c > d) { + return true + } + return false + }, + cmp1Expr: "a == b", + cmp2Expr: "c > d", + logicalExpr: "!(a == b) || !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) && (c == d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c == d", + logicalExpr: "(a <= b) && (c == d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) && !(c == d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c == d", + logicalExpr: "(a <= b) && !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) && (c == d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c == d", + logicalExpr: "!(a <= b) && (c == d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) && !(c == d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c == d", + logicalExpr: "!(a <= b) && !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) || (c == d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c == d", + logicalExpr: "(a <= b) || (c == d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) || !(c == d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c == d", + logicalExpr: "(a <= b) || !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) || (c == d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c == d", + logicalExpr: "!(a <= b) || (c == d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) || !(c == d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c == d", + logicalExpr: "!(a <= b) || !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) && (c <= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c <= d", + logicalExpr: "(a <= b) && (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) && !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c <= d", + logicalExpr: "(a <= b) && !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) && (c <= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c <= d", + logicalExpr: "!(a <= b) && (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) && !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c <= d", + logicalExpr: "!(a <= b) && !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) || (c <= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c <= d", + logicalExpr: "(a <= b) || (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) || !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c <= d", + logicalExpr: "(a <= b) || !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) || (c <= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c <= d", + logicalExpr: "!(a <= b) || (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) || !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c <= d", + logicalExpr: "!(a <= b) || !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) && (c < d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c < d", + logicalExpr: "(a <= b) && (c < d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) && !(c < d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c < d", + logicalExpr: "(a <= b) && !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) && (c < d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c < d", + logicalExpr: "!(a <= b) && (c < d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) && !(c < d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c < d", + logicalExpr: "!(a <= b) && !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) || (c < d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c < d", + logicalExpr: "(a <= b) || (c < d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) || !(c < d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c < d", + logicalExpr: "(a <= b) || !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) || (c < d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c < d", + logicalExpr: "!(a <= b) || (c < d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) || !(c < d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c < d", + logicalExpr: "!(a <= b) || !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) && (c != d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c != d", + logicalExpr: "(a <= b) && (c != d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) && !(c != d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c != d", + logicalExpr: "(a <= b) && !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) && (c != d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c != d", + logicalExpr: "!(a <= b) && (c != d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) && !(c != d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c != d", + logicalExpr: "!(a <= b) && !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) || (c != d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c != d", + logicalExpr: "(a <= b) || (c != d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) || !(c != d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c != d", + logicalExpr: "(a <= b) || !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) || (c != d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c != d", + logicalExpr: "!(a <= b) || (c != d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) || !(c != d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c != d", + logicalExpr: "!(a <= b) || !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) && (c >= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c >= d", + logicalExpr: "(a <= b) && (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) && !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c >= d", + logicalExpr: "(a <= b) && !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) && (c >= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c >= d", + logicalExpr: "!(a <= b) && (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) && !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c >= d", + logicalExpr: "!(a <= b) && !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) || (c >= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c >= d", + logicalExpr: "(a <= b) || (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) || !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c >= d", + logicalExpr: "(a <= b) || !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) || (c >= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c >= d", + logicalExpr: "!(a <= b) || (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) || !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c >= d", + logicalExpr: "!(a <= b) || !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) && (c > d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c > d", + logicalExpr: "(a <= b) && (c > d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) && !(c > d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c > d", + logicalExpr: "(a <= b) && !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) && (c > d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c > d", + logicalExpr: "!(a <= b) && (c > d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) && !(c > d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c > d", + logicalExpr: "!(a <= b) && !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) || (c > d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c > d", + logicalExpr: "(a <= b) || (c > d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a <= b) || !(c > d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c > d", + logicalExpr: "(a <= b) || !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) || (c > d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c > d", + logicalExpr: "!(a <= b) || (c > d)", + }, + { + cmp1: func(a, b T) bool { return a <= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a <= b) || !(c > d) { + return true + } + return false + }, + cmp1Expr: "a <= b", + cmp2Expr: "c > d", + logicalExpr: "!(a <= b) || !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) && (c == d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c == d", + logicalExpr: "(a < b) && (c == d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) && !(c == d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c == d", + logicalExpr: "(a < b) && !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) && (c == d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c == d", + logicalExpr: "!(a < b) && (c == d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) && !(c == d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c == d", + logicalExpr: "!(a < b) && !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) || (c == d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c == d", + logicalExpr: "(a < b) || (c == d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) || !(c == d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c == d", + logicalExpr: "(a < b) || !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) || (c == d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c == d", + logicalExpr: "!(a < b) || (c == d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) || !(c == d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c == d", + logicalExpr: "!(a < b) || !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) && (c <= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c <= d", + logicalExpr: "(a < b) && (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) && !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c <= d", + logicalExpr: "(a < b) && !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) && (c <= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c <= d", + logicalExpr: "!(a < b) && (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) && !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c <= d", + logicalExpr: "!(a < b) && !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) || (c <= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c <= d", + logicalExpr: "(a < b) || (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) || !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c <= d", + logicalExpr: "(a < b) || !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) || (c <= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c <= d", + logicalExpr: "!(a < b) || (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) || !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c <= d", + logicalExpr: "!(a < b) || !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) && (c < d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c < d", + logicalExpr: "(a < b) && (c < d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) && !(c < d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c < d", + logicalExpr: "(a < b) && !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) && (c < d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c < d", + logicalExpr: "!(a < b) && (c < d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) && !(c < d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c < d", + logicalExpr: "!(a < b) && !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) || (c < d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c < d", + logicalExpr: "(a < b) || (c < d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) || !(c < d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c < d", + logicalExpr: "(a < b) || !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) || (c < d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c < d", + logicalExpr: "!(a < b) || (c < d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) || !(c < d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c < d", + logicalExpr: "!(a < b) || !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) && (c != d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c != d", + logicalExpr: "(a < b) && (c != d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) && !(c != d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c != d", + logicalExpr: "(a < b) && !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) && (c != d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c != d", + logicalExpr: "!(a < b) && (c != d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) && !(c != d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c != d", + logicalExpr: "!(a < b) && !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) || (c != d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c != d", + logicalExpr: "(a < b) || (c != d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) || !(c != d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c != d", + logicalExpr: "(a < b) || !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) || (c != d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c != d", + logicalExpr: "!(a < b) || (c != d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) || !(c != d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c != d", + logicalExpr: "!(a < b) || !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) && (c >= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c >= d", + logicalExpr: "(a < b) && (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) && !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c >= d", + logicalExpr: "(a < b) && !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) && (c >= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c >= d", + logicalExpr: "!(a < b) && (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) && !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c >= d", + logicalExpr: "!(a < b) && !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) || (c >= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c >= d", + logicalExpr: "(a < b) || (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) || !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c >= d", + logicalExpr: "(a < b) || !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) || (c >= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c >= d", + logicalExpr: "!(a < b) || (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) || !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c >= d", + logicalExpr: "!(a < b) || !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) && (c > d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c > d", + logicalExpr: "(a < b) && (c > d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) && !(c > d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c > d", + logicalExpr: "(a < b) && !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) && (c > d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c > d", + logicalExpr: "!(a < b) && (c > d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) && !(c > d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c > d", + logicalExpr: "!(a < b) && !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) || (c > d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c > d", + logicalExpr: "(a < b) || (c > d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a < b) || !(c > d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c > d", + logicalExpr: "(a < b) || !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) || (c > d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c > d", + logicalExpr: "!(a < b) || (c > d)", + }, + { + cmp1: func(a, b T) bool { return a < b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a < b) || !(c > d) { + return true + } + return false + }, + cmp1Expr: "a < b", + cmp2Expr: "c > d", + logicalExpr: "!(a < b) || !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) && (c == d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c == d", + logicalExpr: "(a != b) && (c == d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) && !(c == d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c == d", + logicalExpr: "(a != b) && !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) && (c == d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c == d", + logicalExpr: "!(a != b) && (c == d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) && !(c == d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c == d", + logicalExpr: "!(a != b) && !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) || (c == d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c == d", + logicalExpr: "(a != b) || (c == d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) || !(c == d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c == d", + logicalExpr: "(a != b) || !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) || (c == d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c == d", + logicalExpr: "!(a != b) || (c == d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) || !(c == d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c == d", + logicalExpr: "!(a != b) || !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) && (c <= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c <= d", + logicalExpr: "(a != b) && (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) && !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c <= d", + logicalExpr: "(a != b) && !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) && (c <= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c <= d", + logicalExpr: "!(a != b) && (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) && !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c <= d", + logicalExpr: "!(a != b) && !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) || (c <= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c <= d", + logicalExpr: "(a != b) || (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) || !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c <= d", + logicalExpr: "(a != b) || !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) || (c <= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c <= d", + logicalExpr: "!(a != b) || (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) || !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c <= d", + logicalExpr: "!(a != b) || !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) && (c < d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c < d", + logicalExpr: "(a != b) && (c < d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) && !(c < d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c < d", + logicalExpr: "(a != b) && !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) && (c < d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c < d", + logicalExpr: "!(a != b) && (c < d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) && !(c < d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c < d", + logicalExpr: "!(a != b) && !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) || (c < d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c < d", + logicalExpr: "(a != b) || (c < d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) || !(c < d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c < d", + logicalExpr: "(a != b) || !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) || (c < d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c < d", + logicalExpr: "!(a != b) || (c < d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) || !(c < d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c < d", + logicalExpr: "!(a != b) || !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) && (c != d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c != d", + logicalExpr: "(a != b) && (c != d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) && !(c != d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c != d", + logicalExpr: "(a != b) && !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) && (c != d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c != d", + logicalExpr: "!(a != b) && (c != d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) && !(c != d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c != d", + logicalExpr: "!(a != b) && !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) || (c != d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c != d", + logicalExpr: "(a != b) || (c != d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) || !(c != d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c != d", + logicalExpr: "(a != b) || !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) || (c != d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c != d", + logicalExpr: "!(a != b) || (c != d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) || !(c != d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c != d", + logicalExpr: "!(a != b) || !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) && (c >= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c >= d", + logicalExpr: "(a != b) && (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) && !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c >= d", + logicalExpr: "(a != b) && !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) && (c >= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c >= d", + logicalExpr: "!(a != b) && (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) && !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c >= d", + logicalExpr: "!(a != b) && !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) || (c >= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c >= d", + logicalExpr: "(a != b) || (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) || !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c >= d", + logicalExpr: "(a != b) || !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) || (c >= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c >= d", + logicalExpr: "!(a != b) || (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) || !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c >= d", + logicalExpr: "!(a != b) || !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) && (c > d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c > d", + logicalExpr: "(a != b) && (c > d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) && !(c > d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c > d", + logicalExpr: "(a != b) && !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) && (c > d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c > d", + logicalExpr: "!(a != b) && (c > d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) && !(c > d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c > d", + logicalExpr: "!(a != b) && !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) || (c > d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c > d", + logicalExpr: "(a != b) || (c > d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a != b) || !(c > d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c > d", + logicalExpr: "(a != b) || !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) || (c > d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c > d", + logicalExpr: "!(a != b) || (c > d)", + }, + { + cmp1: func(a, b T) bool { return a != b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a != b) || !(c > d) { + return true + } + return false + }, + cmp1Expr: "a != b", + cmp2Expr: "c > d", + logicalExpr: "!(a != b) || !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) && (c == d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c == d", + logicalExpr: "(a >= b) && (c == d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) && !(c == d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c == d", + logicalExpr: "(a >= b) && !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) && (c == d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c == d", + logicalExpr: "!(a >= b) && (c == d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) && !(c == d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c == d", + logicalExpr: "!(a >= b) && !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) || (c == d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c == d", + logicalExpr: "(a >= b) || (c == d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) || !(c == d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c == d", + logicalExpr: "(a >= b) || !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) || (c == d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c == d", + logicalExpr: "!(a >= b) || (c == d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) || !(c == d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c == d", + logicalExpr: "!(a >= b) || !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) && (c <= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c <= d", + logicalExpr: "(a >= b) && (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) && !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c <= d", + logicalExpr: "(a >= b) && !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) && (c <= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c <= d", + logicalExpr: "!(a >= b) && (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) && !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c <= d", + logicalExpr: "!(a >= b) && !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) || (c <= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c <= d", + logicalExpr: "(a >= b) || (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) || !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c <= d", + logicalExpr: "(a >= b) || !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) || (c <= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c <= d", + logicalExpr: "!(a >= b) || (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) || !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c <= d", + logicalExpr: "!(a >= b) || !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) && (c < d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c < d", + logicalExpr: "(a >= b) && (c < d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) && !(c < d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c < d", + logicalExpr: "(a >= b) && !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) && (c < d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c < d", + logicalExpr: "!(a >= b) && (c < d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) && !(c < d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c < d", + logicalExpr: "!(a >= b) && !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) || (c < d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c < d", + logicalExpr: "(a >= b) || (c < d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) || !(c < d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c < d", + logicalExpr: "(a >= b) || !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) || (c < d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c < d", + logicalExpr: "!(a >= b) || (c < d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) || !(c < d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c < d", + logicalExpr: "!(a >= b) || !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) && (c != d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c != d", + logicalExpr: "(a >= b) && (c != d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) && !(c != d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c != d", + logicalExpr: "(a >= b) && !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) && (c != d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c != d", + logicalExpr: "!(a >= b) && (c != d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) && !(c != d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c != d", + logicalExpr: "!(a >= b) && !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) || (c != d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c != d", + logicalExpr: "(a >= b) || (c != d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) || !(c != d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c != d", + logicalExpr: "(a >= b) || !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) || (c != d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c != d", + logicalExpr: "!(a >= b) || (c != d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) || !(c != d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c != d", + logicalExpr: "!(a >= b) || !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) && (c >= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c >= d", + logicalExpr: "(a >= b) && (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) && !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c >= d", + logicalExpr: "(a >= b) && !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) && (c >= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c >= d", + logicalExpr: "!(a >= b) && (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) && !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c >= d", + logicalExpr: "!(a >= b) && !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) || (c >= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c >= d", + logicalExpr: "(a >= b) || (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) || !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c >= d", + logicalExpr: "(a >= b) || !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) || (c >= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c >= d", + logicalExpr: "!(a >= b) || (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) || !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c >= d", + logicalExpr: "!(a >= b) || !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) && (c > d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c > d", + logicalExpr: "(a >= b) && (c > d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) && !(c > d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c > d", + logicalExpr: "(a >= b) && !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) && (c > d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c > d", + logicalExpr: "!(a >= b) && (c > d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) && !(c > d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c > d", + logicalExpr: "!(a >= b) && !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) || (c > d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c > d", + logicalExpr: "(a >= b) || (c > d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a >= b) || !(c > d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c > d", + logicalExpr: "(a >= b) || !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) || (c > d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c > d", + logicalExpr: "!(a >= b) || (c > d)", + }, + { + cmp1: func(a, b T) bool { return a >= b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a >= b) || !(c > d) { + return true + } + return false + }, + cmp1Expr: "a >= b", + cmp2Expr: "c > d", + logicalExpr: "!(a >= b) || !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) && (c == d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c == d", + logicalExpr: "(a > b) && (c == d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) && !(c == d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c == d", + logicalExpr: "(a > b) && !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) && (c == d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c == d", + logicalExpr: "!(a > b) && (c == d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) && !(c == d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c == d", + logicalExpr: "!(a > b) && !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) || (c == d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c == d", + logicalExpr: "(a > b) || (c == d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) || !(c == d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c == d", + logicalExpr: "(a > b) || !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) || (c == d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c == d", + logicalExpr: "!(a > b) || (c == d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a == b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) || !(c == d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c == d", + logicalExpr: "!(a > b) || !(c == d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) && (c <= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c <= d", + logicalExpr: "(a > b) && (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) && !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c <= d", + logicalExpr: "(a > b) && !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) && (c <= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c <= d", + logicalExpr: "!(a > b) && (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) && !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c <= d", + logicalExpr: "!(a > b) && !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) || (c <= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c <= d", + logicalExpr: "(a > b) || (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) || !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c <= d", + logicalExpr: "(a > b) || !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) || (c <= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c <= d", + logicalExpr: "!(a > b) || (c <= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a <= b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) || !(c <= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c <= d", + logicalExpr: "!(a > b) || !(c <= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) && (c < d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c < d", + logicalExpr: "(a > b) && (c < d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) && !(c < d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c < d", + logicalExpr: "(a > b) && !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) && (c < d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c < d", + logicalExpr: "!(a > b) && (c < d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) && !(c < d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c < d", + logicalExpr: "!(a > b) && !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) || (c < d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c < d", + logicalExpr: "(a > b) || (c < d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) || !(c < d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c < d", + logicalExpr: "(a > b) || !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) || (c < d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c < d", + logicalExpr: "!(a > b) || (c < d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a < b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) || !(c < d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c < d", + logicalExpr: "!(a > b) || !(c < d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) && (c != d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c != d", + logicalExpr: "(a > b) && (c != d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) && !(c != d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c != d", + logicalExpr: "(a > b) && !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) && (c != d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c != d", + logicalExpr: "!(a > b) && (c != d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) && !(c != d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c != d", + logicalExpr: "!(a > b) && !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) || (c != d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c != d", + logicalExpr: "(a > b) || (c != d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) || !(c != d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c != d", + logicalExpr: "(a > b) || !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) || (c != d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c != d", + logicalExpr: "!(a > b) || (c != d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a != b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) || !(c != d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c != d", + logicalExpr: "!(a > b) || !(c != d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) && (c >= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c >= d", + logicalExpr: "(a > b) && (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) && !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c >= d", + logicalExpr: "(a > b) && !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) && (c >= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c >= d", + logicalExpr: "!(a > b) && (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) && !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c >= d", + logicalExpr: "!(a > b) && !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) || (c >= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c >= d", + logicalExpr: "(a > b) || (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) || !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c >= d", + logicalExpr: "(a > b) || !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) || (c >= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c >= d", + logicalExpr: "!(a > b) || (c >= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a >= b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) || !(c >= d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c >= d", + logicalExpr: "!(a > b) || !(c >= d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) && (c > d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c > d", + logicalExpr: "(a > b) && (c > d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) && !(c > d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c > d", + logicalExpr: "(a > b) && !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) && (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) && (c > d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c > d", + logicalExpr: "!(a > b) && (c > d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) && !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) && !(c > d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c > d", + logicalExpr: "!(a > b) && !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) || (c > d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c > d", + logicalExpr: "(a > b) || (c > d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return (x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if (a > b) || !(c > d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c > d", + logicalExpr: "(a > b) || !(c > d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) || (y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) || (c > d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c > d", + logicalExpr: "!(a > b) || (c > d)", + }, + { + cmp1: func(a, b T) bool { return a > b }, + cmp2: func(a, b T) bool { return a > b }, + combine: func(x, y bool) bool { return !(x) || !(y) }, + targetFunc: func(a, b, c, d T) bool { + if !(a > b) || !(c > d) { + return true + } + return false + }, + cmp1Expr: "a > b", + cmp2Expr: "c > d", + logicalExpr: "!(a > b) || !(c > d)", + }, + } +} + +func TestInt8ConditionalCmpConst(t *testing.T) { + testCases := generateTestCases[int8]() + base := int8(1 << 6) + values := [3]int8{base - 1, base, base + 1} + + for _, tc := range testCases { + a, c := base, base + for _, b := range values { + for _, d := range values { + expected := tc.combine(tc.cmp1(a, b), tc.cmp2(c, d)) + actual := tc.targetFunc(a, b, c, d) + if actual != expected { + t.Errorf("conditional comparison failed:\n"+ + " type: %T\n"+ + " condition: %s\n"+ + " values: a=%v, b=%v, c=%v, d=%v\n"+ + " cmp1(a,b)=%v (%s)\n"+ + " cmp2(c,d)=%v (%s)\n"+ + " expected: combine(%v, %v)=%v\n"+ + " actual: %v\n"+ + " logical expression: %s", + a, + tc.logicalExpr, + a, b, c, d, + tc.cmp1(a, b), tc.cmp1Expr, + tc.cmp2(c, d), tc.cmp2Expr, + tc.cmp1(a, b), tc.cmp2(c, d), expected, + actual, + tc.logicalExpr) + } + } + } + } +} + +func TestUint8ConditionalCmpConst(t *testing.T) { + testCases := generateTestCases[uint8]() + base := uint8(1 << 6) + values := [3]uint8{base - 1, base, base + 1} + + for _, tc := range testCases { + a, c := base, base + for _, b := range values { + for _, d := range values { + expected := tc.combine(tc.cmp1(a, b), tc.cmp2(c, d)) + actual := tc.targetFunc(a, b, c, d) + if actual != expected { + t.Errorf("conditional comparison failed:\n"+ + " type: %T\n"+ + " condition: %s\n"+ + " values: a=%v, b=%v, c=%v, d=%v\n"+ + " cmp1(a,b)=%v (%s)\n"+ + " cmp2(c,d)=%v (%s)\n"+ + " expected: combine(%v, %v)=%v\n"+ + " actual: %v\n"+ + " logical expression: %s", + a, + tc.logicalExpr, + a, b, c, d, + tc.cmp1(a, b), tc.cmp1Expr, + tc.cmp2(c, d), tc.cmp2Expr, + tc.cmp1(a, b), tc.cmp2(c, d), expected, + actual, + tc.logicalExpr) + } + } + } + } +} + +func TestInt16ConditionalCmpConst(t *testing.T) { + testCases := generateTestCases[int16]() + base := int16(1 << 14) + values := [3]int16{base - 1, base, base + 1} + + for _, tc := range testCases { + a, c := base, base + for _, b := range values { + for _, d := range values { + expected := tc.combine(tc.cmp1(a, b), tc.cmp2(c, d)) + actual := tc.targetFunc(a, b, c, d) + if actual != expected { + t.Errorf("conditional comparison failed:\n"+ + " type: %T\n"+ + " condition: %s\n"+ + " values: a=%v, b=%v, c=%v, d=%v\n"+ + " cmp1(a,b)=%v (%s)\n"+ + " cmp2(c,d)=%v (%s)\n"+ + " expected: combine(%v, %v)=%v\n"+ + " actual: %v\n"+ + " logical expression: %s", + a, + tc.logicalExpr, + a, b, c, d, + tc.cmp1(a, b), tc.cmp1Expr, + tc.cmp2(c, d), tc.cmp2Expr, + tc.cmp1(a, b), tc.cmp2(c, d), expected, + actual, + tc.logicalExpr) + } + } + } + } +} + +func TestUint16ConditionalCmpConst(t *testing.T) { + testCases := generateTestCases[uint16]() + base := uint16(1 << 14) + values := [3]uint16{base - 1, base, base + 1} + + for _, tc := range testCases { + a, c := base, base + for _, b := range values { + for _, d := range values { + expected := tc.combine(tc.cmp1(a, b), tc.cmp2(c, d)) + actual := tc.targetFunc(a, b, c, d) + if actual != expected { + t.Errorf("conditional comparison failed:\n"+ + " type: %T\n"+ + " condition: %s\n"+ + " values: a=%v, b=%v, c=%v, d=%v\n"+ + " cmp1(a,b)=%v (%s)\n"+ + " cmp2(c,d)=%v (%s)\n"+ + " expected: combine(%v, %v)=%v\n"+ + " actual: %v\n"+ + " logical expression: %s", + a, + tc.logicalExpr, + a, b, c, d, + tc.cmp1(a, b), tc.cmp1Expr, + tc.cmp2(c, d), tc.cmp2Expr, + tc.cmp1(a, b), tc.cmp2(c, d), expected, + actual, + tc.logicalExpr) + } + } + } + } +} + +func TestInt32ConditionalCmpConst(t *testing.T) { + testCases := generateTestCases[int32]() + base := int32(1 << 30) + values := [3]int32{base - 1, base, base + 1} + + for _, tc := range testCases { + a, c := base, base + for _, b := range values { + for _, d := range values { + expected := tc.combine(tc.cmp1(a, b), tc.cmp2(c, d)) + actual := tc.targetFunc(a, b, c, d) + if actual != expected { + t.Errorf("conditional comparison failed:\n"+ + " type: %T\n"+ + " condition: %s\n"+ + " values: a=%v, b=%v, c=%v, d=%v\n"+ + " cmp1(a,b)=%v (%s)\n"+ + " cmp2(c,d)=%v (%s)\n"+ + " expected: combine(%v, %v)=%v\n"+ + " actual: %v\n"+ + " logical expression: %s", + a, + tc.logicalExpr, + a, b, c, d, + tc.cmp1(a, b), tc.cmp1Expr, + tc.cmp2(c, d), tc.cmp2Expr, + tc.cmp1(a, b), tc.cmp2(c, d), expected, + actual, + tc.logicalExpr) + } + } + } + } +} + +func TestUint32ConditionalCmpConst(t *testing.T) { + testCases := generateTestCases[uint32]() + base := uint32(1 << 30) + values := [3]uint32{base - 1, base, base + 1} + + for _, tc := range testCases { + a, c := base, base + for _, b := range values { + for _, d := range values { + expected := tc.combine(tc.cmp1(a, b), tc.cmp2(c, d)) + actual := tc.targetFunc(a, b, c, d) + if actual != expected { + t.Errorf("conditional comparison failed:\n"+ + " type: %T\n"+ + " condition: %s\n"+ + " values: a=%v, b=%v, c=%v, d=%v\n"+ + " cmp1(a,b)=%v (%s)\n"+ + " cmp2(c,d)=%v (%s)\n"+ + " expected: combine(%v, %v)=%v\n"+ + " actual: %v\n"+ + " logical expression: %s", + a, + tc.logicalExpr, + a, b, c, d, + tc.cmp1(a, b), tc.cmp1Expr, + tc.cmp2(c, d), tc.cmp2Expr, + tc.cmp1(a, b), tc.cmp2(c, d), expected, + actual, + tc.logicalExpr) + } + } + } + } +} + +func TestIntConditionalCmpConst(t *testing.T) { + testCases := generateTestCases[int]() + base := int(1 << 30) + values := [3]int{base - 1, base, base + 1} + + for _, tc := range testCases { + a, c := base, base + for _, b := range values { + for _, d := range values { + expected := tc.combine(tc.cmp1(a, b), tc.cmp2(c, d)) + actual := tc.targetFunc(a, b, c, d) + if actual != expected { + t.Errorf("conditional comparison failed:\n"+ + " type: %T\n"+ + " condition: %s\n"+ + " values: a=%v, b=%v, c=%v, d=%v\n"+ + " cmp1(a,b)=%v (%s)\n"+ + " cmp2(c,d)=%v (%s)\n"+ + " expected: combine(%v, %v)=%v\n"+ + " actual: %v\n"+ + " logical expression: %s", + a, + tc.logicalExpr, + a, b, c, d, + tc.cmp1(a, b), tc.cmp1Expr, + tc.cmp2(c, d), tc.cmp2Expr, + tc.cmp1(a, b), tc.cmp2(c, d), expected, + actual, + tc.logicalExpr) + } + } + } + } +} + +func TestUintConditionalCmpConst(t *testing.T) { + testCases := generateTestCases[uint]() + base := uint(1 << 30) + values := [3]uint{base - 1, base, base + 1} + + for _, tc := range testCases { + a, c := base, base + for _, b := range values { + for _, d := range values { + expected := tc.combine(tc.cmp1(a, b), tc.cmp2(c, d)) + actual := tc.targetFunc(a, b, c, d) + if actual != expected { + t.Errorf("conditional comparison failed:\n"+ + " type: %T\n"+ + " condition: %s\n"+ + " values: a=%v, b=%v, c=%v, d=%v\n"+ + " cmp1(a,b)=%v (%s)\n"+ + " cmp2(c,d)=%v (%s)\n"+ + " expected: combine(%v, %v)=%v\n"+ + " actual: %v\n"+ + " logical expression: %s", + a, + tc.logicalExpr, + a, b, c, d, + tc.cmp1(a, b), tc.cmp1Expr, + tc.cmp2(c, d), tc.cmp2Expr, + tc.cmp1(a, b), tc.cmp2(c, d), expected, + actual, + tc.logicalExpr) + } + } + } + } +} + +func TestInt64ConditionalCmpConst(t *testing.T) { + testCases := generateTestCases[int64]() + base := int64(1 << 62) + values := [3]int64{base - 1, base, base + 1} + + for _, tc := range testCases { + a, c := base, base + for _, b := range values { + for _, d := range values { + expected := tc.combine(tc.cmp1(a, b), tc.cmp2(c, d)) + actual := tc.targetFunc(a, b, c, d) + if actual != expected { + t.Errorf("conditional comparison failed:\n"+ + " type: %T\n"+ + " condition: %s\n"+ + " values: a=%v, b=%v, c=%v, d=%v\n"+ + " cmp1(a,b)=%v (%s)\n"+ + " cmp2(c,d)=%v (%s)\n"+ + " expected: combine(%v, %v)=%v\n"+ + " actual: %v\n"+ + " logical expression: %s", + a, + tc.logicalExpr, + a, b, c, d, + tc.cmp1(a, b), tc.cmp1Expr, + tc.cmp2(c, d), tc.cmp2Expr, + tc.cmp1(a, b), tc.cmp2(c, d), expected, + actual, + tc.logicalExpr) + } + } + } + } +} + +func TestUint64ConditionalCmpConst(t *testing.T) { + testCases := generateTestCases[uint64]() + base := uint64(1 << 62) + values := [3]uint64{base - 1, base, base + 1} + + for _, tc := range testCases { + a, c := base, base + for _, b := range values { + for _, d := range values { + expected := tc.combine(tc.cmp1(a, b), tc.cmp2(c, d)) + actual := tc.targetFunc(a, b, c, d) + if actual != expected { + t.Errorf("conditional comparison failed:\n"+ + " type: %T\n"+ + " condition: %s\n"+ + " values: a=%v, b=%v, c=%v, d=%v\n"+ + " cmp1(a,b)=%v (%s)\n"+ + " cmp2(c,d)=%v (%s)\n"+ + " expected: combine(%v, %v)=%v\n"+ + " actual: %v\n"+ + " logical expression: %s", + a, + tc.logicalExpr, + a, b, c, d, + tc.cmp1(a, b), tc.cmp1Expr, + tc.cmp2(c, d), tc.cmp2Expr, + tc.cmp1(a, b), tc.cmp2(c, d), expected, + actual, + tc.logicalExpr) + } + } + } + } +} diff --git a/src/cmd/compile/internal/test/testdata/gen/conditionalCmpConstGen.go b/src/cmd/compile/internal/test/testdata/gen/conditionalCmpConstGen.go new file mode 100644 index 0000000000..c3e3d7e817 --- /dev/null +++ b/src/cmd/compile/internal/test/testdata/gen/conditionalCmpConstGen.go @@ -0,0 +1,231 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This program generates tests to verify that conditional comparisons +// with constants are properly optimized by the compiler through constant folding. +// The generated test should be compiled with a known working version of Go. +// Run with `go run conditionalCmpConstGen.go` to generate a file called +// conditionalCmpConst_test.go in the grandparent directory. + +package main + +import ( + "bytes" + "fmt" + "go/format" + "log" + "os" + "strings" +) + +// IntegerConstraint defines a type constraint for all integer types +func writeIntegerConstraint(w *bytes.Buffer) { + fmt.Fprintf(w, "type IntegerConstraint interface {\n") + fmt.Fprintf(w, "\tint | uint | int8 | uint8 | int16 | ") + fmt.Fprintf(w, "uint16 | int32 | uint32 | int64 | uint64\n") + fmt.Fprintf(w, "}\n\n") +} + +// TestCase describes a parameterized test case with comparison and logical operations +func writeTestCaseStruct(w *bytes.Buffer) { + fmt.Fprintf(w, "type TestCase[T IntegerConstraint] struct {\n") + fmt.Fprintf(w, "\tcmp1, cmp2 func(a, b T) bool\n") + fmt.Fprintf(w, "\tcombine func(x, y bool) bool\n") + fmt.Fprintf(w, "\ttargetFunc func(a, b, c, d T) bool\n") + fmt.Fprintf(w, "\tcmp1Expr, cmp2Expr, logicalExpr string // String representations for debugging\n") + fmt.Fprintf(w, "}\n\n") +} + +// BoundaryValues contains base value and its variations for edge case testing +func writeBoundaryValuesStruct(w *bytes.Buffer) { + fmt.Fprintf(w, "type BoundaryValues[T IntegerConstraint] struct {\n") + fmt.Fprintf(w, "\tbase T\n") + fmt.Fprintf(w, "\tvariants [3]T\n") + fmt.Fprintf(w, "}\n\n") +} + +// writeTypeDefinitions generates all necessary type declarations +func writeTypeDefinitions(w *bytes.Buffer) { + writeIntegerConstraint(w) + writeTestCaseStruct(w) + writeBoundaryValuesStruct(w) +} + +// comparisonOperators contains format strings for comparison operators +var comparisonOperators = []string{ + "%s == %s", "%s <= %s", "%s < %s", + "%s != %s", "%s >= %s", "%s > %s", +} + +// logicalOperators contains format strings for logical combination of boolean expressions +var logicalOperators = []string{ + "(%s) && (%s)", "(%s) && !(%s)", "!(%s) && (%s)", "!(%s) && !(%s)", + "(%s) || (%s)", "(%s) || !(%s)", "!(%s) || (%s)", "!(%s) || !(%s)", +} + +// writeComparator generates a comparator function based on the comparison operator +func writeComparator(w *bytes.Buffer, fieldName, operatorFormat string) { + expression := fmt.Sprintf(operatorFormat, "a", "b") + fmt.Fprintf(w, "\t\t\t%s: func(a, b T) bool { return %s },\n", fieldName, expression) +} + +// writeLogicalCombiner generates a function to combine two boolean values +func writeLogicalCombiner(w *bytes.Buffer, logicalOperator string) { + expression := fmt.Sprintf(logicalOperator, "x", "y") + fmt.Fprintf(w, "\t\t\tcombine: func(x, y bool) bool { return %s },\n", expression) +} + +// writeTargetFunction generates the target function with conditional expression +func writeTargetFunction(w *bytes.Buffer, cmp1, cmp2, logicalOp string) { + leftExpr := fmt.Sprintf(cmp1, "a", "b") + rightExpr := fmt.Sprintf(cmp2, "c", "d") + condition := fmt.Sprintf(logicalOp, leftExpr, rightExpr) + + fmt.Fprintf(w, "\t\t\ttargetFunc: func(a, b, c, d T) bool {\n") + fmt.Fprintf(w, "\t\t\t\tif %s {\n", condition) + fmt.Fprintf(w, "\t\t\t\t\treturn true\n") + fmt.Fprintf(w, "\t\t\t\t}\n") + fmt.Fprintf(w, "\t\t\t\treturn false\n") + fmt.Fprintf(w, "\t\t\t},\n") +} + +// writeTestCase creates a single test case with given comparison and logical operators +func writeTestCase(w *bytes.Buffer, cmp1, cmp2, logicalOp string) { + fmt.Fprintf(w, "\t\t{\n") + writeComparator(w, "cmp1", cmp1) + writeComparator(w, "cmp2", cmp2) + writeLogicalCombiner(w, logicalOp) + writeTargetFunction(w, cmp1, cmp2, logicalOp) + + // Store string representations for debugging + cmp1Expr := fmt.Sprintf(cmp1, "a", "b") + cmp2Expr := fmt.Sprintf(cmp2, "c", "d") + logicalExpr := fmt.Sprintf(logicalOp, cmp1Expr, cmp2Expr) + + fmt.Fprintf(w, "\t\t\tcmp1Expr: %q,\n", cmp1Expr) + fmt.Fprintf(w, "\t\t\tcmp2Expr: %q,\n", cmp2Expr) + fmt.Fprintf(w, "\t\t\tlogicalExpr: %q,\n", logicalExpr) + + fmt.Fprintf(w, "\t\t},\n") +} + +// generateTestCases creates a slice of all possible test cases +func generateTestCases(w *bytes.Buffer) { + fmt.Fprintf(w, "func generateTestCases[T IntegerConstraint]() []TestCase[T] {\n") + fmt.Fprintf(w, "\treturn []TestCase[T]{\n") + + for _, cmp1 := range comparisonOperators { + for _, cmp2 := range comparisonOperators { + for _, logicalOp := range logicalOperators { + writeTestCase(w, cmp1, cmp2, logicalOp) + } + } + } + + fmt.Fprintf(w, "\t}\n") + fmt.Fprintf(w, "}\n\n") +} + +// TypeConfig defines a type and its test base value +type TypeConfig struct { + typeName, baseValue string +} + +// typeConfigs contains all integer types to test with their base values +var typeConfigs = []TypeConfig{ + {typeName: "int8", baseValue: "1 << 6"}, + {typeName: "uint8", baseValue: "1 << 6"}, + {typeName: "int16", baseValue: "1 << 14"}, + {typeName: "uint16", baseValue: "1 << 14"}, + {typeName: "int32", baseValue: "1 << 30"}, + {typeName: "uint32", baseValue: "1 << 30"}, + {typeName: "int", baseValue: "1 << 30"}, + {typeName: "uint", baseValue: "1 << 30"}, + {typeName: "int64", baseValue: "1 << 62"}, + {typeName: "uint64", baseValue: "1 << 62"}, +} + +// writeTypeSpecificTest generates test for a specific integer type +func writeTypeSpecificTest(w *bytes.Buffer, typeName, baseValue string) { + typeTitle := strings.Title(typeName) + + fmt.Fprintf(w, "func Test%sConditionalCmpConst(t *testing.T) {\n", typeTitle) + + fmt.Fprintf(w, "\ttestCases := generateTestCases[%s]()\n", typeName) + fmt.Fprintf(w, "\tbase := %s(%s)\n", typeName, baseValue) + fmt.Fprintf(w, "\tvalues := [3]%s{base - 1, base, base + 1}\n\n", typeName) + + fmt.Fprintf(w, "\tfor _, tc := range testCases {\n") + fmt.Fprintf(w, "\t\ta, c := base, base\n") + fmt.Fprintf(w, "\t\tfor _, b := range values {\n") + fmt.Fprintf(w, "\t\t\tfor _, d := range values {\n") + fmt.Fprintf(w, "\t\t\t\texpected := tc.combine(tc.cmp1(a, b), tc.cmp2(c, d))\n") + fmt.Fprintf(w, "\t\t\t\tactual := tc.targetFunc(a, b, c, d)\n") + fmt.Fprintf(w, "\t\t\t\tif actual != expected {\n") + fmt.Fprintf(w, "\t\t\t\t\tt.Errorf(\"conditional comparison failed:\\n\"+\n") + fmt.Fprintf(w, "\t\t\t\t\t\t\" type: %%T\\n\"+\n") + fmt.Fprintf(w, "\t\t\t\t\t\t\" condition: %%s\\n\"+\n") + fmt.Fprintf(w, "\t\t\t\t\t\t\" values: a=%%v, b=%%v, c=%%v, d=%%v\\n\"+\n") + fmt.Fprintf(w, "\t\t\t\t\t\t\" cmp1(a,b)=%%v (%%s)\\n\"+\n") + fmt.Fprintf(w, "\t\t\t\t\t\t\" cmp2(c,d)=%%v (%%s)\\n\"+\n") + fmt.Fprintf(w, "\t\t\t\t\t\t\" expected: combine(%%v, %%v)=%%v\\n\"+\n") + fmt.Fprintf(w, "\t\t\t\t\t\t\" actual: %%v\\n\"+\n") + fmt.Fprintf(w, "\t\t\t\t\t\t\" logical expression: %%s\",\n") + fmt.Fprintf(w, "\t\t\t\t\t\ta,\n") + fmt.Fprintf(w, "\t\t\t\t\t\ttc.logicalExpr,\n") + fmt.Fprintf(w, "\t\t\t\t\t\ta, b, c, d,\n") + fmt.Fprintf(w, "\t\t\t\t\t\ttc.cmp1(a, b), tc.cmp1Expr,\n") + fmt.Fprintf(w, "\t\t\t\t\t\ttc.cmp2(c, d), tc.cmp2Expr,\n") + fmt.Fprintf(w, "\t\t\t\t\t\ttc.cmp1(a, b), tc.cmp2(c, d), expected,\n") + fmt.Fprintf(w, "\t\t\t\t\t\tactual,\n") + fmt.Fprintf(w, "\t\t\t\t\t\ttc.logicalExpr)\n") + fmt.Fprintf(w, "\t\t\t\t}\n") + fmt.Fprintf(w, "\t\t\t}\n") + fmt.Fprintf(w, "\t\t}\n") + fmt.Fprintf(w, "\t}\n") + + fmt.Fprintf(w, "}\n\n") +} + +// writeAllTests generates tests for all supported integer types +func writeAllTests(w *bytes.Buffer) { + for _, config := range typeConfigs { + writeTypeSpecificTest(w, config.typeName, config.baseValue) + } +} + +func main() { + buffer := new(bytes.Buffer) + + // Header for generated file + fmt.Fprintf(buffer, "// Code generated by conditionalCmpConstGen.go; DO NOT EDIT.\n\n") + fmt.Fprintf(buffer, "package test\n\n") + fmt.Fprintf(buffer, "import \"testing\"\n\n") + + // Generate type definitions + writeTypeDefinitions(buffer) + + // Generate test cases + generateTestCases(buffer) + + // Generate specific tests for each integer type + writeAllTests(buffer) + + // Format generated source code + rawSource := buffer.Bytes() + formattedSource, err := format.Source(rawSource) + if err != nil { + // Output raw source for debugging if formatting fails + fmt.Printf("%s\n", rawSource) + log.Fatal("error formatting generated code: ", err) + } + + // Write to output file + outputPath := "../../conditionalCmpConst_test.go" + if err := os.WriteFile(outputPath, formattedSource, 0666); err != nil { + log.Fatal("failed to write output file: ", err) + } + + log.Printf("Tests successfully generated to %s", outputPath) +} diff --git a/test/codegen/comparisons.go b/test/codegen/comparisons.go index 330497c656..43b95646eb 100644 --- a/test/codegen/comparisons.go +++ b/test/codegen/comparisons.go @@ -462,7 +462,7 @@ func CmpToZero_ex5(e, f int32, u uint32) int { func UintLtZero(a uint8, b uint16, c uint32, d uint64) int { // amd64: -`(TESTB|TESTW|TESTL|TESTQ|JCC|JCS)` - // arm64: -`(CMPW|CMP|BHS|BLO)` + // arm64: -`(CMPW|CMP|CCMP|CCMPW|BHS|BLO)` if a < 0 || b < 0 || c < 0 || d < 0 { return 1 } @@ -471,7 +471,7 @@ func UintLtZero(a uint8, b uint16, c uint32, d uint64) int { func UintGeqZero(a uint8, b uint16, c uint32, d uint64) int { // amd64: -`(TESTB|TESTW|TESTL|TESTQ|JCS|JCC)` - // arm64: -`(CMPW|CMP|BLO|BHS)` + // arm64: -`(CMPW|CMP|CCMP|CCMPW|BLO|BHS)` if a >= 0 || b >= 0 || c >= 0 || d >= 0 { return 1 } @@ -479,7 +479,7 @@ func UintGeqZero(a uint8, b uint16, c uint32, d uint64) int { } func UintGtZero(a uint8, b uint16, c uint32, d uint64) int { - // arm64: `(CBN?ZW)`, `(CBN?Z[^W])`, -`(CMPW|CMP|BLS|BHI)` + // arm64: `(CMPW|CMP|CCMP|CCMPW|BNE|BEQ)` if a > 0 || b > 0 || c > 0 || d > 0 { return 1 } @@ -487,7 +487,7 @@ func UintGtZero(a uint8, b uint16, c uint32, d uint64) int { } func UintLeqZero(a uint8, b uint16, c uint32, d uint64) int { - // arm64: `(CBN?ZW)`, `(CBN?Z[^W])`, -`(CMPW|CMP|BHI|BLS)` + // arm64: `(CMPW|CMP|CCMP|CCMPW|BNE|BEQ)` if a <= 0 || b <= 0 || c <= 0 || d <= 0 { return 1 } @@ -495,7 +495,7 @@ func UintLeqZero(a uint8, b uint16, c uint32, d uint64) int { } func UintLtOne(a uint8, b uint16, c uint32, d uint64) int { - // arm64: `(CBN?ZW)`, `(CBN?Z[^W])`, -`(CMPW|CMP|BHS|BLO)` + // arm64: `(CMPW|CMP|CCMP|CCMPW|BNE|BEQ)` if a < 1 || b < 1 || c < 1 || d < 1 { return 1 } @@ -503,13 +503,45 @@ func UintLtOne(a uint8, b uint16, c uint32, d uint64) int { } func UintGeqOne(a uint8, b uint16, c uint32, d uint64) int { - // arm64: `(CBN?ZW)`, `(CBN?Z[^W])`, -`(CMPW|CMP|BLO|BHS)` + // arm64: `(CMPW|CMP|CCMP|CCMPW|BNE|BEQ)` if a >= 1 || b >= 1 || c >= 1 || d >= 1 { return 1 } return 0 } +func ConditionalCompareUint8(a, b uint8) int { + // arm64:"CCMPW EQ, R[0-9]+, [$]1, [$]0" + if a == 1 && b == 1 { + return 1 + } + return 0 +} + +func ConditionalCompareInt16(a, b int16) int { + // arm64:"CCMPW LE, R[0-9]+, R[0-9]+, [$]4" + if a > 3 || a == b { + return 1 + } + return 0 +} + +func ConditionalCompareUint32(a, b uint32) int { + // arm64:"CCMPW LO, R[0-9]+, [$]28, [$]2" + if a > b && a < 28 { + return 1 + } + return 0 +} + +func ConditionalCompareInt64(a, b int64) int { + // arm64:"CCMP GT, R[0-9]+, R[0-9]+, [$]0" + if a <= 16 || a != b { + return 1 + } + return 0 +} + func CmpToZeroU_ex1(a uint8, b uint16, c uint32, d uint64) int { // wasm:"I64Eqz"-"I64LtU" if 0 < a { -- 2.52.0