[llvm-commits] [llvm] r132105 - in /llvm/trunk: lib/CodeGen/CallingConvLower.cpp lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86ISelLowering.h test/CodeGen/X86/2011-05-18-byval-in-reg.ll

Stuart Hastings stuart at apple.com
Wed May 25 19:44:57 PDT 2011


Author: stuart
Date: Wed May 25 21:44:56 2011
New Revision: 132105

URL: http://llvm.org/viewvc/llvm-project?rev=132105&view=rev
Log:
Correctly handle a one-word struct passed byval on x86_64.
rdar://problem/6920088

Added:
    llvm/trunk/test/CodeGen/X86/2011-05-18-byval-in-reg.ll
Modified:
    llvm/trunk/lib/CodeGen/CallingConvLower.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.h

Modified: llvm/trunk/lib/CodeGen/CallingConvLower.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CallingConvLower.cpp?rev=132105&r1=132104&r2=132105&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/CallingConvLower.cpp (original)
+++ llvm/trunk/lib/CodeGen/CallingConvLower.cpp Wed May 25 21:44:56 2011
@@ -48,8 +48,13 @@
   if (MinAlign > (int)Align)
     Align = MinAlign;
   TM.getTargetLowering()->HandleByVal(const_cast<CCState*>(this), Size);
-  unsigned Offset = AllocateStack(Size, Align);
-  addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
+  if (Size) {
+    unsigned Offset = AllocateStack(Size, Align);
+    addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
+  } else {
+    addLoc(CCValAssign::getReg(ValNo, ValVT, getFirstByValReg(), LocVT,
+                               LocInfo));
+  }
 }
 
 /// MarkAllocated - Mark a register and all of its aliases as allocated.

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=132105&r1=132104&r2=132105&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Wed May 25 21:44:56 2011
@@ -2091,28 +2091,54 @@
     }
 
     if (VA.isRegLoc()) {
-      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
-      if (isVarArg && IsWin64) {
-        // Win64 ABI requires argument XMM reg to be copied to the corresponding
-        // shadow reg if callee is a varargs function.
-        unsigned ShadowReg = 0;
-        switch (VA.getLocReg()) {
-        case X86::XMM0: ShadowReg = X86::RCX; break;
-        case X86::XMM1: ShadowReg = X86::RDX; break;
-        case X86::XMM2: ShadowReg = X86::R8; break;
-        case X86::XMM3: ShadowReg = X86::R9; break;
+      if (isByVal) {
+        if (CCInfo.isFirstByValRegValid()) {
+          EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
+          unsigned reg = CCInfo.getFirstByValReg();
+          SDValue Load = DAG.getLoad(PtrVT, dl, Chain, Arg,
+                                     MachinePointerInfo(),
+                                     false, false, 0);
+          MemOpChains.push_back(Load.getValue(1));
+          RegsToPass.push_back(std::make_pair(reg, Load));
+          if (Flags.getByValSize() > 8) {
+            SDValue Const8 = DAG.getConstant(8, MVT::i32);
+            SDValue AddArg = DAG.getNode(ISD::ADD, dl, PtrVT, Arg, Const8);
+            SDValue Load2 = DAG.getLoad(PtrVT, dl, Chain, AddArg,
+                                       MachinePointerInfo(),
+                                       false, false, 0);
+            MemOpChains.push_back(Load.getValue(1));
+            RegsToPass.push_back(std::make_pair(reg+1, Load));
+          }
+          CCInfo.clearFirstByValReg();
+        }
+      } else {
+        // Usual case:
+        RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
+        if (isVarArg && IsWin64) {
+          // Win64 ABI requires argument XMM reg to be copied to the corresponding
+          // shadow reg if callee is a varargs function.
+          unsigned ShadowReg = 0;
+          switch (VA.getLocReg()) {
+          case X86::XMM0: ShadowReg = X86::RCX; break;
+          case X86::XMM1: ShadowReg = X86::RDX; break;
+          case X86::XMM2: ShadowReg = X86::R8; break;
+          case X86::XMM3: ShadowReg = X86::R9; break;
+          }
+          if (ShadowReg)
+            RegsToPass.push_back(std::make_pair(ShadowReg, Arg));
         }
-        if (ShadowReg)
-          RegsToPass.push_back(std::make_pair(ShadowReg, Arg));
       }
     } else if (!IsSibcall && (!isTailCall || isByVal)) {
+      if (isByVal) {    // In memory.
+        // ??
+      }
       assert(VA.isMemLoc());
       if (StackPtr.getNode() == 0)
         StackPtr = DAG.getCopyFromReg(Chain, dl, X86StackPtr, getPointerTy());
       MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Arg,
                                              dl, DAG, VA, Flags));
     }
-  }
+  }     // end for (all register/memloc assignments)
 
   if (!MemOpChains.empty())
     Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
@@ -2438,6 +2464,39 @@
   return Offset;
 }
 
