OSDN Git Service

PPC: Combine duplicate (offset) lvsl Altivec intrinsics
authorHal Finkel <hfinkel@anl.gov>
Sat, 25 May 2013 04:05:05 +0000 (04:05 +0000)
committerHal Finkel <hfinkel@anl.gov>
Sat, 25 May 2013 04:05:05 +0000 (04:05 +0000)
The lvsl permutation control instruction is a function only of the alignment of
the pointer operand (relative to the 16-byte natural alignment of Altivec
vectors). As a result, multiple lvsl intrinsics where the operands differ by a
multiple of 16 can be combined.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182708 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PowerPC/PPCISelLowering.cpp
test/CodeGen/PowerPC/unal-altivec.ll

index 6c8af0c..f47376c 100644 (file)
@@ -540,6 +540,7 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
   setTargetDAGCombine(ISD::STORE);
   setTargetDAGCombine(ISD::BR_CC);
   setTargetDAGCombine(ISD::BSWAP);
+  setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN);
 
   // Use reciprocal estimates.
   if (TM.Options.UnsafeFPMath) {
@@ -6988,8 +6989,10 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N,
       // cause the last vector in the sequence to be (re)loaded. Otherwise,
       // the next vector will be fetched as you might suspect was necessary.
 
-      // FIXME: We might be able to reuse the permutation generation from
+      // We might be able to reuse the permutation generation from
       // a different base address offset from this one by an aligned amount.
+      // The INTRINSIC_WO_CHAIN DAG combine will attempt to perform this
+      // optimization later.
       SDValue PermCntl = BuildIntrinsicOp(Intrinsic::ppc_altivec_lvsl, Ptr,
                                           DAG, dl, MVT::v16i8);
 
@@ -7074,6 +7077,30 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N,
     }
     }
     break;
+  case ISD::INTRINSIC_WO_CHAIN:
+    if (cast<ConstantSDNode>(N->getOperand(0))->getZExtValue() ==
+          Intrinsic::ppc_altivec_lvsl &&
+        N->getOperand(1)->getOpcode() == ISD::ADD) {
+      SDValue Add = N->getOperand(1);
+
+      if (DAG.MaskedValueIsZero(Add->getOperand(1),
+            APInt::getAllOnesValue(4 /* 16 byte alignment */).zext(
+              Add.getValueType().getScalarType().getSizeInBits()))) {
+        SDNode *BasePtr = Add->getOperand(0).getNode();
+        for (SDNode::use_iterator UI = BasePtr->use_begin(),
+             UE = BasePtr->use_end(); UI != UE; ++UI) {
+          if (UI->getOpcode() == ISD::INTRINSIC_WO_CHAIN &&
+              cast<ConstantSDNode>(UI->getOperand(0))->getZExtValue() ==
+                Intrinsic::ppc_altivec_lvsl) {
+            // We've found another LVSL, and this address if an aligned
+            // multiple of that one. The results will be the same, so use the
+            // one we've just found instead.
+
+            return SDValue(*UI, 0);
+          }
+        }
+      }
+    }
   case ISD::BSWAP:
     // Turn BSWAP (LOAD) -> lhbrx/lwbrx.
     if (ISD::isNON_EXTLoad(N->getOperand(0).getNode()) &&
index f89f299..dec93eb 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -mcpu=g5 | FileCheck %s
+; RUN: llc < %s -mcpu=g5 | FileCheck %s -check-prefix=CHECK-PC
 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-f128:128:128-v128:128:128-n32:64"
 target triple = "powerpc64-unknown-linux-gnu"
 
@@ -38,6 +39,11 @@ vector.body:                                      ; preds = %vector.body, %vecto
 ; CHECK: vaddfp {{[0-9]+}}, [[R1]], [[CNST]]
 ; CHECK: blr
 
+; CHECK-PC: @foo
+; CHECK-PC: lvsl
+; CHECK-PC-NOT: lvsl
+; CHECK-PC: blr
+
 for.end:                                          ; preds = %vector.body
   ret void
 }