[llvm] r202600 - Remove extra truncs/exts around i32 bit operations on PPC64

Hal Finkel hfinkel at anl.gov
Sat Mar 1 13:36:59 PST 2014


Author: hfinkel
Date: Sat Mar  1 15:36:57 2014
New Revision: 202600

URL: http://llvm.org/viewvc/llvm-project?rev=202600&view=rev
Log:
Remove extra truncs/exts around i32 bit operations on PPC64

This generalizes the code to eliminate extra truncs/exts around i1 bit
operations to also do the same on PPC64 for i32 bit operations. This eliminates
a fairly prevalent code wart:

int foo(int a) {
  return a == 5 ? 7 : 8;
}

On PPC64, because of the extension implied by the ABI, this would generate:

	cmplwi 0, 3, 5
	li 12, 8
	li 4, 7
	isel 3, 4, 12, 2
	rldicl 3, 3, 0, 32
	blr

where the 'rldicl 3, 3, 0, 32', the extension, is completely unnecessary. At
least for the single-BB case (which is all that the DAG combine mechanism can
handle), this unnecessary extension is no longer generated.

Modified:
    llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
    llvm/trunk/test/CodeGen/PowerPC/crbits.ll

Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=202600&r1=202599&r2=202600&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Sat Mar  1 15:36:57 2014
@@ -563,10 +563,11 @@ PPCTargetLowering::PPCTargetLowering(PPC
   setTargetDAGCombine(ISD::BSWAP);
   setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN);
 
+  setTargetDAGCombine(ISD::SIGN_EXTEND);
+  setTargetDAGCombine(ISD::ZERO_EXTEND);
+  setTargetDAGCombine(ISD::ANY_EXTEND);
+
   if (Subtarget->useCRBits()) {
-    setTargetDAGCombine(ISD::SIGN_EXTEND);
-    setTargetDAGCombine(ISD::ZERO_EXTEND);
-    setTargetDAGCombine(ISD::ANY_EXTEND);
     setTargetDAGCombine(ISD::TRUNCATE);
     setTargetDAGCombine(ISD::SETCC);
     setTargetDAGCombine(ISD::SELECT_CC);
@@ -7294,6 +7295,20 @@ SDValue PPCTargetLowering::DAGCombineTru
       SDNode *User = *UI;
       if (User != N && !Visited.count(User))
         return SDValue();
+
+      // Make sure that we're not going to promote the non-output-value
+      // operand(s) or SELECT or SELECT_CC.
+      // FIXME: Although we could sometimes handle this, and it does occur in
+      // practice that one of the condition inputs to the select is also one of
+      // the outputs, we currently can't deal with this.
+      if (User->getOpcode() == ISD::SELECT) {
+        if (User->getOperand(0) == Inputs[i])
+          return SDValue();
+      } else if (User->getOpcode() == ISD::SELECT_CC) {
+        if (User->getOperand(0) == Inputs[i] ||
+            User->getOperand(1) == Inputs[i])
+          return SDValue();
+      }
     }
   }
 
@@ -7304,6 +7319,20 @@ SDValue PPCTargetLowering::DAGCombineTru
       SDNode *User = *UI;
       if (User != N && !Visited.count(User))
         return SDValue();
+
+      // Make sure that we're not going to promote the non-output-value
+      // operand(s) or SELECT or SELECT_CC.
+      // FIXME: Although we could sometimes handle this, and it does occur in
+      // practice that one of the condition inputs to the select is also one of
+      // the outputs, we currently can't deal with this.
+      if (User->getOpcode() == ISD::SELECT) {
+        if (User->getOperand(0) == PromOps[i])
+          return SDValue();
+      } else if (User->getOpcode() == ISD::SELECT_CC) {
+        if (User->getOperand(0) == PromOps[i] ||
+            User->getOperand(1) == PromOps[i])
+          return SDValue();
+      }
     }
   }
 
