Proper lower 'small' results
authorAnton Korobeynikov <asl@math.spbu.ru>
Thu, 16 Jul 2009 13:58:24 +0000 (13:58 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Thu, 16 Jul 2009 13:58:24 +0000 (13:58 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75962 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/SystemZ/SystemZISelLowering.cpp
lib/Target/SystemZ/SystemZInstrInfo.td
test/CodeGen/SystemZ/2009-05-29-InvalidRetResult.ll [new file with mode: 0644]

index 415ab724dce84685413503f26a93032e303ab6cb..87ea5c3ddaa501bf4dcf7ccaa43755ae025cb545 100644 (file)
@@ -361,10 +361,27 @@ SystemZTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
 
   // Copy all of the result registers out of their specified physreg.
   for (unsigned i = 0; i != RVLocs.size(); ++i) {
-    Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
-                               RVLocs[i].getValVT(), InFlag).getValue(1);
+    CCValAssign &VA = RVLocs[i];
+
+    Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(),
+                               VA.getLocVT(), InFlag).getValue(1);
+    SDValue RetValue = Chain.getValue(0);
     InFlag = Chain.getValue(2);
-    ResultVals.push_back(Chain.getValue(0));
+
+    // If this is an 8/16/32-bit value, it is really passed promoted to 64
+    // bits. Insert an assert[sz]ext to capture this, then truncate to the
+    // right size.
+    if (VA.getLocInfo() == CCValAssign::SExt)
+      RetValue = DAG.getNode(ISD::AssertSext, dl, VA.getLocVT(), RetValue,
+                             DAG.getValueType(VA.getValVT()));
+    else if (VA.getLocInfo() == CCValAssign::ZExt)
+      RetValue = DAG.getNode(ISD::AssertZext, dl, VA.getLocVT(), RetValue,
+                             DAG.getValueType(VA.getValVT()));
+
+    if (VA.getLocInfo() != CCValAssign::Full)
+      RetValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), RetValue);
+
+    ResultVals.push_back(RetValue);
   }
 
   ResultVals.push_back(Chain);
index 34152fe32b3d8f8d3d547846079d84e835f4347b..d1d9d2d670c747f119f1865fe3c81174af99c527 100644 (file)
@@ -304,7 +304,7 @@ let isBranch = 1, isTerminator = 1 in {
 let isCall = 1 in
   // All calls clobber the non-callee saved registers (except R14 which we
   // handle separately). Uses for argument registers are added manually.
-  let Defs = [R0D, R1D, R3D, R4D, R5D] in {
+  let Defs = [R0D, R1D, R2D, R3D, R4D, R5D] in {
     def CALLi     : Pseudo<(outs), (ins i64imm:$dst, variable_ops),
                            "brasl\t%r14, $dst", [(SystemZcall imm:$dst)]>;
     def CALLr     : Pseudo<(outs), (ins ADDR64:$dst, variable_ops),
diff --git a/test/CodeGen/SystemZ/2009-05-29-InvalidRetResult.ll b/test/CodeGen/SystemZ/2009-05-29-InvalidRetResult.ll
new file mode 100644 (file)
index 0000000..6bae51d
--- /dev/null
@@ -0,0 +1,12 @@
+; RUN: llvm-as < %s | llc
+
+target datalayout = "E-p:64:64:64-i1:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128"
+target triple = "s390x-unknown-linux-gnu"
+
+define i32 @main() nounwind {
+entry:
+       %call = call i32 (...)* @random() nounwind              ; <i32> [#uses=0]
+       unreachable
+}
+
+declare i32 @random(...)