From 5a0e60425f4f942afb7e901b401a130da48a4d21 Mon Sep 17 00:00:00 2001 From: Hal Finkel Date: Sat, 25 May 2013 04:05:05 +0000 Subject: [PATCH] PPC: Combine duplicate (offset) lvsl Altivec intrinsics 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 | 29 +++++++++++++++++++++++++- test/CodeGen/PowerPC/unal-altivec.ll | 6 ++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 6c8af0c3689..f47376cc51b 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -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(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(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()) && diff --git a/test/CodeGen/PowerPC/unal-altivec.ll b/test/CodeGen/PowerPC/unal-altivec.ll index f89f299e142..dec93ebf769 100644 --- a/test/CodeGen/PowerPC/unal-altivec.ll +++ b/test/CodeGen/PowerPC/unal-altivec.ll @@ -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 }