]> granicus.if.org Git - llvm/commitdiff
GlobalISel: produce correct code for signext/zeroext ABI flags.
authorTim Northover <tnorthover@apple.com>
Wed, 21 Sep 2016 12:57:45 +0000 (12:57 +0000)
committerTim Northover <tnorthover@apple.com>
Wed, 21 Sep 2016 12:57:45 +0000 (12:57 +0000)
We still don't really have an equivalent of "AssertXExt" in DAG, so we don't
exploit the guarantees on the receiving side yet, but this should produce
conservatively correct code on iOS ABIs.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282069 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/GlobalISel/CallLowering.h
include/llvm/CodeGen/LowLevelType.h
lib/CodeGen/GlobalISel/CallLowering.cpp
lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp
lib/CodeGen/LowLevelType.cpp
lib/Target/AArch64/AArch64CallLowering.cpp
lib/Target/AArch64/AArch64CallLowering.h
lib/Target/AArch64/AArch64CallingConvention.td
test/CodeGen/AArch64/GlobalISel/call-translator.ll

index 6df0e9e32d3ba4627b11503041b00dd4e63e0c40..8307d39247fcc8b7aa2d6a43e5b757da58fdbd1f 100644 (file)
@@ -18,6 +18,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/ValueTypes.h"
 #include "llvm/IR/Function.h"
