summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHal Finkel <hfinkel@anl.gov>2012-12-18 17:50:58 +0000
committerHal Finkel <hfinkel@anl.gov>2012-12-18 17:50:58 +0000
commit943f76d1b304f63f35d6ab256cd0ac5ee8a14223 (patch)
treeaf1803a28727f7b1b2f11354f785042e34fb7c88
parent36a60721ceccdb41ccd01d603e7c92ff7c2bae1a (diff)
downloadbcm5719-llvm-943f76d1b304f63f35d6ab256cd0ac5ee8a14223.tar.gz
bcm5719-llvm-943f76d1b304f63f35d6ab256cd0ac5ee8a14223.zip
Check multiple register classes for inline asm tied registers
A register can be associated with several distinct register classes. For example, on PPC, the floating point registers are each associated with both F4RC (which holds f32) and F8RC (which holds f64). As a result, this code would fail when provided with a floating point register and an f64 operand because it would happen to find the register in the F4RC class first and return that. From the F4RC class, SDAG would extract f32 as the register type and then assert because of the invalid implied conversion between the f64 value and the f32 register. Instead, search all register classes. If a register class containing the the requested register has the requested type, then return that register class. Otherwise, as before, return the first register class found that contains the requested register. llvm-svn: 170436
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp19
-rw-r--r--llvm/test/CodeGen/PowerPC/in-asm-f64-reg.ll22
2 files changed, 38 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 2ec7e73bf17..1dadd1f25a9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -2829,6 +2829,9 @@ getRegForInlineAsmConstraint(const std::string &Constraint,
// Remove the braces from around the name.
StringRef RegName(Constraint.data()+1, Constraint.size()-2);
+ std::pair<unsigned, const TargetRegisterClass*> R =
+ std::make_pair(0u, static_cast<const TargetRegisterClass*>(0));
+
// Figure out which register class contains this reg.
const TargetRegisterInfo *RI = TM.getRegisterInfo();
for (TargetRegisterInfo::regclass_iterator RCI = RI->regclass_begin(),
@@ -2842,12 +2845,22 @@ getRegForInlineAsmConstraint(const std::string &Constraint,
for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end();
I != E; ++I) {
- if (RegName.equals_lower(RI->getName(*I)))
- return std::make_pair(*I, RC);
+ if (RegName.equals_lower(RI->getName(*I))) {
+ std::pair<unsigned, const TargetRegisterClass*> S =
+ std::make_pair(*I, RC);
+
+ // If this register class has the requested value type, return it,
+ // otherwise keep searching and return the first class found
+ // if no other is found which explicitly has the requested type.
+ if (RC->hasType(VT))
+ return S;
+ else if (!R.second)
+ R = S;
+ }
}
}
- return std::make_pair(0u, static_cast<const TargetRegisterClass*>(0));
+ return R;
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/test/CodeGen/PowerPC/in-asm-f64-reg.ll b/llvm/test/CodeGen/PowerPC/in-asm-f64-reg.ll
new file mode 100644
index 00000000000..e457849800e
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/in-asm-f64-reg.ll
@@ -0,0 +1,22 @@
+; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s
+
+target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64"
+target triple = "powerpc64-bgq-linux"
+
+define void @_Z15quad_copy_1024nPcS_m() nounwind {
+; CHECK: @_Z15quad_copy_1024nPcS_m
+
+entry:
+ br i1 undef, label %short_msg, label %if.end
+
+if.end: ; preds = %entry
+ %0 = tail call double* asm sideeffect "qvstfdux $2,$0,$1", "=b,{r7},{f11},0,~{memory}"(i32 64, double undef, double* undef) nounwind, !srcloc !0
+ unreachable
+
+; CHECK: qvstfdux 11,{{[0-9]+}},7
+
+short_msg: ; preds = %entry
+ ret void
+}
+
+!0 = metadata !{i32 -2147422199}
OpenPOWER on IntegriCloud