llvm.org GIT mirror llvm / 95d1109
Refactor the tablegen DAGISelEmitter code for outputing calls to getTargetNode and SelectNodeTo to reduce duplication, and to make some of the getTargetNode code available to SelectNodeTo. Use SelectNodeTo instead of getTargetNode in several new interesting cases, as it mutates nodes in place instead of creating new ones. This triggers some scheduling behavior differences due to nodes being presented to the scheduler in a different order. Some of the arbitrary scheduling decisions it makes are now arbitrarily made differently. This is visible in CodeGen/PowerPC/LargeAbsoluteAddr.ll, where a trivial scheduling difference led to a trivial register allocation difference. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53203 91177308-0d34-0410-b5e6-96231b3b80d8 Dan Gohman 12 years ago
2 changed file(s) with 227 addition(s) and 220 deletion(s). Raw diff Collapse all Expand all
0 ; RUN: llvm-as < %s | llc -march=ppc32 -mtriple=powerpc-apple-darwin | \
1 ; RUN: grep {stw r3, 32751}
1 ; RUN: grep {stw r2, 32751}
22 ; RUN: llvm-as < %s | llc -march=ppc64 -mtriple=powerpc-apple-darwin | \
3 ; RUN: grep {stw r3, 32751}
3 ; RUN: grep {stw r2, 32751}
44 ; RUN: llvm-as < %s | llc -march=ppc64 -mtriple=powerpc-apple-darwin | \
55 ; RUN: grep {std r2, 9024}
66
1717 #include "llvm/Support/MathExtras.h"
1818 #include "llvm/Support/Streams.h"
1919 #include
20 #include
2021 using namespace llvm;
2122
2223 //===----------------------------------------------------------------------===//
10321033 }
10331034
10341035 unsigned ResNo = TmpNo++;
1035 if (!isRoot || InputHasChain || NodeHasChain || NodeHasOutFlag ||
1036 NodeHasOptInFlag || HasImpResults) {
1036
1037 unsigned OpsNo = OpcNo;
1038 std::string CodePrefix;
1039 bool ChainAssignmentNeeded = NodeHasChain && !isRoot;
1040 std::deque After;
1041 std::string NodeName;
1042 if (!isRoot) {
1043 NodeName = "Tmp" + utostr(ResNo);
1044 CodePrefix = "SDOperand " + NodeName + "(";
1045 } else {
1046 NodeName = "ResNode";
1047 if (!ResNodeDecled) {
1048 CodePrefix = "SDNode *" + NodeName + " = ";
1049 ResNodeDecled = true;
1050 } else
1051 CodePrefix = NodeName + " = ";
1052 }
1053
1054 std::string Code = "Opc" + utostr(OpcNo);
1055
1056 emitOpcode(II.Namespace + "::" + II.TheDef->getName());
1057
1058 // Output order: results, chain, flags
1059 // Result types.
1060 if (NumResults > 0 && N->getTypeNum(0) != MVT::isVoid) {
1061 Code += ", VT" + utostr(VTNo);
1062 emitVT(getEnumName(N->getTypeNum(0)));
1063 }
1064 // Add types for implicit results in physical registers, scheduler will
1065 // care of adding copyfromreg nodes.
1066 for (unsigned i = 0; i < NumDstRegs; i++) {
1067 Record *RR = DstRegs[i];
1068 if (RR->isSubClassOf("Register")) {
1069 MVT::SimpleValueType RVT = getRegisterValueType(RR, CGT);
1070 Code += ", " + getEnumName(RVT);
1071 }
1072 }
1073 if (NodeHasChain)
1074 Code += ", MVT::Other";
1075 if (NodeHasOutFlag)
1076 Code += ", MVT::Flag";
1077
1078 // Inputs.
1079 if (IsVariadic) {
1080 for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
1081 emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
1082 AllOps.clear();
1083
1084 // Figure out whether any operands at the end of the op list are not
1085 // part of the variable section.
1086 std::string EndAdjust;
1087 if (NodeHasInFlag || HasImpInputs)
1088 EndAdjust = "-1"; // Always has one flag.
1089 else if (NodeHasOptInFlag)
1090 EndAdjust = "-(HasInFlag?1:0)"; // May have a flag.
1091
1092 emitCode("for (unsigned i = NumInputRootOps + " + utostr(NodeHasChain) +
1093 ", e = N.getNumOperands()" + EndAdjust + "; i != e; ++i) {");
1094
1095 emitCode(" AddToISelQueue(N.getOperand(i));");
1096 emitCode(" Ops" + utostr(OpsNo) + ".push_back(N.getOperand(i));");
1097 emitCode("}");
1098 }
1099
1100 // Generate MemOperandSDNodes nodes for each memory accesses covered by
1101 // this pattern.
1102 if (II.isSimpleLoad | II.mayLoad | II.mayStore) {
1103 std::vector::const_iterator mi, mie;
1104 for (mi = LSI.begin(), mie = LSI.end(); mi != mie; ++mi) {
1105 emitCode("SDOperand LSI_" + *mi + " = "
1106 "CurDAG->getMemOperand(cast(" +
1107 *mi + ")->getMemOperand());");
1108 if (IsVariadic)
1109 emitCode("Ops" + utostr(OpsNo) + ".push_back(LSI_" + *mi + ");");
1110 else
1111 AllOps.push_back("LSI_" + *mi);
1112 }
1113 }
1114
1115 if (NodeHasChain) {
1116 if (IsVariadic)
1117 emitCode("Ops" + utostr(OpsNo) + ".push_back(" + ChainName + ");");
1118 else
1119 AllOps.push_back(ChainName);
1120 }
1121
1122 if (IsVariadic) {
1123 if (NodeHasInFlag || HasImpInputs)
1124 emitCode("Ops" + utostr(OpsNo) + ".push_back(InFlag);");
1125 else if (NodeHasOptInFlag) {
1126 emitCode("if (HasInFlag)");
1127 emitCode(" Ops" + utostr(OpsNo) + ".push_back(InFlag);");
1128 }
1129 Code += ", &Ops" + utostr(OpsNo) + "[0], Ops" + utostr(OpsNo) +
1130 ".size()";
1131 } else if (NodeHasInFlag || NodeHasOptInFlag || HasImpInputs)
1132 AllOps.push_back("InFlag");
1133
1134 unsigned NumOps = AllOps.size();
1135 if (NumOps) {
1136 if (!NodeHasOptInFlag && NumOps < 4) {
1137 for (unsigned i = 0; i != NumOps; ++i)
1138 Code += ", " + AllOps[i];
1139 } else {
1140 std::string OpsCode = "SDOperand Ops" + utostr(OpsNo) + "[] = { ";
1141 for (unsigned i = 0; i != NumOps; ++i) {
1142 OpsCode += AllOps[i];
1143 if (i != NumOps-1)
1144 OpsCode += ", ";
1145 }
1146 emitCode(OpsCode + " };");
1147 Code += ", Ops" + utostr(OpsNo) + ", ";
1148 if (NodeHasOptInFlag) {
1149 Code += "HasInFlag ? ";
1150 Code += utostr(NumOps) + " : " + utostr(NumOps-1);
1151 } else
1152 Code += utostr(NumOps);
1153 }
1154 }
1155
1156 if (!isRoot)
1157 Code += "), 0";
1158
1159 bool NeedReplace = false;
1160 if (!isRoot) {
1161 NodeOps.push_back("Tmp" + utostr(ResNo));
1162 } else {
1163
1164 if (NodeHasOutFlag) {
1165 if (!InFlagDecled) {
1166 After.push_back("SDOperand InFlag(ResNode, " +
1167 utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) +
1168 ");");
1169 InFlagDecled = true;
1170 } else
1171 After.push_back("InFlag = SDOperand(ResNode, " +
1172 utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) +
1173 ");");
1174 }
1175
1176 if (FoldedChains.size() > 0) {
10371177 std::string Code;
1038 std::string Code2;
1039 std::string NodeName;
1040 if (!isRoot) {
1041 NodeName = "Tmp" + utostr(ResNo);
1042 Code2 = "SDOperand " + NodeName + "(";
1178 for (unsigned j = 0, e = FoldedChains.size(); j < e; j++)
1179 After.push_back("ReplaceUses(SDOperand(" +
1180 FoldedChains[j].first + ".Val, " +
1181 utostr(FoldedChains[j].second) +
1182 "), SDOperand(ResNode, " +
1183 utostr(NumResults+NumDstRegs) + "));");
1184 NeedReplace = true;
1185 }
1186
1187 if (NodeHasOutFlag) {
1188 if (FoldedFlag.first != "") {
1189 After.push_back("ReplaceUses(SDOperand(" + FoldedFlag.first +
1190 ".Val, " +
1191 utostr(FoldedFlag.second) + "), InFlag);");
10431192 } else {
1044 NodeName = "ResNode";
1045 if (!ResNodeDecled) {
1046 Code2 = "SDNode *" + NodeName + " = ";
1047 ResNodeDecled = true;
1048 } else
1049 Code2 = NodeName + " = ";
1050 }
1051
1052 Code += "CurDAG->getTargetNode(Opc" + utostr(OpcNo);
1053 unsigned OpsNo = OpcNo;
1054 emitOpcode(II.Namespace + "::" + II.TheDef->getName());
1055
1056 // Output order: results, chain, flags
1057 // Result types.
1058 if (NumResults > 0 && N->getTypeNum(0) != MVT::isVoid) {
1059 Code += ", VT" + utostr(VTNo);
1060 emitVT(getEnumName(N->getTypeNum(0)));
1061 }
1062 // Add types for implicit results in physical registers, scheduler will
1063 // care of adding copyfromreg nodes.
1064 for (unsigned i = 0; i < NumDstRegs; i++) {
1065 Record *RR = DstRegs[i];
1066 if (RR->isSubClassOf("Register")) {
1067 MVT::SimpleValueType RVT = getRegisterValueType(RR, CGT);
1068 Code += ", " + getEnumName(RVT);
1069 }
1070 }
1071 if (NodeHasChain)
1072 Code += ", MVT::Other";
1193 assert(NodeHasProperty(Pattern, SDNPOutFlag, CGP));
1194 After.push_back("ReplaceUses(SDOperand(N.Val, " +
1195 utostr(NumPatResults + (unsigned)InputHasChain)
1196 +"), InFlag);");
1197 }
1198 NeedReplace = true;
1199 }
1200
1201 if (NeedReplace && InputHasChain) {
1202 After.push_back("ReplaceUses(SDOperand(N.Val, " +
1203 utostr(NumPatResults) + "), SDOperand(" + ChainName
1204 + ".Val, " + ChainName + ".ResNo" + "));");
1205 ChainAssignmentNeeded |= NodeHasChain;
1206 }
1207
1208 // User does not expect the instruction would produce a chain!
1209 if ((!InputHasChain && NodeHasChain) && NodeHasOutFlag) {
1210 ;
1211 } else if (InputHasChain && !NodeHasChain) {
1212 // One of the inner node produces a chain.
10731213 if (NodeHasOutFlag)
1074 Code += ", MVT::Flag";
1075
1076 // Inputs.
1077 if (IsVariadic) {
1078 for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
1079 emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
1080 AllOps.clear();
1081
1082 // Figure out whether any operands at the end of the op list are not
1083 // part of the variable section.
1084 std::string EndAdjust;
1085 if (NodeHasInFlag || HasImpInputs)
1086 EndAdjust = "-1"; // Always has one flag.
1087 else if (NodeHasOptInFlag)
1088 EndAdjust = "-(HasInFlag?1:0)"; // May have a flag.
1089
1090 emitCode("for (unsigned i = NumInputRootOps + " + utostr(NodeHasChain) +
1091 ", e = N.getNumOperands()" + EndAdjust + "; i != e; ++i) {");
1092
1093 emitCode(" AddToISelQueue(N.getOperand(i));");
1094 emitCode(" Ops" + utostr(OpsNo) + ".push_back(N.getOperand(i));");
1095 emitCode("}");
1096 }
1097
1098 // Generate MemOperandSDNodes nodes for each memory accesses covered by
1099 // this pattern.
1100 if (II.isSimpleLoad | II.mayLoad | II.mayStore) {
1101 std::vector::const_iterator mi, mie;
1102 for (mi = LSI.begin(), mie = LSI.end(); mi != mie; ++mi) {
1103 emitCode("SDOperand LSI_" + *mi + " = "
1104 "CurDAG->getMemOperand(cast(" +
1105 *mi + ")->getMemOperand());");
1106 if (IsVariadic)
1107 emitCode("Ops" + utostr(OpsNo) + ".push_back(LSI_" + *mi + ");");
1108 else
1109 AllOps.push_back("LSI_" + *mi);
1110 }
1111 }
1112
1113 if (NodeHasChain) {
1114 if (IsVariadic)
1115 emitCode("Ops" + utostr(OpsNo) + ".push_back(" + ChainName + ");");
1116 else
1117 AllOps.push_back(ChainName);
1118 }
1119
1120 if (IsVariadic) {
1121 if (NodeHasInFlag || HasImpInputs)
1122 emitCode("Ops" + utostr(OpsNo) + ".push_back(InFlag);");
1123 else if (NodeHasOptInFlag) {
1124 emitCode("if (HasInFlag)");
1125 emitCode(" Ops" + utostr(OpsNo) + ".push_back(InFlag);");
1126 }
1127 Code += ", &Ops" + utostr(OpsNo) + "[0], Ops" + utostr(OpsNo) +
1128 ".size()";
1129 } else if (NodeHasInFlag || NodeHasOptInFlag || HasImpInputs)
1130 AllOps.push_back("InFlag");
1131
1132 unsigned NumOps = AllOps.size();
1133 if (NumOps) {
1134 if (!NodeHasOptInFlag && NumOps < 4) {
1135 for (unsigned i = 0; i != NumOps; ++i)
1136 Code += ", " + AllOps[i];
1137 } else {
1138 std::string OpsCode = "SDOperand Ops" + utostr(OpsNo) + "[] = { ";
1139 for (unsigned i = 0; i != NumOps; ++i) {
1140 OpsCode += AllOps[i];
1141 if (i != NumOps-1)
1142 OpsCode += ", ";
1143 }
1144 emitCode(OpsCode + " };");
1145 Code += ", Ops" + utostr(OpsNo) + ", ";
1146 if (NodeHasOptInFlag) {
1147 Code += "HasInFlag ? ";
1148 Code += utostr(NumOps) + " : " + utostr(NumOps-1);
1149 } else
1150 Code += utostr(NumOps);
1151 }
1152 }
1153
1214 After.push_back("ReplaceUses(SDOperand(N.Val, " +
1215 utostr(NumPatResults+1) +
1216 "), SDOperand(ResNode, N.ResNo-1));");
1217 After.push_back("ReplaceUses(SDOperand(N.Val, " +
1218 utostr(NumPatResults) + "), " + ChainName + ");");
1219 NeedReplace = true;
1220 }
1221 }
1222
1223 if (ChainAssignmentNeeded) {
1224 // Remember which op produces the chain.
1225 std::string ChainAssign;
11541226 if (!isRoot)
1155 Code += "), 0";
1156 emitCode(Code2 + Code + ");");
1157
1158 if (NodeHasChain) {
1159 // Remember which op produces the chain.
1160 if (!isRoot)
1161 emitCode(ChainName + " = SDOperand(" + NodeName +
1162 ".Val, " + utostr(NumResults+NumDstRegs) + ");");
1163 else
1164 emitCode(ChainName + " = SDOperand(" + NodeName +
1165 ", " + utostr(NumResults+NumDstRegs) + ");");
1166 }
1167
1168 if (!isRoot) {
1169 NodeOps.push_back("Tmp" + utostr(ResNo));
1170 return NodeOps;
1171 }
1172
1173 bool NeedReplace = false;
1174 if (NodeHasOutFlag) {
1175 if (!InFlagDecled) {
1176 emitCode("SDOperand InFlag(ResNode, " +
1177 utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) + ");");
1178 InFlagDecled = true;
1179 } else
1180 emitCode("InFlag = SDOperand(ResNode, " +
1181 utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) + ");");
1182 }
1183
1184 if (FoldedChains.size() > 0) {
1185 std::string Code;
1186 for (unsigned j = 0, e = FoldedChains.size(); j < e; j++)
1187 emitCode("ReplaceUses(SDOperand(" +
1188 FoldedChains[j].first + ".Val, " +
1189 utostr(FoldedChains[j].second) + "), SDOperand(ResNode, " +
1190 utostr(NumResults+NumDstRegs) + "));");
1191 NeedReplace = true;
1192 }
1193
1194 if (NodeHasOutFlag) {
1195 if (FoldedFlag.first != "") {
1196 emitCode("ReplaceUses(SDOperand(" + FoldedFlag.first + ".Val, " +
1197 utostr(FoldedFlag.second) + "), InFlag);");
1198 } else {
1199 assert(NodeHasProperty(Pattern, SDNPOutFlag, CGP));
1200 emitCode("ReplaceUses(SDOperand(N.Val, " +
1201 utostr(NumPatResults + (unsigned)InputHasChain)
1202 +"), InFlag);");
1203 }
1204 NeedReplace = true;
1205 }
1206
1207 if (NeedReplace && InputHasChain)
1208 emitCode("ReplaceUses(SDOperand(N.Val, " +
1209 utostr(NumPatResults) + "), SDOperand(" + ChainName
1210 + ".Val, " + ChainName + ".ResNo" + "));");
1211
1212 // User does not expect the instruction would produce a chain!
1213 if ((!InputHasChain && NodeHasChain) && NodeHasOutFlag) {
1214 ;
1215 } else if (InputHasChain && !NodeHasChain) {
1216 // One of the inner node produces a chain.
1217 if (NodeHasOutFlag)
1218 emitCode("ReplaceUses(SDOperand(N.Val, " + utostr(NumPatResults+1) +
1219 "), SDOperand(ResNode, N.ResNo-1));");
1220 emitCode("ReplaceUses(SDOperand(N.Val, " + utostr(NumPatResults) +
1221 "), " + ChainName + ");");
1222 }
1223
1224 emitCode("return ResNode;");
1227 ChainAssign = ChainName + " = SDOperand(" + NodeName +
1228 ".Val, " + utostr(NumResults+NumDstRegs) + ");";
1229 else
1230 ChainAssign = ChainName + " = SDOperand(" + NodeName +
1231 ", " + utostr(NumResults+NumDstRegs) + ");";
1232
1233 After.push_front(ChainAssign);
1234 }
1235
1236 // Use getTargetNode or SelectNodeTo? The safe choice is getTargetNode,
1237 // but SelectNodeTo can be faster.
1238 //
1239 // SelectNodeTo is not safe in a non-root context, or if there is any
1240 // replacement of results needed.
1241 //
1242 // SelectNodeTo is not profitable if it would require a dynamically
1243 // allocated operand list in a situation where getTargetNode would be
1244 // able to reuse a co-allocated operand list (as in a unary, binary or
1245 // ternary SDNode, for example).
1246 //
1247 if (!isRoot || NeedReplace ||
1248 (!IsVariadic && AllOps.size() < 4 &&
1249 Pattern->getNumChildren() + InputHasChain + NodeHasInFlag <
1250 AllOps.size())) {
1251 Code = "CurDAG->getTargetNode(" + Code;
12251252 } else {
1226 std::string Code = "return CurDAG->SelectNodeTo(N.Val, Opc" +
1227 utostr(OpcNo);
1228 if (N->getTypeNum(0) != MVT::isVoid)
1229 Code += ", VT" + utostr(VTNo);
1230 if (NodeHasOutFlag)
1231 Code += ", MVT::Flag";
1232
1233 if (NodeHasInFlag || NodeHasOptInFlag || HasImpInputs)
1234 AllOps.push_back("InFlag");
1235
1236 unsigned NumOps = AllOps.size();
1237 if (NumOps) {
1238 if (!NodeHasOptInFlag && NumOps < 4) {
1239 for (unsigned i = 0; i != NumOps; ++i)
1240 Code += ", " + AllOps[i];
1241 } else {
1242 std::string OpsCode = "SDOperand Ops" + utostr(OpcNo) + "[] = { ";
1243 for (unsigned i = 0; i != NumOps; ++i) {
1244 OpsCode += AllOps[i];
1245 if (i != NumOps-1)
1246 OpsCode += ", ";
1247 }
1248 emitCode(OpsCode + " };");
1249 Code += ", Ops" + utostr(OpcNo) + ", ";
1250 Code += utostr(NumOps);
1251 }
1252 }
1253 emitCode(Code + ");");
1254 emitOpcode(II.Namespace + "::" + II.TheDef->getName());
1255 if (N->getTypeNum(0) != MVT::isVoid)
1256 emitVT(getEnumName(N->getTypeNum(0)));
1257 }
1253 Code = "CurDAG->SelectNodeTo(N.Val, " + Code;
1254 }
1255 if (isRoot) {
1256 if (After.empty())
1257 CodePrefix = "return ";
1258 else
1259 After.push_back("return ResNode;");
1260 }
1261
1262 emitCode(CodePrefix + Code + ");");
1263 for (unsigned i = 0, e = After.size(); i != e; ++i)
1264 emitCode(After[i]);
12581265
12591266 return NodeOps;
12601267 } else if (Op->isSubClassOf("SDNodeXForm")) {