[llvm-commits] [llvm] r46414 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/fp-in-intregs.ll

Chris Lattner sabre at nondot.org
Sun Jan 27 09:42:28 PST 2008


Author: lattner
Date: Sun Jan 27 11:42:27 2008
New Revision: 46414

URL: http://llvm.org/viewvc/llvm-project?rev=46414&view=rev
Log:
Implement some dag combines that allow doing fneg/fabs/fcopysign in integer
registers if used by a bitconvert or using a bitconvert.  This allows us to
avoid constant pool loads and use cheaper integer instructions when the
values come from or end up in integer regs anyway.  For example, we now 
compile CodeGen/X86/fp-in-intregs.ll to:

_test1:
	movl	$2147483648, %eax
	xorl	4(%esp), %eax
	ret
_test2:
	movl	$1065353216, %eax
	orl	4(%esp), %eax
	andl	$3212836864, %eax
	ret

Instead of:
_test1:
	movss	4(%esp), %xmm0
	xorps	LCPI2_0, %xmm0
	movd	%xmm0, %eax
	ret
_test2:
	movss	4(%esp), %xmm0
	andps	LCPI3_0, %xmm0
	movss	LCPI3_1, %xmm1
	andps	LCPI3_2, %xmm1
	orps	%xmm0, %xmm1
	movd	%xmm1, %eax
	ret

bitconverts can happen due to various calling conventions that require
fp values to passed in integer regs in some cases, e.g. when returning
a complex.


Added:
    llvm/trunk/test/CodeGen/X86/fp-in-intregs.ll
Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

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

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Sun Jan 27 11:42:27 2008
@@ -1190,7 +1190,7 @@
     return DAG.getNode(ISD::SUB, VT, DAG.getConstant(0, VT), N0);
   // If we know the sign bits of both operands are zero, strength reduce to a
   // udiv instead.  Handles (X&15) /s 4 -> X&15 >> 2
-  uint64_t SignBit = 1ULL << (MVT::getSizeInBits(VT)-1);
+  uint64_t SignBit = MVT::getIntVTSignBit(VT);
   if (DAG.MaskedValueIsZero(N1, SignBit) &&
       DAG.MaskedValueIsZero(N0, SignBit))
     return DAG.getNode(ISD::UDIV, N1.getValueType(), N0, N1);
@@ -1306,7 +1306,7 @@
     return DAG.getNode(ISD::SREM, VT, N0, N1);
   // If we know the sign bits of both operands are zero, strength reduce to a
   // urem instead.  Handles (X & 0x0FFFFFFF) %s 16 -> X&15
-  uint64_t SignBit = 1ULL << (MVT::getSizeInBits(VT)-1);
+  uint64_t SignBit = MVT::getIntVTSignBit(VT);
   if (DAG.MaskedValueIsZero(N1, SignBit) &&
       DAG.MaskedValueIsZero(N0, SignBit))
     return DAG.getNode(ISD::UREM, VT, N0, N1);
@@ -3276,6 +3276,57 @@
     }
   }
   
+  // Fold bitconvert(fneg(x)) -> xor(bitconvert(x), signbit)
+  // Fold bitconvert(fabs(x)) -> and(bitconvert(x), ~signbit)
+  // This often reduces constant pool loads.
+  if ((N0.getOpcode() == ISD::FNEG || N0.getOpcode() == ISD::FABS) &&
+      N0.Val->hasOneUse() && MVT::isInteger(VT) && !MVT::isVector(VT)) {
+    SDOperand NewConv = DAG.getNode(ISD::BIT_CONVERT, VT, N0.getOperand(0));
+    AddToWorkList(NewConv.Val);
+    
+    uint64_t SignBit = MVT::getIntVTSignBit(VT);
+    if (N0.getOpcode() == ISD::FNEG)
+      return DAG.getNode(ISD::XOR, VT, NewConv, DAG.getConstant(SignBit, VT));
+    assert(N0.getOpcode() == ISD::FABS);
+    return DAG.getNode(ISD::AND, VT, NewConv, DAG.getConstant(~SignBit, VT));
+  }
+  
+  // Fold bitconvert(fcopysign(cst, x)) -> bitconvert(x)&sign | cst&~sign'
+  // Note that we don't handle copysign(x,cst) because this can always be folded
+  // to an fneg or fabs.
+  if (N0.getOpcode() == ISD::FCOPYSIGN && N0.Val->hasOneUse() &&
+      isa<ConstantFPSDNode>(N0.getOperand(0))) {
+    unsigned OrigXWidth = MVT::getSizeInBits(N0.getOperand(1).getValueType());
+    SDOperand X = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(OrigXWidth),
+                              N0.getOperand(1));
+    AddToWorkList(X.Val);
+
+    // If X has a different width than the result/lhs, sext it or truncate it.
+    unsigned VTWidth = MVT::getSizeInBits(VT);
+    if (OrigXWidth < VTWidth) {
+      X = DAG.getNode(ISD::SIGN_EXTEND, VT, X);
+      AddToWorkList(X.Val);
+    } else if (OrigXWidth > VTWidth) {
+      // To get the sign bit in the right place, we have to shift it right
+      // before truncating.
+      X = DAG.getNode(ISD::SRL, X.getValueType(), X, 
+                      DAG.getConstant(OrigXWidth-VTWidth, X.getValueType()));
+      AddToWorkList(X.Val);
+      X = DAG.getNode(ISD::TRUNCATE, VT, X);
+      AddToWorkList(X.Val);
+    }
+    
+    uint64_t SignBit = MVT::getIntVTSignBit(VT);
+    X = DAG.getNode(ISD::AND, VT, X, DAG.getConstant(SignBit, VT));
+    AddToWorkList(X.Val);
+
+    SDOperand Cst = DAG.getNode(ISD::BIT_CONVERT, VT, N0.getOperand(0));
+    Cst = DAG.getNode(ISD::AND, VT, Cst, DAG.getConstant(~SignBit, VT));
+    AddToWorkList(Cst.Val);
+
+    return DAG.getNode(ISD::OR, VT, X, Cst);
+  }
+  
   return SDOperand();
 }
 
