diff options
-rw-r--r-- | llvm/lib/Target/PowerPC/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCCCState.cpp | 36 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCCCState.h | 42 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCCallingConv.td | 12 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCFastISel.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 13 | ||||
-rw-r--r-- | llvm/test/CodeGen/PowerPC/ppc32-align-long-double-sf.ll | 21 |
7 files changed, 122 insertions, 4 deletions
diff --git a/llvm/lib/Target/PowerPC/CMakeLists.txt b/llvm/lib/Target/PowerPC/CMakeLists.txt index 53c2ed3d51e..4842c3b7a65 100644 --- a/llvm/lib/Target/PowerPC/CMakeLists.txt +++ b/llvm/lib/Target/PowerPC/CMakeLists.txt @@ -16,6 +16,7 @@ add_llvm_target(PowerPCCodeGen PPCBoolRetToInt.cpp PPCAsmPrinter.cpp PPCBranchSelector.cpp + PPCCCState.cpp PPCCTRLoops.cpp PPCHazardRecognizers.cpp PPCInstrInfo.cpp diff --git a/llvm/lib/Target/PowerPC/PPCCCState.cpp b/llvm/lib/Target/PowerPC/PPCCCState.cpp new file mode 100644 index 00000000000..5510a95430f --- /dev/null +++ b/llvm/lib/Target/PowerPC/PPCCCState.cpp @@ -0,0 +1,36 @@ +//===---- PPCCCState.cpp - CCState with PowerPC specific extensions ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PPCCCState.h" +#include "PPCSubtarget.h" +#include "llvm/IR/Module.h" +using namespace llvm; + +// Identify lowered values that originated from ppcf128 arguments and record +// this. +void PPCCCState::PreAnalyzeCallOperands( + const SmallVectorImpl<ISD::OutputArg> &Outs) { + for (const auto &I : Outs) { + if (I.ArgVT == llvm::MVT::ppcf128) + OriginalArgWasPPCF128.push_back(true); + else + OriginalArgWasPPCF128.push_back(false); + } +} + +void PPCCCState::PreAnalyzeFormalArguments( + const SmallVectorImpl<ISD::InputArg> &Ins) { + for (const auto &I : Ins) { + if (I.ArgVT == llvm::MVT::ppcf128) { + OriginalArgWasPPCF128.push_back(true); + } else { + OriginalArgWasPPCF128.push_back(false); + } + } +}
\ No newline at end of file diff --git a/llvm/lib/Target/PowerPC/PPCCCState.h b/llvm/lib/Target/PowerPC/PPCCCState.h new file mode 100644 index 00000000000..9be9f11dbea --- /dev/null +++ b/llvm/lib/Target/PowerPC/PPCCCState.h @@ -0,0 +1,42 @@ +//===---- PPCCCState.h - CCState with PowerPC specific extensions -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef PPCCCSTATE_H +#define PPCCCSTATE_H + +#include "PPCISelLowering.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/CallingConvLower.h" + +namespace llvm { + +class PPCCCState : public CCState { +public: + + void + PreAnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs); + void + PreAnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins); + +private: + + // Records whether the value has been lowered from an ppcf128. + SmallVector<bool, 4> OriginalArgWasPPCF128; + +public: + PPCCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, + SmallVectorImpl<CCValAssign> &locs, LLVMContext &C) + : CCState(CC, isVarArg, MF, locs, C) {} + + bool WasOriginalArgPPCF128(unsigned ValNo) { return OriginalArgWasPPCF128[ValNo]; } + void clearWasPPCF128() { OriginalArgWasPPCF128.clear(); } +}; +} + +#endif diff --git a/llvm/lib/Target/PowerPC/PPCCallingConv.td b/llvm/lib/Target/PowerPC/PPCCallingConv.td index 2fd3ab67297..92c51e5fc5e 100644 --- a/llvm/lib/Target/PowerPC/PPCCallingConv.td +++ b/llvm/lib/Target/PowerPC/PPCCallingConv.td @@ -23,6 +23,9 @@ class CCIfNotSubtarget<string F, CCAction A> "(State.getMachineFunction().getSubtarget()).", F), A>; +class CCIfOrigArgWasNotPPCF128<CCAction A> + : CCIf<"!static_cast<PPCCCState *>(&State)->WasOriginalArgPPCF128(ValNo)", + A>; //===----------------------------------------------------------------------===// // Return Value Calling Convention @@ -131,7 +134,14 @@ def CC_PPC32_SVR4_Common : CallingConv<[ // The ABI requires i64 to be passed in two adjacent registers with the first // register having an odd register number. - CCIfType<[i32], CCIfSplit<CCCustom<"CC_PPC32_SVR4_Custom_AlignArgRegs">>>, + CCIfType<[i32], + CCIfSplit<CCIfSubtarget<"useSoftFloat()", + CCIfOrigArgWasNotPPCF128< + CCCustom<"CC_PPC32_SVR4_Custom_AlignArgRegs">>>>>, + + CCIfType<[i32], + CCIfSplit<CCIfNotSubtarget<"useSoftFloat()", + CCCustom<"CC_PPC32_SVR4_Custom_AlignArgRegs">>>>, // The 'nest' parameter, if any, is passed in R11. CCIfNest<CCAssignToReg<[R11]>>, diff --git a/llvm/lib/Target/PowerPC/PPCFastISel.cpp b/llvm/lib/Target/PowerPC/PPCFastISel.cpp index 7ff7e48795d..cccc75faf26 100644 --- a/llvm/lib/Target/PowerPC/PPCFastISel.cpp +++ b/llvm/lib/Target/PowerPC/PPCFastISel.cpp @@ -16,6 +16,7 @@ #include "PPC.h" #include "MCTargetDesc/PPCPredicates.h" #include "PPCCallingConv.h" +#include "PPCCCState.h" #include "PPCISelLowering.h" #include "PPCMachineFunctionInfo.h" #include "PPCSubtarget.h" diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index e5cd3e30afb..813bf27f009 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -14,6 +14,7 @@ #include "PPCISelLowering.h" #include "MCTargetDesc/PPCPredicates.h" #include "PPCCallingConv.h" +#include "PPCCCState.h" #include "PPCMachineFunctionInfo.h" #include "PPCPerfectShuffle.h" #include "PPCTargetMachine.h" @@ -2842,14 +2843,17 @@ PPCTargetLowering::LowerFormalArguments_32SVR4( // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; - CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, + PPCCCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext()); // Reserve space for the linkage area on the stack. unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize(); CCInfo.AllocateStack(LinkageSize, PtrByteSize); + if (Subtarget.useSoftFloat()) + CCInfo.PreAnalyzeFormalArguments(Ins); CCInfo.AnalyzeFormalArguments(Ins, CC_PPC32_SVR4); + CCInfo.clearWasPPCF128(); for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; @@ -4736,12 +4740,14 @@ PPCTargetLowering::LowerCall_32SVR4(SDValue Chain, SDValue Callee, // Assign locations to all of the outgoing arguments. SmallVector<CCValAssign, 16> ArgLocs; - CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, + PPCCCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext()); // Reserve space for the linkage area on the stack. CCInfo.AllocateStack(Subtarget.getFrameLowering()->getLinkageSize(), PtrByteSize); + if (Subtarget.useSoftFloat()) + CCInfo.PreAnalyzeCallOperands(Outs); if (isVarArg) { // Handle fixed and variable vector arguments differently. @@ -4774,7 +4780,8 @@ PPCTargetLowering::LowerCall_32SVR4(SDValue Chain, SDValue Callee, // All arguments are treated the same. CCInfo.AnalyzeCallOperands(Outs, CC_PPC32_SVR4); } - + CCInfo.clearWasPPCF128(); + // Assign locations to all of the outgoing aggregate by value arguments. SmallVector<CCValAssign, 16> ByValArgLocs; CCState CCByValInfo(CallConv, isVarArg, DAG.getMachineFunction(), diff --git a/llvm/test/CodeGen/PowerPC/ppc32-align-long-double-sf.ll b/llvm/test/CodeGen/PowerPC/ppc32-align-long-double-sf.ll new file mode 100644 index 00000000000..f8a6d071cfe --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/ppc32-align-long-double-sf.ll @@ -0,0 +1,21 @@ +; RUN: llc -O2 -mtriple=powerpc-unknown-linux-gnu < %s | FileCheck %s + +@x = global ppc_fp128 0xM405EDA5E353F7CEE0000000000000000, align 16 +@.str = private unnamed_addr constant [5 x i8] c"%Lf\0A\00", align 1 + + +define void @foo() #0 { +entry: + %0 = load ppc_fp128, ppc_fp128* @x, align 16 + %call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i32 0, i32 0), ppc_fp128 %0) + ret void +} +; Do not skip register r4 because of register alignment in soft float mode. Instead skipping +; put in r4 part of first argument for printf function (long double). +; CHECK: lwzu 4, x@l({{[0-9]+}}) + +declare i32 @printf(i8* nocapture readonly, ...) #0 + +attributes #0 = { "use-soft-float"="true" } + +
\ No newline at end of file |