+/// HandleByVal - Every parameter *after* a byval parameter is passed
+/// on the stack.  Remember the next parameter register to allocate,
+/// and then confiscate the rest of the parameter registers to insure
+/// this.
+void
+llvm::X86TargetLowering::HandleByVal(CCState *State, unsigned &size) const {
+  if (!Subtarget->is64Bit())
+    return;
+
+  if (size == 0 || size > 16)
+    return;
+
+  int RegsRequired = (size > 8) ? 2 : 1;
+
+  static const unsigned GPR64ArgRegs64Bit[] = {
+    X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8, X86::R9
+  };
+  unsigned NextRegToAlloc = State->getFirstUnallocated(GPR64ArgRegs64Bit, 6);
+
+  // If insufficient registers available
+  if (NextRegToAlloc + RegsRequired > 6)
+    return;
+
+  size = 0;     // Tell caller not to allocate stack.
+
+  unsigned reg = State->AllocateReg(GPR64ArgRegs64Bit, 6);
+  State->setFirstByValReg(reg);
+  
+  if (RegsRequired == 2) {
+    State->AllocateReg(GPR64ArgRegs64Bit, 6);
+  }
+}
+
 /// MatchingStackOffset - Return true if the given stack call argument is
 /// already available in the same position (relatively) of the caller's
 /// incoming argument stack.

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.h?rev=132105&r1=132104&r2=132105&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Wed May 25 21:44:56 2011
@@ -816,6 +816,8 @@
     // Utility functions to help LowerVECTOR_SHUFFLE
     SDValue LowerVECTOR_SHUFFLEv8i16(SDValue Op, SelectionDAG &DAG) const;
 
+    void HandleByVal(CCState *, unsigned &) const;
+
     virtual SDValue
       LowerFormalArguments(SDValue Chain,
                            CallingConv::ID CallConv, bool isVarArg,

Added: llvm/trunk/test/CodeGen/X86/2011-05-18-byval-in-reg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2011-05-18-byval-in-reg.ll?rev=132105&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/2011-05-18-byval-in-reg.ll (added)
+++ llvm/trunk/test/CodeGen/X86/2011-05-18-byval-in-reg.ll Wed May 25 21:44:56 2011
@@ -0,0 +1,35 @@
+; RUN: llc < %s | FileCheck %s
+; rdar://problem/6920088
+;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-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "x86_64-apple-darwin9.0"
+@"\01LC" = internal constant [2 x i8] c"a\00"		; <[2 x i8]*> [#uses=1]
+@"\01LC1" = internal constant [2 x i8] c"b\00"		; <[2 x i8]*> [#uses=1]
+@"\01LC2" = internal constant [2 x i8] c"c\00"		; <[2 x i8]*> [#uses=1]
+@"\01LC3" = internal constant [2 x i8] c"d\00"		; <[2 x i8]*> [#uses=1]
+@"\01LC4" = internal constant [2 x i8] c"e\00"		; <[2 x i8]*> [#uses=1]
+@"\01LC5" = internal constant [2 x i8] c"f\00"		; <[2 x i8]*> [#uses=1]
+@"\01LC6" = internal constant [2 x i8] c"g\00"		; <[2 x i8]*> [#uses=1]
+@"\01LC7" = internal constant [4 x i8] c"%s\0A\00"		; <[4 x i8]*> [#uses=1]
+
+define i32 @main(i32 %argc, i8** %argv) nounwind {
+entry:
+	%tmp = alloca i8*		; <i8**> [#uses=2]
+	%tmp1 = alloca i8*		; <i8**> [#uses=2]
+	%tmp2 = alloca i8*		; <i8**> [#uses=2]
+; CHECK:      leaq LC4(%rip), [[AREG:%[a-z]+]]
+; CHECK-NEXT: movq [[AREG]], [[STKOFF:[0-9]+]](%rsp)
+	store i8* getelementptr ([2 x i8]* @"\01LC4", i32 0, i32 0), i8** %tmp
+	store i8* getelementptr ([2 x i8]* @"\01LC5", i32 0, i32 0), i8** %tmp1
+	store i8* getelementptr ([2 x i8]* @"\01LC6", i32 0, i32 0), i8** %tmp2
+; The LC4 struct should be passed in %r9:
+; CHECK:      movq [[STKOFF]](%rsp), %r9
+	call void (i8**,  ...)* @generate_password(i8** null, 
+         i8* getelementptr ([2 x i8]* @"\01LC", i32 0, i32 0),
+         i8* getelementptr ([2 x i8]* @"\01LC1", i32 0, i32 0),
+         i8* getelementptr ([2 x i8]* @"\01LC2", i32 0, i32 0),
+         i8* getelementptr ([2 x i8]* @"\01LC3", i32 0, i32 0),
+         i8** byval %tmp, i8** byval %tmp1, i8** byval %tmp2)
+	ret i32 0
+}
+
+declare void @generate_password(i8** %pw, ...) nounwind





More information about the llvm-commits mailing list