Author: zhuqing Date: 2011-06-16 03:09:17 -0400 (Thu, 16 Jun 2011) New Revision: 3649
Modified: trunk/osprey/be/cg/ia64/expand.cxx Log: Fix bug704. Add some intrinsic support for IA64. Reviewed by Jianxin. Modified: trunk/osprey/be/cg/ia64/expand.cxx =================================================================== --- trunk/osprey/be/cg/ia64/expand.cxx 2011-06-15 06:41:57 UTC (rev 3648) +++ trunk/osprey/be/cg/ia64/expand.cxx 2011-06-16 07:09:17 UTC (rev 3649) @@ -1419,6 +1419,14 @@ } void +Expand_Binary_Nand (TN *dest, TN *src1, TN *src2, TYPE_ID mtype, OPS *ops) +{ + TN *tmp = Build_TN_Like(dest); + Expand_Binary_And_Or (TOP_and, tmp, src1, src2, mtype, ops); + Expand_Binary_And_Or (TOP_xor, dest, tmp, Gen_Literal_TN(1, 4), mtype, ops); +} + +void Expand_Binary_Or (TN *dest, TN *src1, TN *src2, TYPE_ID mtype, OPS *ops) { Expand_Binary_And_Or (TOP_or, dest, src1, src2, mtype, ops); @@ -3395,6 +3403,7 @@ Get_Intrinsic_Size_Mtype (INTRINSIC id) { switch (id) { + case INTRN_BOOL_COMPARE_AND_SWAP_I4: case INTRN_COMPARE_AND_SWAP_I4: case INTRN_LOCK_TEST_AND_SET_I4: case INTRN_LOCK_RELEASE_I4: @@ -3411,6 +3420,7 @@ case INTRN_FETCH_AND_AND_I4: case INTRN_FETCH_AND_NAND_I4: return MTYPE_I4; + case INTRN_BOOL_COMPARE_AND_SWAP_I8: case INTRN_COMPARE_AND_SWAP_I8: case INTRN_LOCK_TEST_AND_SET_I8: case INTRN_LOCK_RELEASE_I8: @@ -3475,160 +3485,163 @@ // expand these at cgexp time to avoid bundling issues // when handling simulated ops in cgemit. - switch (id) { - case INTRN_COMPARE_AND_SWAP_I4: - case INTRN_COMPARE_AND_SWAP_I8: - // - // compare_and_swap (type* ptr, type oldvalue, type newvalue) - // if (*ptr != oldvalue) return 0; - // else { - // *ptr = newvalue; - // return 1; - // } - // where op0 == ptr, op1 == oldvalue, op2 == newvalue - result = Build_TN_Of_Mtype (MTYPE_I8); - ar_ccv = Build_Dedicated_TN ( ISA_REGISTER_CLASS_application, - (REGISTER)(REGISTER_MIN + 32), - 8); - Build_OP (TOP_mov_t_ar_r, ar_ccv, True_TN, op1, ops); - Build_OP (TOP_mf, True_TN, ops); // memory fence - if (size_mtype == MTYPE_I4) - top = TOP_cmpxchg4; - else - top = TOP_cmpxchg8; - Build_OP (top, result, True_TN, Gen_Enum_TN(ECV_sem_rel), - Gen_Enum_TN(ECV_ldhint_nta), op0, op2, ops); - p1 = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate); - p2 = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate); - Build_OP (TOP_cmp_eq, p1, p2, True_TN, result, op1, ops); - Build_OP (TOP_mov_i, result, p1, Gen_Literal_TN(1, 4), ops); - Build_OP (TOP_mov, result, p2, Zero_TN, ops); - break; - case INTRN_LOCK_TEST_AND_SET_I4: - case INTRN_LOCK_TEST_AND_SET_I8: - // type __lock_test_and_set (type* ptr, type value, ...) - // atomically store the supplied value in *ptr - // and return the old value of *ptr - // i.e. { tmp = *ptr; *ptr = value; return tmp; } - // op0 == ptr, op1 == value - if (size_mtype == MTYPE_I4) - top = TOP_xchg4; - else - top = TOP_xchg8; - result = Build_TN_Of_Mtype (MTYPE_I8); - Build_OP (top, result, True_TN, Gen_Enum_TN(ECV_ldhint_nta), - op0, op1, ops); - break; + if (id == INTRN_BOOL_COMPARE_AND_SWAP_I4 || id == INTRN_BOOL_COMPARE_AND_SWAP_I8 || + id == INTRN_COMPARE_AND_SWAP_I4 || id == INTRN_COMPARE_AND_SWAP_I8) { + // + // compare_and_swap (type* ptr, type oldvalue, type newvalue) + // if (*ptr != oldvalue) return 0; + // else { + // *ptr = newvalue; + // return 1; + // } + // where op0 == ptr, op1 == oldvalue, op2 == newvalue + result = Build_TN_Of_Mtype (MTYPE_I8); + ar_ccv = Build_Dedicated_TN ( ISA_REGISTER_CLASS_application, + (REGISTER)(REGISTER_MIN + 32), + 8); + Build_OP (TOP_mov_t_ar_r, ar_ccv, True_TN, op1, ops); + Build_OP (TOP_mf, True_TN, ops); // memory fence + if (size_mtype == MTYPE_I4) + top = TOP_cmpxchg4; + else + top = TOP_cmpxchg8; + Build_OP (top, result, True_TN, Gen_Enum_TN(ECV_sem_rel), + Gen_Enum_TN(ECV_ldhint_nta), op0, op2, ops); + p1 = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate); + p2 = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate); + Build_OP (TOP_cmp_eq, p1, p2, True_TN, result, op1, ops); + Build_OP (TOP_mov_i, result, p1, Gen_Literal_TN(1, 4), ops); + Build_OP (TOP_mov, result, p2, Zero_TN, ops); + return result; + } - case INTRN_LOCK_RELEASE_I4: - case INTRN_LOCK_RELEASE_I8: - // "void __lock_release (type* ptr, ...)" - // Set *ptr to 0. (i.e.) { *ptr = 0 } - // op0 == ptr - if (size_mtype == MTYPE_I4) - top = TOP_st4; - else - top = TOP_st8; - Build_OP (top, True_TN, - Gen_Enum_TN(ECV_sttype_rel), - Gen_Enum_TN(ECV_sthint_nta), - op0, Zero_TN, ops); - break; + else if (id == INTRN_LOCK_TEST_AND_SET_I4 || id == INTRN_LOCK_TEST_AND_SET_I8) { + // type __lock_test_and_set (type* ptr, type value, ...) + // atomically store the supplied value in *ptr + // and return the old value of *ptr + // i.e. { tmp = *ptr; *ptr = value; return tmp; } + // op0 == ptr, op1 == value + if (size_mtype == MTYPE_I4) + top = TOP_xchg4; + else + top = TOP_xchg8; + result = Build_TN_Of_Mtype (MTYPE_I8); + Build_OP (top, result, True_TN, Gen_Enum_TN(ECV_ldhint_nta), + op0, op1, ops); + return result; + } - case INTRN_SYNCHRONIZE: - Build_OP (TOP_mf, True_TN, ops); // memory fence - break; + else if (id == INTRN_LOCK_RELEASE_I4 || id == INTRN_LOCK_RELEASE_I8) { + // "void __lock_release (type* ptr, ...)" + // Set *ptr to 0. (i.e.) { *ptr = 0 } + // op0 == ptr + if (size_mtype == MTYPE_I4) + top = TOP_st4; + else + top = TOP_st8; + Build_OP (top, True_TN, + Gen_Enum_TN(ECV_sttype_rel), + Gen_Enum_TN(ECV_sthint_nta), + op0, Zero_TN, ops); + return result; + } - case INTRN_FETCH_AND_ADD_I4: - case INTRN_FETCH_AND_ADD_I8: - // fetch_and_add (type *ptr, type value, ...) - // tmp = *ptr; *ptr += value; return tmp; - // op0 = ptr, op1 = value - // fetchadd inst only takes +/- 1,4,8,16 - if (TN_is_constant(op1) && TN_has_value(op1) - && ISA_LC_Value_In_Class ( TN_value(op1), LC_fetchadd) ) - { - Build_OP (TOP_mf, True_TN, ops); // memory fence - if (size_mtype == MTYPE_I4) - top = TOP_fetchadd4; - else - top = TOP_fetchadd8; - result = Build_TN_Of_Mtype (MTYPE_I8); - Build_OP (top, result, True_TN, - Gen_Enum_TN(ECV_sem_rel), - Gen_Enum_TN(ECV_ldhint), - op0, op1, ops); - break; - } - /* fallthru */ - case INTRN_ADD_AND_FETCH_I4: - case INTRN_ADD_AND_FETCH_I8: - { - // tmp == new *ptr, result == old *ptr - TN *orig_value = Build_TN_Of_Mtype (size_mtype); - TN *old_value = Build_TN_Of_Mtype (size_mtype); - TN *new_value = Build_TN_Of_Mtype (size_mtype); - if (Intrinsic_Returns_New_Value(id)) - result = new_value; - else - result = old_value; - // immed doesn't fit, so do loop case - Expand_Load ( - // load is of address, not of result type - OPCODE_make_op(OPR_LDID, Pointer_Mtype, Pointer_Mtype), - orig_value, op0, Gen_Literal_TN (0, 4), V_NONE, ops); + else if (id == INTRN_SYNCHRONIZE) { + Build_OP (TOP_mf, True_TN, ops); // memory fence + return result; + } + + // fetch_and_add (type *ptr, type value, ...) + // tmp = *ptr; *ptr += value; return tmp; + // op0 = ptr, op1 = value + // fetchadd inst only takes +/- 1,4,8,16 + else if((id == INTRN_FETCH_AND_ADD_I4 || id == INTRN_FETCH_AND_ADD_I8) && + (TN_is_constant(op1) && (TN_value(op1) == 1 || TN_value(op1) == -1 || + TN_value(op1) == 4 || TN_value(op1) == -4 || TN_value(op1) == 8 || + TN_value(op1) == -8 || TN_value(op1) == 16 || TN_value(op1) == -16 ))){ + Build_OP (TOP_mf, True_TN, ops); // memory fence + if (size_mtype == MTYPE_I4) + top = TOP_fetchadd4; + else + top = TOP_fetchadd8; + result = Build_TN_Of_Mtype (MTYPE_I8); + Build_OP (top, result, True_TN, + Gen_Enum_TN(ECV_sem_rel), + Gen_Enum_TN(ECV_ldhint), + op0, op1, ops); + return result; + } - *label = Gen_Temp_Label(); - Expand_Add (new_value, orig_value, op1, size_mtype, loop_ops); - ar_ccv = Build_Dedicated_TN ( ISA_REGISTER_CLASS_application, - (REGISTER)(REGISTER_MIN + 32), - 8); - Build_OP (TOP_mov_t_ar_r, ar_ccv, True_TN, orig_value, loop_ops); - Build_OP (TOP_mf, True_TN, loop_ops); // memory fence - if (size_mtype == MTYPE_I4) - top = TOP_cmpxchg4; - else - top = TOP_cmpxchg8; - Build_OP (top, old_value, True_TN, Gen_Enum_TN(ECV_sem_rel), - Gen_Enum_TN(ECV_ldhint), op0, new_value, loop_ops); - p1 = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate); - p2 = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate); - Build_OP (TOP_cmp_eq, p1, p2, True_TN, old_value, orig_value, loop_ops); - Build_OP (TOP_mov, orig_value, p2, old_value, loop_ops); - Build_OP (TOP_br_cond, p2, - Gen_Enum_TN(ECV_bwh_dptk), - Gen_Enum_TN(ECV_ph_few), - Gen_Enum_TN(ECV_dh), - Gen_Label_TN(*label,0), loop_ops); - break; + else { + // tmp == new *ptr, result == old *ptr + TN *orig_value = Build_TN_Of_Mtype (size_mtype); + TN *old_value = Build_TN_Of_Mtype (size_mtype); + TN *new_value = Build_TN_Of_Mtype (size_mtype); + // immed doesn't fit, so do loop case + Expand_Load ( + // load is of address, not of result type + OPCODE_make_op(OPR_LDID, Pointer_Mtype, Pointer_Mtype), + orig_value, op0, Gen_Literal_TN (0, 4), V_NONE, ops); + + *label = Gen_Temp_Label(); + if(id == INTRN_FETCH_AND_ADD_I4 || id == INTRN_FETCH_AND_ADD_I8 || + id == INTRN_ADD_AND_FETCH_I4 || id == INTRN_ADD_AND_FETCH_I8){ + Expand_Add (new_value, orig_value, op1, size_mtype, loop_ops); } - case INTRN_FETCH_AND_SUB_I4: - case INTRN_FETCH_AND_SUB_I8: - case INTRN_SUB_AND_FETCH_I4: - case INTRN_OR_AND_FETCH_I4: - case INTRN_XOR_AND_FETCH_I4: - case INTRN_AND_AND_FETCH_I4: - case INTRN_NAND_AND_FETCH_I4: - case INTRN_FETCH_AND_OR_I4: - case INTRN_FETCH_AND_XOR_I4: - case INTRN_FETCH_AND_AND_I4: - case INTRN_FETCH_AND_NAND_I4: - case INTRN_SUB_AND_FETCH_I8: - case INTRN_OR_AND_FETCH_I8: - case INTRN_XOR_AND_FETCH_I8: - case INTRN_AND_AND_FETCH_I8: - case INTRN_NAND_AND_FETCH_I8: - case INTRN_FETCH_AND_OR_I8: - case INTRN_FETCH_AND_XOR_I8: - case INTRN_FETCH_AND_AND_I8: - case INTRN_FETCH_AND_NAND_I8: - default: - #pragma mips_frequency_hint NEVER - FmtAssert (FALSE, ("WHIRL_To_OPs: illegal intrinsic call")); - /*NOTREACHED*/ + else if(id == INTRN_FETCH_AND_SUB_I4 || id == INTRN_FETCH_AND_SUB_I8 || + id == INTRN_SUB_AND_FETCH_I4 || id == INTRN_SUB_AND_FETCH_I8){ + Expand_Sub (new_value, orig_value, op1, size_mtype, loop_ops); + } + else if(id == INTRN_FETCH_AND_OR_I4 || id == INTRN_FETCH_AND_OR_I8 || + id == INTRN_OR_AND_FETCH_I4 || id == INTRN_OR_AND_FETCH_I8){ + Expand_Binary_Or (new_value, orig_value, op1, size_mtype, loop_ops); + } + else if(id == INTRN_FETCH_AND_AND_I4 || id == INTRN_FETCH_AND_AND_I8 || + id == INTRN_AND_AND_FETCH_I4 || id == INTRN_AND_AND_FETCH_I8){ + Expand_Binary_And (new_value, orig_value, op1, size_mtype, loop_ops); + } + else if(id == INTRN_FETCH_AND_XOR_I4 || id == INTRN_FETCH_AND_XOR_I8 || + id == INTRN_XOR_AND_FETCH_I4 || id == INTRN_XOR_AND_FETCH_I8){ + Expand_Binary_Xor (new_value, orig_value, op1, size_mtype, loop_ops); + } + else if(id == INTRN_FETCH_AND_NAND_I4 || id == INTRN_FETCH_AND_NAND_I8 || + id == INTRN_NAND_AND_FETCH_I4 || id == INTRN_NAND_AND_FETCH_I8){ + Expand_Binary_Nand (new_value, orig_value, op1, size_mtype, loop_ops); + } + else{ + #pragma mips_frequency_hint NEVER + FmtAssert (FALSE, ("WHIRL_To_OPs: illegal intrinsic call")); + } + ar_ccv = Build_Dedicated_TN ( ISA_REGISTER_CLASS_application, + (REGISTER)(REGISTER_MIN + 32), + 8); + Build_OP (TOP_mov_t_ar_r, ar_ccv, True_TN, orig_value, loop_ops); + Build_OP (TOP_mf, True_TN, loop_ops); // memory fence + if (size_mtype == MTYPE_I4) + top = TOP_cmpxchg4; + else + top = TOP_cmpxchg8; + Build_OP (top, old_value, True_TN, Gen_Enum_TN(ECV_sem_rel), + Gen_Enum_TN(ECV_ldhint), op0, new_value, loop_ops); + p1 = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate); + p2 = Build_RCLASS_TN (ISA_REGISTER_CLASS_predicate); + Build_OP (TOP_cmp_eq, p1, p2, True_TN, old_value, orig_value, loop_ops); + if (Intrinsic_Returns_New_Value(id)){ + Build_OP (TOP_mov, orig_value, p2, new_value, loop_ops); + result = new_value; + } + else { + Build_OP (TOP_mov, orig_value, p2, old_value, loop_ops); + result = old_value; + } + Build_OP (TOP_br_cond, p2, + Gen_Enum_TN(ECV_bwh_dptk), + Gen_Enum_TN(ECV_ph_few), + Gen_Enum_TN(ECV_dh), + Gen_Label_TN(*label,0), loop_ops); + return result; } - return result; } ------------------------------------------------------------------------------ EditLive Enterprise is the world's most technically advanced content authoring tool. Experience the power of Track Changes, Inline Image Editing and ensure content is compliant with Accessibility Checking. http://p.sf.net/sfu/ephox-dev2dev _______________________________________________ Open64-devel mailing list Open64-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/open64-devel