aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG/TargetLowering.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-04-27 00:37:18 +0000
committerChris Lattner <sabre@nondot.org>2008-04-27 00:37:18 +0000
commit5a09690446a36f94f990db7d18d9b9ac8587888a (patch)
tree4ea3e1952e67a7ec106e63b63ad6996a7f3d6ab6 /lib/CodeGen/SelectionDAG/TargetLowering.cpp
parent507ffd2423cfd0f5204c69e44c50aa3c759609d8 (diff)
Implement a signficant optimization for inline asm:
When choosing between constraints with multiple options, like "ir", test to see if we can use the 'i' constraint and go with that if possible. This produces more optimal ASM in all cases (sparing a register and an instruction to load it), and fixes inline asm like this: void test () { asm volatile (" %c0 %1 " : : "imr" (42), "imr"(14)); } Previously we would dump "42" into a memory location (which is ok for the 'm' constraint) which would cause a problem because the 'c' modifier is not valid on memory operands. Isn't it great how inline asm turns 'missed optimization' into 'compile failed'?? Incidentally, this was the todo in PowerPC/2007-04-24-InlineAsm-I-Modifier.ll Please do NOT pull this into Tak. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50315 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/TargetLowering.cpp')
-rw-r--r--lib/CodeGen/SelectionDAG/TargetLowering.cpp26
1 files changed, 23 insertions, 3 deletions
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index cd43349411..dd9d96cca6 100644
--- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -1688,7 +1688,8 @@ static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) {
/// 'm' over 'r', for example.
///
static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo,
- const TargetLowering &TLI) {
+ const TargetLowering &TLI,
+ SDOperand Op, SelectionDAG *DAG) {
assert(OpInfo.Codes.size() > 1 && "Doesn't have multiple constraint options");
unsigned BestIdx = 0;
TargetLowering::ConstraintType BestType = TargetLowering::C_Unknown;
@@ -1699,6 +1700,23 @@ static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo,
TargetLowering::ConstraintType CType =
TLI.getConstraintType(OpInfo.Codes[i]);
+ // If this is an 'other' constraint, see if the operand is valid for it.
+ // For example, on X86 we might have an 'rI' constraint. If the operand
+ // is an integer in the range [0..31] we want to use I (saving a load
+ // of a register), otherwise we must use 'r'.
+ if (CType == TargetLowering::C_Other && Op.Val) {
+ assert(OpInfo.Codes[i].size() == 1 &&
+ "Unhandled multi-letter 'other' constraint");
+ std::vector<SDOperand> ResultOps;
+ TLI.LowerAsmOperandForConstraint(Op, OpInfo.Codes[i][0],
+ ResultOps, *DAG);
+ if (!ResultOps.empty()) {
+ BestType = CType;
+ BestIdx = i;
+ break;
+ }
+ }
+
// This constraint letter is more general than the previous one, use it.
int Generality = getConstraintGenerality(CType);
if (Generality > BestGenerality) {
@@ -1715,7 +1733,9 @@ static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo,
/// ComputeConstraintToUse - Determines the constraint code and constraint
/// type to use for the specific AsmOperandInfo, setting
/// OpInfo.ConstraintCode and OpInfo.ConstraintType.
-void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo) const {
+void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo,
+ SDOperand Op,
+ SelectionDAG *DAG) const {
assert(!OpInfo.Codes.empty() && "Must have at least one constraint");
// Single-letter constraints ('r') are very common.
@@ -1723,7 +1743,7 @@ void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo) const {
OpInfo.ConstraintCode = OpInfo.Codes[0];
OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode);
} else {
- ChooseConstraint(OpInfo, *this);
+ ChooseConstraint(OpInfo, *this, Op, DAG);
}
// 'X' matches anything.