@@ -3732,6 +3783,19 @@
   if (isNegatibleForFree(N0))
     return GetNegatedExpression(N0, DAG);
 
+  // Transform fneg(bitconvert(x)) -> bitconvert(x^sign) to avoid loading
+  // constant pool values.
+  if (N0.getOpcode() == ISD::BIT_CONVERT && N0.Val->hasOneUse()) {
+    SDOperand Int = N0.getOperand(0);
+    MVT::ValueType IntVT = Int.getValueType();
+    if (MVT::isInteger(IntVT) && !MVT::isVector(IntVT)) {
+      Int = DAG.getNode(ISD::XOR, IntVT, Int, 
+                        DAG.getConstant(MVT::getIntVTSignBit(IntVT), IntVT));
+      AddToWorkList(Int.Val);
+      return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Int);
+    }
+  }
+  
   return SDOperand();
 }
 
@@ -3751,6 +3815,19 @@
   if (N0.getOpcode() == ISD::FNEG || N0.getOpcode() == ISD::FCOPYSIGN)
     return DAG.getNode(ISD::FABS, VT, N0.getOperand(0));
   
+  // Transform fabs(bitconvert(x)) -> bitconvert(x&~sign) to avoid loading
+  // constant pool values.
+  if (N0.getOpcode() == ISD::BIT_CONVERT && N0.Val->hasOneUse()) {
+    SDOperand Int = N0.getOperand(0);
+    MVT::ValueType IntVT = Int.getValueType();
+    if (MVT::isInteger(IntVT) && !MVT::isVector(IntVT)) {
+      Int = DAG.getNode(ISD::AND, IntVT, Int, 
+                        DAG.getConstant(~MVT::getIntVTSignBit(IntVT), IntVT));
+      AddToWorkList(Int.Val);
+      return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Int);
+    }
+  }
+  
   return SDOperand();
 }
 

Added: llvm/trunk/test/CodeGen/X86/fp-in-intregs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fp-in-intregs.ll?rev=46414&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/X86/fp-in-intregs.ll (added)
+++ llvm/trunk/test/CodeGen/X86/fp-in-intregs.ll Sun Jan 27 11:42:27 2008
@@ -0,0 +1,21 @@
+; RUN: llvm-as < %s | llc -march=x86 -mcpu=yonah | not egrep {\(\(xor\|and\)ps\|movd\)}
+
+; These operations should be done in integer registers, eliminating constant
+; pool loads, movd's etc.
+
+define i32 @test1(float %x) nounwind  {
+entry:
+	%tmp2 = sub float -0.000000e+00, %x		; <float> [#uses=1]
+	%tmp210 = bitcast float %tmp2 to i32		; <i32> [#uses=1]
+	ret i32 %tmp210
+}
+
+define i32 @test2(float %x) nounwind  {
+entry:
+	%tmp2 = tail call float @copysignf( float 1.000000e+00, float %x ) nounwind readnone 		; <float> [#uses=1]
+	%tmp210 = bitcast float %tmp2 to i32		; <i32> [#uses=1]
+	ret i32 %tmp210
+}
+
+declare float @copysignf(float, float) nounwind readnone 
+





More information about the llvm-commits mailing list