summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Stannard <oliver.stannard@arm.com>2014-02-07 11:19:53 +0000
committerOliver Stannard <oliver.stannard@arm.com>2014-02-07 11:19:53 +0000
commit1dc1034218b95150bbbae415fa9937b113b327c0 (patch)
treeef7467287fa098e98d803805fdbc7863de112dc5
parent6a284eecec15e88b5c2a277b356c810fba0803bc (diff)
downloadbcm5719-llvm-1dc1034218b95150bbbae415fa9937b113b327c0.tar.gz
bcm5719-llvm-1dc1034218b95150bbbae415fa9937b113b327c0.zip
LLVM-1163: AAPCS-VFP violation when CPRC allocated to stack
According to the AAPCS, when a CPRC is allocated to the stack, all other VFP registers should be marked as unavailable. I have also modified the rules for allocating non-CPRCs to the stack, to make it more explicit that all GPRs must be made unavailable. I cannot think of a case where the old version would produce incorrect answers, so there is no test for this. llvm-svn: 200970
-rw-r--r--llvm/include/llvm/CodeGen/CallingConvLower.h9
-rw-r--r--llvm/include/llvm/Target/TargetCallingConv.td14
-rw-r--r--llvm/lib/Target/ARM/ARMCallingConv.td9
-rw-r--r--llvm/test/CodeGen/ARM/2014-02-05-vfp-regs-after-stack.ll22
-rw-r--r--llvm/utils/TableGen/CallingConvEmitter.cpp26
5 files changed, 69 insertions, 11 deletions
diff --git a/llvm/include/llvm/CodeGen/CallingConvLower.h b/llvm/include/llvm/CodeGen/CallingConvLower.h
index f824e73433a..4bc8cecaff8 100644
--- a/llvm/include/llvm/CodeGen/CallingConvLower.h
+++ b/llvm/include/llvm/CodeGen/CallingConvLower.h
@@ -348,6 +348,15 @@ public:
return AllocateStack(Size, Align);
}
+ /// Version of AllocateStack with list of extra registers to be shadowed.
+ /// Note that, unlike AllocateReg, this shadows ALL of the shadow registers.
+ unsigned AllocateStack(unsigned Size, unsigned Align,
+ const uint16_t *ShadowRegs, unsigned NumShadowRegs) {
+ for (unsigned i = 0; i < NumShadowRegs; ++i)
+ MarkAllocated(ShadowRegs[i]);
+ return AllocateStack(Size, Align);
+ }
+
// HandleByVal - Allocate a stack slot large enough to pass an argument by
// value. The size and alignment information of the argument is encoded in its
// parameter attribute.
diff --git a/llvm/include/llvm/Target/TargetCallingConv.td b/llvm/include/llvm/Target/TargetCallingConv.td
index c1bef28652e..9d1dc3837ac 100644
--- a/llvm/include/llvm/Target/TargetCallingConv.td
+++ b/llvm/include/llvm/Target/TargetCallingConv.td
@@ -89,11 +89,15 @@ class CCAssignToStack<int size, int align> : CCAction {
int Align = align;
}
-/// CCAssignToStackWithShadow - Same as CCAssignToStack, but with a register
-/// to be shadowed.
-class CCAssignToStackWithShadow<int size, int align, Register reg> :
- CCAssignToStack<size, align> {
- Register ShadowReg = reg;
+/// CCAssignToStackWithShadow - Same as CCAssignToStack, but with a list of
+/// registers to be shadowed. Note that, unlike CCAssignToRegWithShadow, this
+/// shadows ALL of the registers in shadowList.
+class CCAssignToStackWithShadow<int size,
+ int align,
+ list<Register> shadowList> : CCAction {
+ int Size = size;
+ int Align = align;
+ list<Register> ShadowRegList = shadowList;
}
/// CCPassByVal - This action always matches: it assigns the value to a stack
diff --git a/llvm/lib/Target/ARM/ARMCallingConv.td b/llvm/lib/Target/ARM/ARMCallingConv.td
index 9bea4b2d68e..9ca2e465d85 100644
--- a/llvm/lib/Target/ARM/ARMCallingConv.td
+++ b/llvm/lib/Target/ARM/ARMCallingConv.td
@@ -114,10 +114,11 @@ def CC_ARM_AAPCS_Common : CallingConv<[
CCIfType<[i32], CCIf<"ArgFlags.getOrigAlign() != 8",
CCAssignToReg<[R0, R1, R2, R3]>>>,
- CCIfType<[i32], CCIfAlign<"8", CCAssignToStackWithShadow<4, 8, R3>>>,
- CCIfType<[i32, f32], CCAssignToStack<4, 4>>,
- CCIfType<[f64], CCAssignToStack<8, 8>>,
- CCIfType<[v2f64], CCAssignToStack<16, 8>>
+ CCIfType<[i32], CCIfAlign<"8", CCAssignToStackWithShadow<4, 8, [R0, R1, R2, R3]>>>,
+ CCIfType<[i32], CCAssignToStackWithShadow<4, 4, [R0, R1, R2, R3]>>,
+ CCIfType<[f32], CCAssignToStackWithShadow<4, 4, [Q0, Q1, Q2, Q3]>>,
+ CCIfType<[f64], CCAssignToStackWithShadow<8, 8, [Q0, Q1, Q2, Q3]>>,
+ CCIfType<[v2f64], CCAssignToStackWithShadow<16, 8, [Q0, Q1, Q2, Q3]>>
]>;
def RetCC_ARM_AAPCS_Common : CallingConv<[
diff --git a/llvm/test/CodeGen/ARM/2014-02-05-vfp-regs-after-stack.ll b/llvm/test/CodeGen/ARM/2014-02-05-vfp-regs-after-stack.ll
new file mode 100644
index 00000000000..4c36a2a6a5e
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/2014-02-05-vfp-regs-after-stack.ll
@@ -0,0 +1,22 @@
+; RUN: llc < %s -o - -filetype=asm | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv8-none--eabi"
+
+; CHECK-LABEL: fn1:
+define arm_aapcs_vfpcc float @fn1(double %a, double %b, double %c, double %d, double %e, double %f, double %g, float %h, double %i, float %j) {
+ ret float %j
+; CHECK: vldr s0, [sp, #8]
+}
+
+; CHECK-LABEL: fn2:
+define arm_aapcs_vfpcc float @fn2(double %a, double %b, double %c, double %d, double %e, double %f, float %h, <4 x float> %i, float %j) {
+ ret float %j
+; CHECK: vldr s0, [sp, #16]
+}
+
+; CHECK-LABEL: fn3:
+define arm_aapcs_vfpcc float @fn3(float %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, float %j) #0 {
+ ret float %j
+; CHECK: vldr s0, [sp, #8]
+}
diff --git a/llvm/utils/TableGen/CallingConvEmitter.cpp b/llvm/utils/TableGen/CallingConvEmitter.cpp
index e316e86cd2c..96bd3361ffc 100644
--- a/llvm/utils/TableGen/CallingConvEmitter.cpp
+++ b/llvm/utils/TableGen/CallingConvEmitter.cpp
@@ -185,12 +185,34 @@ void CallingConvEmitter::EmitAction(Record *Action,
else
O << "\n" << IndentStr << " State.getTarget().getDataLayout()"
"->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()))";
- if (Action->isSubClassOf("CCAssignToStackWithShadow"))
- O << ", " << getQualifiedName(Action->getValueAsDef("ShadowReg"));
O << ");\n" << IndentStr
<< "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
<< Counter << ", LocVT, LocInfo));\n";
O << IndentStr << "return false;\n";
+ } else if (Action->isSubClassOf("CCAssignToStackWithShadow")) {
+ int Size = Action->getValueAsInt("Size");
+ int Align = Action->getValueAsInt("Align");
+ ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
+
+ unsigned ShadowRegListNumber = ++Counter;
+
+ O << IndentStr << "static const uint16_t ShadowRegList"
+ << ShadowRegListNumber << "[] = {\n";
+ O << IndentStr << " ";
+ for (unsigned i = 0, e = ShadowRegList->getSize(); i != e; ++i) {
+ if (i != 0) O << ", ";
+ O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
+ }
+ O << "\n" << IndentStr << "};\n";
+
+ O << IndentStr << "unsigned Offset" << ++Counter
+ << " = State.AllocateStack("
+ << Size << ", " << Align << ", "
+ << "ShadowRegList" << ShadowRegListNumber << ", "
+ << ShadowRegList->getSize() << ");\n";
+ O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
+ << Counter << ", LocVT, LocInfo));\n";
+ O << IndentStr << "return false;\n";
} else if (Action->isSubClassOf("CCPromoteToType")) {
Record *DestTy = Action->getValueAsDef("DestTy");
MVT::SimpleValueType DestVT = getValueType(DestTy);
OpenPOWER on IntegriCloud