+#include "llvm/Target/TargetCallingConv.h"
 
 namespace llvm {
 // Forward declarations.
@@ -39,7 +40,21 @@ class CallLowering {
     const XXXTargetLowering *getTLI() const {
     return static_cast<const XXXTargetLowering *>(TLI);
   }
- public:
+
+  struct ArgInfo {
+    unsigned Reg;
+    Type *Ty;
+    ISD::ArgFlagsTy Flags;
+
+    ArgInfo(unsigned Reg, Type *Ty, ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{})
+        : Reg(Reg), Ty(Ty), Flags(Flags) {}
+  };
+
+  template <typename FuncInfoTy>
+  void setArgFlags(ArgInfo &Arg, unsigned OpNum, const DataLayout &DL,
+                   const FuncInfoTy &FuncInfo) const;
+
+public:
   CallLowering(const TargetLowering *TLI) : TLI(TLI) {}
   virtual ~CallLowering() {}
 
@@ -87,9 +102,8 @@ class CallLowering {
   ///
   /// \return true if the lowering succeeded, false otherwise.
   virtual bool lowerCall(MachineIRBuilder &MIRBuilder,
-                         const MachineOperand &Callee, Type * ResTy,
-                         unsigned ResReg, ArrayRef<Type *> ArgTys,
-                         ArrayRef<unsigned> ArgRegs) const {
+                         const MachineOperand &Callee, const ArgInfo &OrigRet,
+                         ArrayRef<ArgInfo> OrigArgs) const {
     return false;
   }
 
index 414406920ccbf90446d65d304075bec39d36bc95..b8885c3a95fd70d355fdf42a9592ee72b74b8d9e 100644 (file)
@@ -83,6 +83,8 @@ public:
   /// Construct a low-level type based on an LLVM type.
   explicit LLT(Type &Ty, const DataLayout &DL);
 
+  explicit LLT(MVT VT);
+
   bool isValid() const { return Kind != Invalid; }
 
   bool isScalar() const { return Kind == Scalar; }
index de63280fd716a5cf29cd3cf46fd4b5dbaf769e4c..578556cc8bb30a2ae242c43b5791a25c1d896e05 100644 (file)
 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
 #include "llvm/CodeGen/MachineOperand.h"
 #include "llvm/IR/Instructions.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Target/TargetLowering.h"
 
 using namespace llvm;
 
 bool CallLowering::lowerCall(
     MachineIRBuilder &MIRBuilder, const CallInst &CI, unsigned ResReg,
     ArrayRef<unsigned> ArgRegs, std::function<unsigned()> GetCalleeReg) const {
+  auto &DL = CI.getParent()->getParent()->getParent()->getDataLayout();
+
   // First step is to marshall all the function's parameters into the correct
   // physregs and memory locations. Gather the sequence of argument types that
   // we'll pass to the assigner function.
-  SmallVector<Type *, 8> ArgTys;
-  for (auto &Arg : CI.arg_operands())
-    ArgTys.push_back(Arg->getType());
+  SmallVector<ArgInfo, 8> OrigArgs;
+  unsigned i = 0;
+  for (auto &Arg : CI.arg_operands()) {
+    ArgInfo OrigArg{ArgRegs[i], Arg->getType(), ISD::ArgFlagsTy{}};
+    setArgFlags(OrigArg, i + 1, DL, CI);
+    OrigArgs.push_back(OrigArg);
+    ++i;
+  }
 
   MachineOperand Callee = MachineOperand::CreateImm(0);
   if (Function *F = CI.getCalledFunction())
@@ -35,5 +45,58 @@ bool CallLowering::lowerCall(
   else
     Callee = MachineOperand::CreateReg(GetCalleeReg(), false);
 
-  return lowerCall(MIRBuilder, Callee, CI.getType(), ResReg, ArgTys, ArgRegs);
+  ArgInfo OrigRet{ResReg, CI.getType(), ISD::ArgFlagsTy{}};
+  if (!OrigRet.Ty->isVoidTy())
+    setArgFlags(OrigRet, AttributeSet::ReturnIndex, DL, CI);
+
+  return lowerCall(MIRBuilder, Callee, OrigRet, OrigArgs);
 }
+
+template <typename FuncInfoTy>
+void CallLowering::setArgFlags(CallLowering::ArgInfo &Arg, unsigned OpIdx,
+                               const DataLayout &DL,
+                               const FuncInfoTy &FuncInfo) const {
+  const AttributeSet &Attrs = FuncInfo.getAttributes();
+  if (Attrs.hasAttribute(OpIdx, Attribute::ZExt))
+    Arg.Flags.setZExt();
+  if (Attrs.hasAttribute(OpIdx, Attribute::SExt))
+    Arg.Flags.setSExt();
+  if (Attrs.hasAttribute(OpIdx, Attribute::InReg))
+    Arg.Flags.setInReg();
+  if (Attrs.hasAttribute(OpIdx, Attribute::StructRet))
+    Arg.Flags.setSRet();
+  if (Attrs.hasAttribute(OpIdx, Attribute::SwiftSelf))
+    Arg.Flags.setSwiftSelf();
+  if (Attrs.hasAttribute(OpIdx, Attribute::SwiftError))
+    Arg.Flags.setSwiftError();
+  if (Attrs.hasAttribute(OpIdx, Attribute::ByVal))
+    Arg.Flags.setByVal();
+  if (Attrs.hasAttribute(OpIdx, Attribute::InAlloca))
+    Arg.Flags.setInAlloca();
+
+  if (Arg.Flags.isByVal() || Arg.Flags.isInAlloca()) {
+    Type *ElementTy = cast<PointerType>(Arg.Ty)->getElementType();
+    Arg.Flags.setByValSize(DL.getTypeAllocSize(ElementTy));
+    // For ByVal, alignment should be passed from FE.  BE will guess if
+    // this info is not there but there are cases it cannot get right.
+    unsigned FrameAlign;
+    if (FuncInfo.getParamAlignment(OpIdx))
+      FrameAlign = FuncInfo.getParamAlignment(OpIdx);
+    else
+      FrameAlign = getTLI()->getByValTypeAlignment(ElementTy, DL);
+    Arg.Flags.setByValAlign(FrameAlign);
+  }
+  if (Attrs.hasAttribute(OpIdx, Attribute::Nest))
+    Arg.Flags.setNest();
+  Arg.Flags.setOrigAlign(DL.getABITypeAlignment(Arg.Ty));
+}
+
+template void
+CallLowering::setArgFlags<Function>(CallLowering::ArgInfo &Arg, unsigned OpIdx,
+                                    const DataLayout &DL,
+                                    const Function &FuncInfo) const;
+
+template void
+CallLowering::setArgFlags<CallInst>(CallLowering::ArgInfo &Arg, unsigned OpIdx,
+                                    const DataLayout &DL,
+                                    const CallInst &FuncInfo) const;
index ede2bc233935326cf9d761def4687aef0a9c948b..d6368b3d96995edfd18da337a63e49819aa1932b 100644 (file)
@@ -109,9 +109,10 @@ MachineLegalizeHelper::libcall(MachineInstr &MI) {
     const char *Name =
         TLI.getLibcallName(Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32);
 
-    CLI.lowerCall(MIRBuilder, MachineOperand::CreateES(Name), Ty,
-                  MI.getOperand(0).getReg(), {Ty, Ty},
-                  {MI.getOperand(1).getReg(), MI.getOperand(2).getReg()});
+    CLI.lowerCall(
+        MIRBuilder, MachineOperand::CreateES(Name),
+        {MI.getOperand(0).getReg(), Ty},
+        {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}});
     MI.eraseFromParent();
     return Legalized;
   }
index fd235f2cfd1b640f61df3dde31baf52275cdb591..d74b7306e0f43d4216f3385e172cb24abc466e68 100644 (file)
@@ -40,6 +40,24 @@ LLT::LLT(Type &Ty, const DataLayout &DL) {
   }
 }
 
+LLT::LLT(MVT VT) {
+  if (VT.isVector()) {
+    SizeInBits = VT.getVectorElementType().getSizeInBits();
+    ElementsOrAddrSpace = VT.getVectorNumElements();
+    Kind = ElementsOrAddrSpace == 1 ? Scalar : Vector;
+  } else if (VT.isValid()) {
+    // Aggregates are no different from real scalars as far as GlobalISel is
+    // concerned.
+    Kind = Scalar;
+    SizeInBits = VT.getSizeInBits();
+    ElementsOrAddrSpace = 1;
+    assert(SizeInBits != 0 && "invalid zero-sized type");
+  } else {
+    Kind = Invalid;
+    SizeInBits = ElementsOrAddrSpace = 0;
+  }
+}
+
 void LLT::print(raw_ostream &OS) const {
   if (isVector())
     OS << "<" << ElementsOrAddrSpace << " x s" << SizeInBits << ">";
index 0a3b911dfb876a9dd927cfcd6250460417b1ca04..3cf4eea6bb6d6683a6b9f62eda140d19c7ace8bb 100644 (file)
@@ -35,8 +35,7 @@ AArch64CallLowering::AArch64CallLowering(const AArch64TargetLowering &TLI)
 
 bool AArch64CallLowering::handleAssignments(MachineIRBuilder &MIRBuilder,
                                             CCAssignFn *AssignFn,
-                                            ArrayRef<Type *> ArgTypes,
-                                            ArrayRef<unsigned> ArgRegs,
+                                            ArrayRef<ArgInfo> Args,
                                             AssignFnTy AssignValToReg) const {
   MachineFunction &MF = MIRBuilder.getMF();
   const Function &F = *MF.getFunction();
@@ -44,81 +43,90 @@ bool AArch64CallLowering::handleAssignments(MachineIRBuilder &MIRBuilder,
   SmallVector<CCValAssign, 16> ArgLocs;
   CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext());
 
-  unsigned NumArgs = ArgTypes.size();
-  auto CurTy = ArgTypes.begin();
-  for (unsigned i = 0; i != NumArgs; ++i, ++CurTy) {
-    MVT CurVT = MVT::getVT(*CurTy);
-    if (AssignFn(i, CurVT, CurVT, CCValAssign::Full, ISD::ArgFlagsTy(), CCInfo))
+  unsigned NumArgs = Args.size();
+  for (unsigned i = 0; i != NumArgs; ++i) {
+    MVT CurVT = MVT::getVT(Args[i].Ty);
+    if (AssignFn(i, CurVT, CurVT, CCValAssign::Full, Args[i].Flags, CCInfo))
       return false;
   }
-  assert(ArgLocs.size() == ArgTypes.size() &&
-         "We have a different number of location and args?!");
-  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
     CCValAssign &VA = ArgLocs[i];
 
     // FIXME: Support non-register argument.
     if (!VA.isRegLoc())
       return false;
 
-    switch (VA.getLocInfo()) {
-    default:
-      //  Unknown loc info!
-      return false;
-    case CCValAssign::Full:
-      break;
-    case CCValAssign::BCvt:
-      // We don't care about bitcast.
-      break;
-    case CCValAssign::AExt:
-      // Existing high bits are fine for anyext (whatever they are).
-      break;
-    case CCValAssign::SExt:
-    case CCValAssign::ZExt:
-      // Zero/Sign extend the register.
-      // FIXME: Not yet implemented
-      return false;
-    }
-
     // Everything checks out, tell the caller where we've decided this
     // parameter/return value should go.
-    AssignValToReg(MIRBuilder, ArgTypes[i], ArgRegs[i], VA.getLocReg());
+    AssignValToReg(MIRBuilder, Args[i].Ty, Args[i].Reg, VA);
   }
   return true;
 }
 
-void AArch64CallLowering::splitToValueTypes(
-    unsigned Reg, Type *Ty, SmallVectorImpl<unsigned> &SplitRegs,
-    SmallVectorImpl<Type *> &SplitTys, const DataLayout &DL,
-    MachineRegisterInfo &MRI, SplitArgTy SplitArg) const {
+void AArch64CallLowering::splitToValueTypes(const ArgInfo &OrigArg,
+                                            SmallVectorImpl<ArgInfo> &SplitArgs,
+                                            const DataLayout &DL,
+                                            MachineRegisterInfo &MRI,
+                                            SplitArgTy PerformArgSplit) const {
   const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
-  LLVMContext &Ctx = Ty->getContext();
+  LLVMContext &Ctx = OrigArg.Ty->getContext();
 
   SmallVector<EVT, 4> SplitVTs;
   SmallVector<uint64_t, 4> Offsets;
-  ComputeValueVTs(TLI, DL, Ty, SplitVTs, &Offsets, 0);
+  ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0);
 
   if (SplitVTs.size() == 1) {
     // No splitting to do, just forward the input directly.
-    SplitTys.push_back(Ty);
-    SplitRegs.push_back(Reg);
+    SplitArgs.push_back(OrigArg);
     return;
   }
 
-  unsigned FirstRegIdx = SplitRegs.size();
+  unsigned FirstRegIdx = SplitArgs.size();
   for (auto SplitVT : SplitVTs) {
+    // FIXME: set split flags if they're actually used (e.g. i128 on AAPCS).
     Type *SplitTy = SplitVT.getTypeForEVT(Ctx);
-    SplitRegs.push_back(MRI.createGenericVirtualRegister(LLT{*SplitTy, DL}));
-    SplitTys.push_back(SplitTy);
+    SplitArgs.push_back(
+        ArgInfo{MRI.createGenericVirtualRegister(LLT{*SplitTy, DL}), SplitTy,
+                OrigArg.Flags});
   }
 
   SmallVector<uint64_t, 4> BitOffsets;
   for (auto Offset : Offsets)
     BitOffsets.push_back(Offset * 8);
 
-  SplitArg(ArrayRef<unsigned>(&SplitRegs[FirstRegIdx], SplitRegs.end()),
-           BitOffsets);
+  SmallVector<unsigned, 8> SplitRegs;
+  for (auto I = &SplitArgs[FirstRegIdx]; I != SplitArgs.end(); ++I)
+    SplitRegs.push_back(I->Reg);
+
+  PerformArgSplit(SplitRegs, BitOffsets);
+}
+
+static void copyToPhysReg(MachineIRBuilder &MIRBuilder, unsigned ValReg,
+                          CCValAssign &VA, MachineRegisterInfo &MRI) {
+  LLT LocTy{VA.getLocVT()};
+  switch (VA.getLocInfo()) {
+  default: break;
+  case CCValAssign::AExt:
+    assert(!VA.getLocVT().isVector() && "unexpected vector extend");
+    // Otherwise, it's a nop.
+    break;
+  case CCValAssign::SExt: {
+    unsigned NewReg = MRI.createGenericVirtualRegister(LocTy);
+    MIRBuilder.buildSExt(NewReg, ValReg);
+    ValReg = NewReg;
+    break;
+  }
+  case CCValAssign::ZExt: {
+    unsigned NewReg = MRI.createGenericVirtualRegister(LocTy);
+    MIRBuilder.buildZExt(NewReg, ValReg);
+    ValReg = NewReg;
+    break;
+  }
+  }
+  MIRBuilder.buildCopy(VA.getLocReg(), ValReg);
 }
 
+
 bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
                                       const Value *Val, unsigned VReg) const {
   MachineFunction &MF = MIRBuilder.getMF();
@@ -135,18 +143,20 @@ bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
     MachineRegisterInfo &MRI = MF.getRegInfo();
     auto &DL = F.getParent()->getDataLayout();
 
-    SmallVector<Type *, 8> SplitTys;
-    SmallVector<unsigned, 8> SplitRegs;
-    splitToValueTypes(VReg, Val->getType(), SplitRegs, SplitTys, DL, MRI,
+    ArgInfo OrigArg{VReg, Val->getType()};
+    setArgFlags(OrigArg, AttributeSet::ReturnIndex, DL, F);
+
+    SmallVector<ArgInfo, 8> SplitArgs;
+    splitToValueTypes(OrigArg, SplitArgs, DL, MRI,
                       [&](ArrayRef<unsigned> Regs, ArrayRef<uint64_t> Offsets) {
                         MIRBuilder.buildExtract(Regs, Offsets, VReg);
                       });
 
-    return handleAssignments(MIRBuilder, AssignFn, SplitTys, SplitRegs,
+    return handleAssignments(MIRBuilder, AssignFn, SplitArgs,
                              [&](MachineIRBuilder &MIRBuilder, Type *Ty,
-                                 unsigned ValReg, unsigned PhysReg) {
-                               MIRBuilder.buildCopy(PhysReg, ValReg);
-                               MIB.addUse(PhysReg, RegState::Implicit);
+                                 unsigned ValReg, CCValAssign &VA) {
+                               copyToPhysReg(MIRBuilder, ValReg, VA, MRI);
+                               MIB.addUse(VA.getLocReg(), RegState::Implicit);
                              });
   }
   return true;
@@ -161,12 +171,12 @@ bool AArch64CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
   MachineRegisterInfo &MRI = MF.getRegInfo();
   auto &DL = F.getParent()->getDataLayout();
 
-  SmallVector<MachineInstr *, 8> Seqs;
-  SmallVector<Type *, 8> SplitTys;
-  SmallVector<unsigned, 8> SplitRegs;
+  SmallVector<ArgInfo, 8> SplitArgs;
   unsigned i = 0;
   for (auto &Arg : Args) {
-    splitToValueTypes(VRegs[i], Arg.getType(), SplitRegs, SplitTys, DL, MRI,
+    ArgInfo OrigArg{VRegs[i], Arg.getType()};
+    setArgFlags(OrigArg, i + 1, DL, F);
+    splitToValueTypes(OrigArg, SplitArgs, DL, MRI,
                       [&](ArrayRef<unsigned> Regs, ArrayRef<uint64_t> Offsets) {
                         MIRBuilder.buildSequence(VRegs[i], Regs, Offsets);
                       });
@@ -180,34 +190,36 @@ bool AArch64CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
   CCAssignFn *AssignFn =
       TLI.CCAssignFnForCall(F.getCallingConv(), /*IsVarArg=*/false);
 
-  bool Res = handleAssignments(MIRBuilder, AssignFn, SplitTys, SplitRegs,
-                               [](MachineIRBuilder &MIRBuilder, Type *Ty,
-                                  unsigned ValReg, unsigned PhysReg) {
-                                 MIRBuilder.getMBB().addLiveIn(PhysReg);
-                                 MIRBuilder.buildCopy(ValReg, PhysReg);
-                               });
+  if (!handleAssignments(MIRBuilder, AssignFn, SplitArgs,
+                         [](MachineIRBuilder &MIRBuilder, Type *Ty,
+                            unsigned ValReg, CCValAssign &VA) {
+                           // FIXME: a sign/zeroext loc actually gives
+                           // us an optimization hint. We should use it.
+                           MIRBuilder.getMBB().addLiveIn(VA.getLocReg());
+                           MIRBuilder.buildCopy(ValReg, VA.getLocReg());
+                         }))
+    return false;
 
   // Move back to the end of the basic block.
   MIRBuilder.setMBB(MBB);
 
-  return Res;
+  return true;
 }
 
 bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
-                                    const MachineOperand &Callee, Type *ResTy,
-                                    unsigned ResReg, ArrayRef<Type *> ArgTys,
-                                    ArrayRef<unsigned> ArgRegs) const {
+                                    const MachineOperand &Callee,
+                                    const ArgInfo &OrigRet,
+                                    ArrayRef<ArgInfo> OrigArgs) const {
   MachineFunction &MF = MIRBuilder.getMF();
   const Function &F = *MF.getFunction();
   MachineRegisterInfo &MRI = MF.getRegInfo();
   auto &DL = F.getParent()->getDataLayout();
 
-  SmallVector<Type *, 8> SplitTys;
-  SmallVector<unsigned, 8> SplitRegs;
-  for (unsigned i = 0; i < ArgTys.size(); ++i) {
-    splitToValueTypes(ArgRegs[i], ArgTys[i], SplitRegs, SplitTys, DL, MRI,
+  SmallVector<ArgInfo, 8> SplitArgs;
+  for (auto &OrigArg : OrigArgs) {
+    splitToValueTypes(OrigArg, SplitArgs, DL, MRI,
                       [&](ArrayRef<unsigned> Regs, ArrayRef<uint64_t> Offsets) {
-                        MIRBuilder.buildExtract(Regs, Offsets, ArgRegs[i]);
+                        MIRBuilder.buildExtract(Regs, Offsets, OrigArg.Reg);
                       });
   }
 
@@ -219,12 +231,13 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
   // And finally we can do the actual assignments. For a call we need to keep
   // track of the registers used because they'll be implicit uses of the BL.
   SmallVector<unsigned, 8> PhysRegs;
-  handleAssignments(MIRBuilder, CallAssignFn, SplitTys, SplitRegs,
-                    [&](MachineIRBuilder &MIRBuilder, Type *Ty, unsigned ValReg,
-                        unsigned PhysReg) {
-                      MIRBuilder.buildCopy(PhysReg, ValReg);
-                      PhysRegs.push_back(PhysReg);
-                    });
+  if (!handleAssignments(MIRBuilder, CallAssignFn, SplitArgs,
+                         [&](MachineIRBuilder &MIRBuilder, Type *Ty,
+                             unsigned ValReg, CCValAssign &VA) {
+                           copyToPhysReg(MIRBuilder, ValReg, VA, MRI);
+                           PhysRegs.push_back(VA.getLocReg());
+                         }))
+    return false;
 
   // Now we can build the actual call instruction.
   auto MIB = MIRBuilder.buildInstr(Callee.isReg() ? AArch64::BLR : AArch64::BL);
@@ -241,26 +254,31 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
   // symmetry with the arugments, the physical register must be an
   // implicit-define of the call instruction.
   CCAssignFn *RetAssignFn = TLI.CCAssignFnForReturn(F.getCallingConv());
-  if (ResReg) {
-    SplitTys.clear();
-    SplitRegs.clear();
+  if (OrigRet.Reg) {
+    SplitArgs.clear();
 
     SmallVector<uint64_t, 8> RegOffsets;
-    splitToValueTypes(ResReg, ResTy, SplitRegs, SplitTys, DL, MRI,
+    SmallVector<unsigned, 8> SplitRegs;
+    splitToValueTypes(OrigRet, SplitArgs, DL, MRI,
                       [&](ArrayRef<unsigned> Regs, ArrayRef<uint64_t> Offsets) {
                         std::copy(Offsets.begin(), Offsets.end(),
                                   std::back_inserter(RegOffsets));
+                        std::copy(Regs.begin(), Regs.end(),
+                                  std::back_inserter(SplitRegs));
                       });
 
-    handleAssignments(MIRBuilder, RetAssignFn, SplitTys, SplitRegs,
+    if (!handleAssignments(MIRBuilder, RetAssignFn, SplitArgs,
                       [&](MachineIRBuilder &MIRBuilder, Type *Ty,
-                          unsigned ValReg, unsigned PhysReg) {
-                        MIRBuilder.buildCopy(ValReg, PhysReg);
-                        MIB.addDef(PhysReg, RegState::Implicit);
-                      });
+                          unsigned ValReg, CCValAssign &VA) {
+                             // FIXME: a sign/zeroext loc actually gives
+                             // us an optimization hint. We should use it.
+                             MIRBuilder.buildCopy(ValReg, VA.getLocReg());
+                             MIB.addDef(VA.getLocReg(), RegState::Implicit);
+                           }))
+      return false;
 
     if (!RegOffsets.empty())
-      MIRBuilder.buildSequence(ResReg, SplitRegs, RegOffsets);
+      MIRBuilder.buildSequence(OrigRet.Reg, SplitRegs, RegOffsets);
   }
 
   return true;
index 452551d98ae0c831f766b88ae1a680b9b14a3667..baf063aa3ea2b1db57a59ac72db47c56cc1cb42c 100644 (file)
@@ -34,24 +34,24 @@ class AArch64CallLowering: public CallLowering {
                             ArrayRef<unsigned> VRegs) const override;
 
   bool lowerCall(MachineIRBuilder &MIRBuilder, const MachineOperand &Callee,
-                 Type *ResTy, unsigned ResReg, ArrayRef<Type *> ArgTys,
-                 ArrayRef<unsigned> ArgRegs) const override;
+                 const ArgInfo &OrigRet,
+                 ArrayRef<ArgInfo> OrigArgs) const override;
 
 private:
-  typedef std::function<void(MachineIRBuilder &, Type *, unsigned, unsigned)>
+  typedef std::function<void(MachineIRBuilder &, Type *, unsigned,
+                             CCValAssign &)>
       AssignFnTy;
 
   typedef std::function<void(ArrayRef<unsigned>, ArrayRef<uint64_t>)>
       SplitArgTy;
 
-  void splitToValueTypes(unsigned Reg, Type *Ty,
-                         SmallVectorImpl<unsigned> &SplitRegs,
-                         SmallVectorImpl<Type *> &SplitTys,
+  void splitToValueTypes(const ArgInfo &OrigArgInfo,
+                         SmallVectorImpl<ArgInfo> &SplitArgs,
                          const DataLayout &DL, MachineRegisterInfo &MRI,
                          SplitArgTy SplitArg) const;
 
   bool handleAssignments(MachineIRBuilder &MIRBuilder, CCAssignFn *AssignFn,
-                         ArrayRef<Type *> ArgsTypes, ArrayRef<unsigned> ArgRegs,
+                         ArrayRef<ArgInfo> Args,
                          AssignFnTy AssignValToReg) const;
 };
 } // End of namespace llvm;
index 41ad0a8a8c5a69f62e30d1be984a8a996257555c..9058617768dd0205d1635fac0dc9493d1ca1d079 100644 (file)
@@ -100,6 +100,7 @@ def RetCC_AArch64_AAPCS : CallingConv<[
   CCIfBigEndian<CCIfType<[v2i64, v2f64, v4i32, v4f32, v8i16, v8f16, v16i8],
                          CCBitConvertToType<f128>>>,
 
+  CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
   CCIfType<[i32], CCAssignToRegWithShadow<[W0, W1, W2, W3, W4, W5, W6, W7],
                                           [X0, X1, X2, X3, X4, X5, X6, X7]>>,
   CCIfType<[i64], CCAssignToRegWithShadow<[X0, X1, X2, X3, X4, X5, X6, X7],
index 8ab17d37f150eaeeab531acaa9a3e545f3698e0c..85bad60ce17066129c0023f3ed86a0cf037a9170 100644 (file)
@@ -101,3 +101,43 @@ define i64 @test_arr_call([4 x i64]* %addr) {
   %val = extractvalue [4 x i64] %res, 1
   ret i64 %val
 }
+
+
+; CHECK-LABEL: name: test_abi_exts_call
+; CHECK: [[VAL:%[0-9]+]](s8) = G_LOAD
+; CHECK: %w0 = COPY [[VAL]]
+; CHECK: BL @take_char, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %w0
+; CHECK: [[SVAL:%[0-9]+]](s32) = G_SEXT [[VAL]](s8)
+; CHECK: %w0 = COPY [[SVAL]](s32)
+; CHECK: BL @take_char, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %w0
+; CHECK: [[ZVAL:%[0-9]+]](s32) = G_ZEXT [[VAL]](s8)
+; CHECK: %w0 = COPY [[ZVAL]](s32)
+; CHECK: BL @take_char, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %w0
+declare void @take_char(i8)
+define void @test_abi_exts_call(i8* %addr) {
+  %val = load i8, i8* %addr
+  call void @take_char(i8 %val)
+  call void @take_char(i8 signext %val)
+  call void @take_char(i8 zeroext %val)
+  ret void
+}
+
+; CHECK-LABEL: name: test_abi_sext_ret
+; CHECK: [[VAL:%[0-9]+]](s8) = G_LOAD
+; CHECK: [[SVAL:%[0-9]+]](s32) = G_SEXT [[VAL]](s8)
+; CHECK: %w0 = COPY [[SVAL]](s32)
+; CHECK: RET_ReallyLR implicit %w0
+define signext i8 @test_abi_sext_ret(i8* %addr) {
+  %val = load i8, i8* %addr
+  ret i8 %val
+}
+
+; CHECK-LABEL: name: test_abi_zext_ret
+; CHECK: [[VAL:%[0-9]+]](s8) = G_LOAD
+; CHECK: [[SVAL:%[0-9]+]](s32) = G_ZEXT [[VAL]](s8)
+; CHECK: %w0 = COPY [[SVAL]](s32)
+; CHECK: RET_ReallyLR implicit %w0
+define zeroext i8 @test_abi_zext_ret(i8* %addr) {
+  %val = load i8, i8* %addr
+  ret i8 %val
+}