@@ -7391,8 +7420,6 @@ SDValue PPCTargetLowering::DAGCombineExt
   SelectionDAG &DAG = DCI.DAG;
   SDLoc dl(N);
 
-  assert(PPCSubTarget.useCRBits() &&
-         "Expecting to be tracking CR bits");
   // If we're tracking CR bits, we need to be careful that we don't have:
   //   zext(binary-ops(trunc(x), trunc(y)))
   // or
@@ -7402,11 +7429,19 @@ SDValue PPCTargetLowering::DAGCombineExt
   // bits are set as required by the final extension, we still may need to do
   // some masking to get the proper behavior.
 
+  // This same functionality is important on PPC64 when dealing with
+  // 32-to-64-bit extensions; these occur often when 32-bit values are used as
+  // the return values of functions. Because it is so similar, it is handled
+  // here as well.
+
   if (N->getValueType(0) != MVT::i32 &&
       N->getValueType(0) != MVT::i64)
     return SDValue();
 
-  if (N->getOperand(0).getValueType() != MVT::i1)
+  if (!((N->getOperand(0).getValueType() == MVT::i1 &&
+        PPCSubTarget.useCRBits()) ||
+       (N->getOperand(0).getValueType() == MVT::i32 &&
+        PPCSubTarget.isPPC64())))
     return SDValue();
 
   if (N->getOperand(0).getOpcode() != ISD::AND &&
@@ -7468,6 +7503,20 @@ SDValue PPCTargetLowering::DAGCombineExt
       SDNode *User = *UI;
       if (User != N && !Visited.count(User))
         return SDValue();
+
+      // Make sure that we're not going to promote the non-output-value
+      // operand(s) or SELECT or SELECT_CC.
+      // FIXME: Although we could sometimes handle this, and it does occur in
+      // practice that one of the condition inputs to the select is also one of
+      // the outputs, we currently can't deal with this.
+      if (User->getOpcode() == ISD::SELECT) {
+        if (User->getOperand(0) == Inputs[i])
+          return SDValue();
+      } else if (User->getOpcode() == ISD::SELECT_CC) {
+        if (User->getOperand(0) == Inputs[i] ||
+            User->getOperand(1) == Inputs[i])
+          return SDValue();
+      }
     }
   }
 
@@ -7478,9 +7527,24 @@ SDValue PPCTargetLowering::DAGCombineExt
       SDNode *User = *UI;
       if (User != N && !Visited.count(User))
         return SDValue();
+
+      // Make sure that we're not going to promote the non-output-value
+      // operand(s) or SELECT or SELECT_CC.
+      // FIXME: Although we could sometimes handle this, and it does occur in
+      // practice that one of the condition inputs to the select is also one of
+      // the outputs, we currently can't deal with this.
+      if (User->getOpcode() == ISD::SELECT) {
+        if (User->getOperand(0) == PromOps[i])
+          return SDValue();
+      } else if (User->getOpcode() == ISD::SELECT_CC) {
+        if (User->getOperand(0) == PromOps[i] ||
+            User->getOperand(1) == PromOps[i])
+          return SDValue();
+      }
     }
   }
 
+  unsigned PromBits = N->getOperand(0).getValueSizeInBits();
   bool ReallyNeedsExt = false;
   if (N->getOpcode() != ISD::ANY_EXTEND) {
     // If all of the inputs are not already sign/zero extended, then
@@ -7491,12 +7555,15 @@ SDValue PPCTargetLowering::DAGCombineExt
 
       unsigned OpBits =
         Inputs[i].getOperand(0).getValueSizeInBits();
+      assert(PromBits < OpBits && "Truncation not to a smaller bit count?");
+
       if ((N->getOpcode() == ISD::ZERO_EXTEND &&
            !DAG.MaskedValueIsZero(Inputs[i].getOperand(0),
-                                 APInt::getHighBitsSet(OpBits,
-                                                       OpBits-1))) ||
+                                  APInt::getHighBitsSet(OpBits,
+                                                        OpBits-PromBits))) ||
           (N->getOpcode() == ISD::SIGN_EXTEND &&
-           DAG.ComputeNumSignBits(Inputs[i].getOperand(0)) != OpBits)) {
+           DAG.ComputeNumSignBits(Inputs[i].getOperand(0)) <
+             (OpBits-(PromBits-1)))) {
         ReallyNeedsExt = true;
         break;
       }
