/** * Calculates the permutations to convert between source and destination indices (where source is * the generic instruction, destination is the target architecture specific instruction). * * @param intrinsic The intrinsic * @param rgSourceOps The array of source operands of the instruction * @param rgDestArgs The array of destination operands (the intrinsic arguments) * @param rgPermSourceToDest This array will contain the source → destination permutation on * exit of the method * @param rgPermDestToSource This array will contain the destination → source permutation on * exit of the method */ private static void getArgumentPermutations( Intrinsic intrinsic, IOperand[] rgSourceOps, Argument[] rgDestArgs, int[] rgPermSourceToDest, int[] rgPermDestToSource) { Arrays.fill(rgPermSourceToDest, UNDEFINED); Arrays.fill(rgPermDestToSource, UNDEFINED); String[] rgArgNamesGeneric = Globals.getIntrinsicArguments(intrinsic.getBaseName()); if (rgArgNamesGeneric != null) { for (int i = 0; i < rgSourceOps.length; i++) { rgPermSourceToDest[i] = i < rgSourceOps.length - 1 ? InstructionListTranslator.getArgNum(rgDestArgs, rgArgNamesGeneric[i]) : InstructionListTranslator.getOutputArgumentIndex( rgDestArgs); // last argument is output if (0 <= rgPermSourceToDest[i] && rgPermSourceToDest[i] < rgPermDestToSource.length) { if (rgPermDestToSource[rgPermSourceToDest[i]] == UNDEFINED) rgPermDestToSource[rgPermSourceToDest[i]] = i; } } } else { // no intrinsic arguments defined for this intrinsic; just return the identity permutation for (int i = 0; i < rgPermSourceToDest.length; i++) rgPermSourceToDest[i] = i; for (int i = 0; i < rgPermDestToSource.length; i++) rgPermDestToSource[i] = i; } }
/** * If instruction arguments are not compatible (e.g., an argument is passed by address, but the * intrinsic requires a register), this method tries to find operands which can be interchanged * and which make the operands compatible after interchanging. * * @param intrinsic The intrinsic to issue * @param rgSourceOps The array of operands of the original, generic instruction * @param rgDestArgs The array of intrinsic arguments * @param rgPermSourceToDest The source-to-destination permutation * @param rgPermDestToSource The destination-to-source permutation * @return */ private static IOperand[] compatibilizeCommutatives( Intrinsic intrinsic, IOperand[] rgSourceOps, Argument[] rgDestArgs, int[] rgPermSourceToDest, int[] rgPermDestToSource, int nOutputArgDestIndex, boolean bIntrinsicHasSharedResult) { if (bIntrinsicHasSharedResult) { // if there is an input argument that is the same as the output argument // try to permute it to the "shared" position IOperand opShared = rgSourceOps[rgPermDestToSource[nOutputArgDestIndex]]; int nCommonInOutIdx = InstructionListTranslator.getIndexOfNonSharedInputArgsResult(rgSourceOps, opShared); if (nCommonInOutIdx != -1) { int nOldPos = nCommonInOutIdx; int nNewPos = rgPermDestToSource[nOutputArgDestIndex]; if (Globals.canSwapIntrinsicArguments(intrinsic.getBaseName(), nOldPos, nNewPos) && InstructionListTranslator.isCompatible( rgSourceOps[nOldPos], rgDestArgs[rgPermSourceToDest[nNewPos]]) && InstructionListTranslator.isCompatible( rgSourceOps[nNewPos], rgDestArgs[rgPermSourceToDest[nOldPos]])) { // do the swap IOperand[] rgSourceOpsSwapped = new IOperand[rgSourceOps.length]; for (int k = 0; k < rgSourceOpsSwapped.length; k++) { if (k == nOldPos) rgSourceOpsSwapped[k] = rgSourceOps[nNewPos]; else if (k == nNewPos) rgSourceOpsSwapped[k] = rgSourceOps[nOldPos]; else rgSourceOpsSwapped[k] = rgSourceOps[k]; } return rgSourceOpsSwapped; } } } for (int i = 0; i < rgSourceOps.length; i++) { if (rgPermSourceToDest[i] != UNDEFINED) { if (!InstructionListTranslator.isCompatible( rgSourceOps[i], rgDestArgs[rgPermSourceToDest[i]])) { // try to find an argument which can be swapped with this non-compatible one // and check whether both operands are compatible after swapping for (int j = 0; j < rgSourceOps.length - 1; j++) { if (i == j) continue; if (Globals.canSwapIntrinsicArguments(intrinsic.getBaseName(), i, j)) { if (rgPermSourceToDest[j] != UNDEFINED && InstructionListTranslator.isCompatible( rgSourceOps[i], rgDestArgs[rgPermSourceToDest[j]]) && InstructionListTranslator.isCompatible( rgSourceOps[j], rgDestArgs[rgPermSourceToDest[i]])) { // assume that only one swap is to be done, i.e., there are only // two arguments that can be interchanged // do the swap IOperand[] rgSourceOpsSwapped = new IOperand[rgSourceOps.length]; for (int k = 0; k < rgSourceOpsSwapped.length; k++) { if (k == i) rgSourceOpsSwapped[k] = rgSourceOps[j]; else if (k == j) rgSourceOpsSwapped[k] = rgSourceOps[i]; else rgSourceOpsSwapped[k] = rgSourceOps[k]; } return rgSourceOpsSwapped; } } } } } } return rgSourceOps; }