[llvm-commits] [llvm] r57699 - in /llvm/trunk: lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp test/CodeGen/PowerPC/2008-10-17-AsmMatchingOperands.ll

Chris Lattner sabre at nondot.org
Fri Oct 17 10:52:49 PDT 2008


Author: lattner
Date: Fri Oct 17 12:52:49 2008
New Revision: 57699

URL: http://llvm.org/viewvc/llvm-project?rev=57699&view=rev
Log:
Fix PR2356 on PowerPC: if we have an input and output that are tied together
that have different sizes (e.g. i32 and i64) make sure to reserve registers for
the bigger operand.

Added:
    llvm/trunk/test/CodeGen/PowerPC/2008-10-17-AsmMatchingOperands.ll
Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp?rev=57699&r1=57698&r2=57699&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp Fri Oct 17 12:52:49 2008
@@ -4721,6 +4721,7 @@
         OpInfo.CallOperandVal = CS.getArgument(ArgNo++);
         break;
       }
+        
       // The return value of the call is this value.  As such, there is no
       // corresponding argument.
       assert(CS.getType() != Type::VoidTy && "Bad inline asm!");
@@ -4753,6 +4754,30 @@
     }
     
     OpInfo.ConstraintVT = OpVT;
+  }
+  
+  // Second pass over the constraints: compute which constraint option to use
+  // and assign registers to constraints that want a specific physreg.
+  for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) {
+    SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i];
+    
+    // If this is an output operand with a matching input operand, look up the
+    // matching input.  It might have a different type (e.g. the output might be
+    // i32 and the input i64) and we need to pick the larger width to ensure we
+    // reserve the right number of registers.  
+    if (OpInfo.hasMatchingInput()) {
+      SDISelAsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput];
+      if (OpInfo.ConstraintVT != Input.ConstraintVT) {
+        assert(OpInfo.ConstraintVT.isInteger() &&
+               Input.ConstraintVT.isInteger() &&
+               "Asm constraints must be the same or different sized integers");
+        if (OpInfo.ConstraintVT.getSizeInBits() < 
+            Input.ConstraintVT.getSizeInBits())
+          OpInfo.ConstraintVT = Input.ConstraintVT;
+        else
+          Input.ConstraintVT = OpInfo.ConstraintVT;
+      }
+    }
     
     // Compute the constraint code and ConstraintType to use.
     TLI.ComputeConstraintToUse(OpInfo, OpInfo.CallOperand, hasMemory, &DAG);
@@ -5002,24 +5027,26 @@
   // and set it as the value of the call.
   if (!RetValRegs.Regs.empty()) {
     SDValue Val = RetValRegs.getCopyFromRegs(DAG, Chain, &Flag);
-
+    MVT ResultType = TLI.getValueType(CS.getType());
+    
     // If any of the results of the inline asm is a vector, it may have the
     // wrong width/num elts.  This can happen for register classes that can
     // contain multiple different value types.  The preg or vreg allocated may
-    // not have the same VT as was expected.  Convert it to the right type with
-    // bit_convert.
-    if (const StructType *ResSTy = dyn_cast<StructType>(CS.getType())) {
-      for (unsigned i = 0, e = ResSTy->getNumElements(); i != e; ++i) {
-        if (Val.getNode()->getValueType(i).isVector())
-          Val = DAG.getNode(ISD::BIT_CONVERT,
-                            TLI.getValueType(ResSTy->getElementType(i)), Val);
-      }
-    } else {
-      if (Val.getValueType().isVector())
-        Val = DAG.getNode(ISD::BIT_CONVERT, TLI.getValueType(CS.getType()),
-                          Val);
+    // not have the same VT as was expected.  Convert it to the right type
+    // with bit_convert.
+    // FIXME: Is this sufficient for inline asms with MRVs?
+    if (ResultType != Val.getValueType() && Val.getValueType().isVector()) {
+      Val = DAG.getNode(ISD::BIT_CONVERT, ResultType, Val);
+
+    } else if (ResultType != Val.getValueType() && 
+               ResultType.isInteger() && Val.getValueType().isInteger()) {
+      // If a result value was tied to an input value, the computed result may
+      // have a wider width than the expected result.  Extract the relevant
+      // portion.
+      Val = DAG.getNode(ISD::TRUNCATE, ResultType, Val);
     }
-
+    
+    assert(ResultType == Val.getValueType() && "Asm result value mismatch!");
     setValue(CS.getInstruction(), Val);
   }
   
@@ -5273,7 +5300,8 @@
          Value != NumValues; ++Value) {
       MVT VT = ValueVTs[Value];
       const Type *ArgTy = VT.getTypeForMVT();
-      SDValue Op = SDValue(Args[i].Node.getNode(), Args[i].Node.getResNo() + Value);
+      SDValue Op = SDValue(Args[i].Node.getNode(),
+                           Args[i].Node.getResNo() + Value);
       ISD::ArgFlagsTy Flags;
       unsigned OriginalAlignment =
         getTargetData()->getABITypeAlignment(ArgTy);

Added: llvm/trunk/test/CodeGen/PowerPC/2008-10-17-AsmMatchingOperands.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/2008-10-17-AsmMatchingOperands.ll?rev=57699&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/2008-10-17-AsmMatchingOperands.ll (added)
+++ llvm/trunk/test/CodeGen/PowerPC/2008-10-17-AsmMatchingOperands.ll Fri Oct 17 12:52:49 2008
@@ -0,0 +1,11 @@
+; RUN: llvm-as < %s | llc
+; PR2356
+target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f128:64:128"
+target triple = "powerpc-apple-darwin9"
+
+define i32 @test(i64 %x, i32* %p) nounwind {
+entry:
+	%asmtmp = call i32 asm "", "=r,0"(i64 0) nounwind		; <i32> [#uses=0]
+	%y = add i32 %asmtmp, 1
+	ret i32 %y
+}





More information about the llvm-commits mailing list