aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-01-29 23:45:14 +0000
committerChris Lattner <sabre@nondot.org>2007-01-29 23:45:14 +0000
commit367f109ba954239a348c624a3331422bfdb31d03 (patch)
treeba9c93ef5a6c57af84e55a4f4263c3620485b58f
parentdb4e6e77fc6e97e0bc6d14a93ee191b91bc40777 (diff)
add initial support for handling inline asms with multiple constraints.
This doesn't do the "right thing" but will probably work in most cases. This implements CodeGen/PowerPC/2007-01-29-lbrx-asm.ll. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33643 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp46
1 files changed, 42 insertions, 4 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 3b452979aa..da351bbdf1 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -2433,6 +2433,44 @@ GetRegistersForValue(const std::string &ConstrCode,
return RegsForValue();
}
+/// getConstraintGenerality - Return an integer indicating how general CT is.
+static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) {
+ switch (CT) {
+ default: assert(0 && "Unknown constraint type!");
+ case TargetLowering::C_Other:
+ case TargetLowering::C_Unknown:
+ return 0;
+ case TargetLowering::C_Register:
+ return 1;
+ case TargetLowering::C_RegisterClass:
+ return 2;
+ case TargetLowering::C_Memory:
+ return 3;
+ }
+}
+
+static std::string GetMostGeneralConstraint(std::vector<std::string> &C,
+ const TargetLowering &TLI) {
+ assert(!C.empty() && "Must have at least one constraint");
+ if (C.size() == 1) return C[0];
+
+ std::string *Current = &C[0];
+ // If we have multiple constraints, try to pick the most general one ahead
+ // of time. This isn't a wonderful solution, but handles common cases.
+ TargetLowering::ConstraintType Flavor = TLI.getConstraintType(Current[0][0]);
+ for (unsigned j = 1, e = C.size(); j != e; ++j) {
+ TargetLowering::ConstraintType ThisFlavor = TLI.getConstraintType(C[j][0]);
+ if (getConstraintGenerality(ThisFlavor) >
+ getConstraintGenerality(Flavor)) {
+ // This constraint letter is more general than the previous one,
+ // use it.
+ Flavor = ThisFlavor;
+ Current = &C[j];
+ }
+ }
+ return *Current;
+}
+
/// visitInlineAsm - Handle a call to an InlineAsm object.
///
@@ -2462,8 +2500,8 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
std::set<unsigned> OutputRegs, InputRegs;
unsigned OpNum = 1;
for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
- assert(Constraints[i].Codes.size() == 1 && "Only handles one code so far!");
- std::string &ConstraintCode = Constraints[i].Codes[0];
+ std::string ConstraintCode =
+ GetMostGeneralConstraint(Constraints[i].Codes, TLI);
MVT::ValueType OpVT;
@@ -2527,8 +2565,8 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
OpNum = 1;
for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
- assert(Constraints[i].Codes.size() == 1 && "Only handles one code so far!");
- std::string &ConstraintCode = Constraints[i].Codes[0];
+ std::string ConstraintCode =
+ GetMostGeneralConstraint(Constraints[i].Codes, TLI);
switch (Constraints[i].Type) {
case InlineAsm::isOutput: {