Index: lib/Target/PowerPC/CMakeLists.txt =================================================================== --- lib/Target/PowerPC/CMakeLists.txt +++ lib/Target/PowerPC/CMakeLists.txt @@ -16,6 +16,7 @@ PPCBoolRetToInt.cpp PPCAsmPrinter.cpp PPCBranchSelector.cpp + PPCCCState.cpp PPCCTRLoops.cpp PPCHazardRecognizers.cpp PPCInstrInfo.cpp Index: lib/Target/PowerPC/PPCCCState.h =================================================================== --- lib/Target/PowerPC/PPCCCState.h +++ 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 &Outs); + void + PreAnalyzeFormalArguments(const SmallVectorImpl &Ins); + +private: + + // Records whether the value has been lowered from an ppcf128. + SmallVector OriginalArgWasPPCF128; + +public: + PPCCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, + SmallVectorImpl &locs, LLVMContext &C) + : CCState(CC, isVarArg, MF, locs, C) {} + + bool WasOriginalArgPPCF128(unsigned ValNo) { return OriginalArgWasPPCF128[ValNo]; } + void clearWasPPCF128() { OriginalArgWasPPCF128.clear(); } +}; +} + +#endif Index: lib/Target/PowerPC/PPCCCState.cpp =================================================================== --- lib/Target/PowerPC/PPCCCState.cpp +++ 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 &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 &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 Index: lib/Target/PowerPC/PPCCallingConv.td =================================================================== --- lib/Target/PowerPC/PPCCallingConv.td +++ lib/Target/PowerPC/PPCCallingConv.td @@ -23,6 +23,9 @@ "(State.getMachineFunction().getSubtarget()).", F), A>; +class CCIfOrigArgWasNotPPCF128 + : CCIf<"!static_cast(&State)->WasOriginalArgPPCF128(ValNo)", + A>; //===----------------------------------------------------------------------===// // Return Value Calling Convention @@ -131,7 +134,14 @@ // The ABI requires i64 to be passed in two adjacent registers with the first // register having an odd register number. - CCIfType<[i32], CCIfSplit>>, + CCIfType<[i32], + CCIfSplit>>>>, + + CCIfType<[i32], + CCIfSplit>>>, // The 'nest' parameter, if any, is passed in R11. CCIfNest>, Index: lib/Target/PowerPC/PPCFastISel.cpp =================================================================== --- lib/Target/PowerPC/PPCFastISel.cpp +++ 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" Index: lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCISelLowering.cpp +++ 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" @@ -2847,14 +2848,17 @@ // Assign locations to all of the incoming arguments. SmallVector 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]; @@ -4741,12 +4745,14 @@ // Assign locations to all of the outgoing arguments. SmallVector 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. @@ -4779,7 +4785,8 @@ // 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 ByValArgLocs; CCState CCByValInfo(CallConv, isVarArg, DAG.getMachineFunction(), Index: test/CodeGen/PowerPC/ppc32-align-long-double-sf.ll =================================================================== --- test/CodeGen/PowerPC/ppc32-align-long-double-sf.ll +++ 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