Revision: 125328 Author: clattner Date: 2007-03-24 21:02:59 -0700 (Sat, 24 Mar 2007)
Log Message: ----------- Improve CanonicalizeConstraint to support canonicalization of multiple-alternative inline asm constraints, e.g., turn: __asm__ volatile("inw %w1, %w0" : "=a" (datum) : "Nd" (port)); into: "={ax},N{dx},... instead of: "={ax},Nd,... This allows us to correctly compile inline asm like the example above. Modified Paths: -------------- apple-local/branches/llvm/gcc/llvm-convert.cpp Modified: apple-local/branches/llvm/gcc/llvm-convert.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-03-25 03:39:48 UTC (rev 125327) +++ apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-03-25 04:02:59 UTC (rev 125328) @@ -3415,11 +3415,9 @@ /// CanonicalizeConstraint - If we can canonicalize the constraint into /// something simpler, do so now. This turns register classes with a single /// register into the register itself, expands builtin constraints to multiple -/// alternatives, etc. If the constraint cannot be simplified, this returns an -/// empty string. +/// alternatives, etc. static std::string CanonicalizeConstraint(const char *Constraint) { std::string Result; - unsigned RegClass; // Skip over modifier characters. bool DoneModifiers = false; @@ -3436,51 +3434,67 @@ ++Constraint; break; case '#': // No constraint letters left. - return ""; + return Result; } } + while (*Constraint) { + char ConstraintChar = *Constraint++; + + // 'g' is just short-hand for 'imr'. + if (ConstraintChar == 'g') { + Result += "imr"; + continue; + } - if (*Constraint == 'r') // r is a special case for some reason. - RegClass = GENERAL_REGS; - else if (*Constraint == 'g') - return "imr"; - else - RegClass = REG_CLASS_FROM_CONSTRAINT(*Constraint, Constraint); + // See if this is a regclass constraint. + unsigned RegClass; + if (ConstraintChar == 'r') + // REG_CLASS_FROM_CONSTRAINT doesn't support 'r' for some reason. + RegClass = GENERAL_REGS; + else + RegClass = REG_CLASS_FROM_CONSTRAINT(Constraint[-1], Constraint-1); - if (RegClass == NO_REGS) return Result; // not a reg class. + if (RegClass == NO_REGS) { // not a reg class. + Result += ConstraintChar; + continue; + } - // Look to see if the specified regclass has exactly one member, and if so, - // what it is. Cache this information in AnalyzedRegClasses once computed. - static std::map<unsigned, int> AnalyzedRegClasses; + // Look to see if the specified regclass has exactly one member, and if so, + // what it is. Cache this information in AnalyzedRegClasses once computed. + static std::map<unsigned, int> AnalyzedRegClasses; - std::map<unsigned, int>::iterator I =AnalyzedRegClasses.lower_bound(RegClass); + std::map<unsigned, int>::iterator I = + AnalyzedRegClasses.lower_bound(RegClass); - int RegMember; - if (I != AnalyzedRegClasses.end() && I->first == RegClass) { - // We've already computed this, reuse value. - RegMember = I->second; - } else { - // Otherwise, scan the regclass, looking for exactly one member. - RegMember = -1; // -1 => not one thing - for (unsigned j = 0; j != FIRST_PSEUDO_REGISTER; ++j) - if (TEST_HARD_REG_BIT(reg_class_contents[RegClass], j)) { - if (RegMember == -1) { - RegMember = j; - } else { - RegMember = -1; - break; + int RegMember; + if (I != AnalyzedRegClasses.end() && I->first == RegClass) { + // We've already computed this, reuse value. + RegMember = I->second; + } else { + // Otherwise, scan the regclass, looking for exactly one member. + RegMember = -1; // -1 => not a single-register class. + for (unsigned j = 0; j != FIRST_PSEUDO_REGISTER; ++j) + if (TEST_HARD_REG_BIT(reg_class_contents[RegClass], j)) { + if (RegMember == -1) { + RegMember = j; + } else { + RegMember = -1; + break; + } } - } - // Remember this answer for the next query of this regclass. - AnalyzedRegClasses.insert(I, std::make_pair(RegClass, RegMember)); - } + // Remember this answer for the next query of this regclass. + AnalyzedRegClasses.insert(I, std::make_pair(RegClass, RegMember)); + } - // If we found a single register register class, return the register. - if (RegMember != -1) { - Result = '{'; - Result += reg_names[RegMember]; - Result += '}'; + // If we found a single register register class, return the register. + if (RegMember != -1) { + Result += '{'; + Result += reg_names[RegMember]; + Result += '}'; + } else { + Result += ConstraintChar; + } } return Result; @@ -3556,14 +3570,7 @@ // If we can simplify the constraint into something else, do so now. This // avoids LLVM having to know about all the (redundant) GCC constraints. - std::string Simplified = CanonicalizeConstraint(Constraint+1); - if (!Simplified.empty()) { - char *NewConstraint = (char*)alloca(Simplified.size()+2); - NewConstraint[0] = '='; - memcpy(NewConstraint+1, &Simplified[0], Simplified.size()); - NewConstraint[Simplified.size()+1] = 0; - Constraint = NewConstraint; - } + std::string SimplifiedConstraint = '='+CanonicalizeConstraint(Constraint+1); LValue Dest = EmitLV(Operand); assert(!Dest.isBitfield() && "Cannot assign into a bitfield!"); @@ -3571,11 +3578,11 @@ assert(StoreCallResultAddr == 0 && "Already have a result val?"); StoreCallResultAddr = Dest.Ptr; ConstraintStr += ","; - ConstraintStr += Constraint; + ConstraintStr += SimplifiedConstraint; CallResultType = cast<PointerType>(Dest.Ptr->getType())->getElementType(); } else { ConstraintStr += ",="; - ConstraintStr += Constraint; + ConstraintStr += SimplifiedConstraint; CallOps.push_back(Dest.Ptr); CallArgTypes.push_back(Dest.Ptr->getType()); } @@ -3624,12 +3631,7 @@ } else { // If there is a simpler form for the register constraint, use it. std::string Simplified = CanonicalizeConstraint(Constraint); - if (!Simplified.empty()) { - ConstraintStr += Simplified; - } else { - // Otherwise, just add the constraint! - ConstraintStr += Constraint; - } + ConstraintStr += Simplified; } } _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits