diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_operand.h b/src/mapleall/maple_be/include/cg/aarch64/aarch64_operand.h index 7fc6d2a7a6e277f176aa6ef69c135c74156f2884..ea5c5cfda9a43c8bd153e08780cf9d93860ac048 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_operand.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_operand.h @@ -89,6 +89,14 @@ class AArch64RegOperand : public RegOperand { return memPool.Clone(*this); } + void SetCsetOpnd() { + csetOpnd = true; + } + + bool IsCsetOpnd() { + return csetOpnd; + } + void SetIF64Vec() { if64Vec = true; } @@ -140,6 +148,7 @@ class AArch64RegOperand : public RegOperand { int16 vecLane = -1; /* -1 for whole reg, 0 to 15 to specify each lane one at a time */ uint16 vecLaneSize = 0; /* Number of lanes */ bool if64Vec = false; /* operand returning 64x1's int value in FP/Simd register */ + bool csetOpnd = false; /* used by nested select */ }; /* diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp index 2d602e0a5d81a629fae2856ba9b71f1a00bb4e21..f35e1affae945727e62530bf60170fccfc3d72d3 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -3889,6 +3889,7 @@ void AArch64CGFunc::SelectCmpOp(Operand &resOpnd, Operand &lhsOpnd, Operand &rhs CHECK_FATAL(false, "illegal logical operator"); } SelectAArch64CSet(resOpnd, GetCondOperand(cc), (dsize == k64BitSize)); + static_cast(resOpnd).SetCsetOpnd(); } Operand *AArch64CGFunc::SelectCmpOp(CompareNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) { @@ -5099,32 +5100,42 @@ Operand *AArch64CGFunc::SelectSelect(TernaryNode &node, Operand &opnd0, Operand PrimType cmpType = static_cast(node.Opnd(0))->GetOpndType(); bool isFloat = IsPrimitiveFloat(cmpType); bool unsignedIntegerComparison = !isFloat && !IsSignedInteger(cmpType); - switch (opcode) { - case OP_eq: - cc = CC_EQ; - break; - case OP_ne: - cc = CC_NE; - break; - case OP_le: - cc = unsignedIntegerComparison ? CC_LS : CC_LE; - break; - case OP_ge: - cc = unsignedIntegerComparison ? CC_HS : CC_GE; - break; - case OP_gt: - cc = unsignedIntegerComparison ? CC_HI : CC_GT; - break; - case OP_lt: - if (CanLtOptimized(*(node.Opnd(0)))) { - cc = unsignedIntegerComparison ? CC_LO : CC_LT; - } else { - hasCompare = true; - } - break; - default: - hasCompare = true; - break; + /* For nested Select expr, the outer Select may have processed the "cond" expr and + in register. The inner Select may have its own "cond" and hence its own cc reg, + the outer Select must not share the same cc. Note outer SelectSelect is to be + called later than the inner SelectSelect. If the outer SelectSelect found the + cond already processed and was from a compare condition expr, create a new compare. */ + if (opnd0.IsRegister() && static_cast(opnd0).IsCsetOpnd()) { + cc = CC_NE; + isCompare = true; + } else { + switch (opcode) { + case OP_eq: + cc = CC_EQ; + break; + case OP_ne: + cc = CC_NE; + break; + case OP_le: + cc = unsignedIntegerComparison ? CC_LS : CC_LE; + break; + case OP_ge: + cc = unsignedIntegerComparison ? CC_HS : CC_GE; + break; + case OP_gt: + cc = unsignedIntegerComparison ? CC_HI : CC_GT; + break; + case OP_lt: + if (CanLtOptimized(*(node.Opnd(0)))) { + cc = unsignedIntegerComparison ? CC_LO : CC_LT; + } else { + isCompare = true; + } + break; + default: + isCompare = true; + break; + } } SelectSelect(resOpnd, opnd0, opnd1, opnd2, dtype, ctype, hasCompare, cc); return &resOpnd;