@@ -7580,16 +7647,19 @@ SDValue PPCTargetLowering::DAGCombineExt
   if (!ReallyNeedsExt)
     return N->getOperand(0);
 
-  // To zero extend, just mask off everything except for the first bit.
+  // To zero extend, just mask off everything except for the first bit (in the
+  // i1 case).
   if (N->getOpcode() == ISD::ZERO_EXTEND)
     return DAG.getNode(ISD::AND, dl, N->getValueType(0), N->getOperand(0),
-                       DAG.getConstant(1, N->getValueType(0)));
+                       DAG.getConstant(APInt::getLowBitsSet(
+                                         N->getValueSizeInBits(0), PromBits),
+                                       N->getValueType(0)));
 
   assert(N->getOpcode() == ISD::SIGN_EXTEND &&
          "Invalid extension type");
   EVT ShiftAmountTy = getShiftAmountTy(N->getValueType(0));
   SDValue ShiftCst =
-    DAG.getConstant(N->getValueSizeInBits(0)-1, ShiftAmountTy);
+    DAG.getConstant(N->getValueSizeInBits(0)-PromBits, ShiftAmountTy);
   return DAG.getNode(ISD::SRA, dl, N->getValueType(0), 
                      DAG.getNode(ISD::SHL, dl, N->getValueType(0),
                                  N->getOperand(0), ShiftCst), ShiftCst);

Modified: llvm/trunk/test/CodeGen/PowerPC/crbits.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/crbits.ll?rev=202600&r1=202599&r2=202600&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/crbits.ll (original)
+++ llvm/trunk/test/CodeGen/PowerPC/crbits.ll Sat Mar  1 15:36:57 2014
@@ -124,11 +124,39 @@ entry:
 
 ; CHECK-LABEL: @test7
 ; CHECK: andi. {{[0-9]+}}, 3, 1
-; CHECK: isel [[REG1:[0-9]+]], 4, 5, 1
-; CHECK: extsw 3, [[REG1]]
+; CHECK: isel 3, 4, 5, 1
 ; CHECK: blr
 }
 
+define signext i32 @exttest7(i32 signext %a) #0 {
+entry:
+  %cmp = icmp eq i32 %a, 5
+  %cond = select i1 %cmp, i32 7, i32 8
+  ret i32 %cond
+
+; CHECK-LABEL: @exttest7
+; CHECK-DAG: cmplwi {{[0-9]+}}, 3, 5
+; CHECK-DAG: li [[REG1:[0-9]+]], 8
+; CHECK-DAG: li [[REG2:[0-9]+]], 7
+; CHECK: isel 3, [[REG2]], [[REG1]],
+; CHECK-NOT: rldicl
+; CHECK: blr
+}
+
+define zeroext i32 @exttest8() #0 {
+entry:
+  %v0 = load i64* undef, align 8
+  %sub = sub i64 80, %v0
+  %div = lshr i64 %sub, 1
+  %conv13 = trunc i64 %div to i32
+  %cmp14 = icmp ugt i32 %conv13, 80
+  %.conv13 = select i1 %cmp14, i32 0, i32 %conv13
+  ret i32 %.conv13
+; CHECK-LABEL: @exttest8
+; This is a don't-crash test: %conv13 is both one of the possible select output
+; values and also an input to the conditional feeding it.
+}
+
 ; Function Attrs: nounwind readnone
 define float @test8(i1 zeroext %v2, float %v1, float %v3) #0 {
 entry:





More information about the llvm-commits mailing list