Merge Extend and Shift into a UBFX

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216899 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Xu 2014-09-02 09:33:56 +00:00
parent 3da41a28a1
commit 4e2b661005
2 changed files with 43 additions and 13 deletions

View File

@ -1381,20 +1381,21 @@ static bool isBitfieldExtractOpFromAnd(SelectionDAG *CurDAG, SDNode *N,
return true;
}
static bool isOneBitExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0,
unsigned &LSB, unsigned &MSB) {
// We are looking for the following pattern which basically extracts a single
// bit from the source value and places it in the LSB of the destination
// value, all other bits of the destination value or set to zero:
static bool isSeveralBitsExtractOpFromShr(SDNode *N, unsigned &Opc,
SDValue &Opd0, unsigned &LSB,
unsigned &MSB) {
// We are looking for the following pattern which basically extracts several
// continuous bits from the source value and places it from the LSB of the
// destination value, all other bits of the destination value or set to zero:
//
// Value2 = AND Value, MaskImm
// SRL Value2, ShiftImm
//
// with MaskImm >> ShiftImm == 1.
// with MaskImm >> ShiftImm to search for the bit width.
//
// This gets selected into a single UBFM:
//
// UBFM Value, ShiftImm, ShiftImm
// UBFM Value, ShiftImm, BitWide + Srl_imm -1
//
if (N->getOpcode() != ISD::SRL)
@ -1410,15 +1411,16 @@ static bool isOneBitExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0,
if (!isIntImmediate(N->getOperand(1), Srl_imm))
return false;
// Check whether we really have a one bit extract here.
if (And_mask >> Srl_imm == 0x1) {
// Check whether we really have several bits extract here.
unsigned BitWide = 64 - CountLeadingOnes_64(~(And_mask >> Srl_imm));
if (BitWide && isMask_64(And_mask >> Srl_imm)) {
if (N->getValueType(0) == MVT::i32)
Opc = AArch64::UBFMWri;
else
Opc = AArch64::UBFMXri;
LSB = MSB = Srl_imm;
LSB = Srl_imm;
MSB = BitWide + Srl_imm - 1;
return true;
}
@ -1439,8 +1441,8 @@ static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0,
assert((VT == MVT::i32 || VT == MVT::i64) &&
"Type checking must have been done before calling this function");
// Check for AND + SRL doing a one bit extract.
if (isOneBitExtractOpFromShr(N, Opc, Opd0, LSB, MSB))
// Check for AND + SRL doing several bits extract.
if (isSeveralBitsExtractOpFromShr(N, Opc, Opd0, LSB, MSB))
return true;
// we're looking for a shift of a shift

View File

@ -0,0 +1,28 @@
; RUN: llc -O3 < %s | FileCheck %s
target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
target triple = "arm64--linux-gnu"
; Function Attrs: nounwind readnone
define i32 @test1(i8 %a) {
; CHECK-LABLE: @test1
; CHECK: ubfx {{w[0-9]+}}, w0, #3, #5
entry:
%conv = zext i8 %a to i32
%shr1 = lshr i32 %conv, 3
ret i32 %shr1
}
; Function Attrs: nounwind readnone
define i32 @test2(i8 %a) {
; CHECK-LABLE: @test2
; CHECK: and {{w[0-9]+}}, w0, #0xff
; CHECK: ubfx {{w[0-9]+}}, w0, #3, #5
entry:
%conv = zext i8 %a to i32
%cmp = icmp ugt i8 %a, 47
%shr5 = lshr i32 %conv, 3
%retval.0 = select i1 %cmp, i32 %shr5, i32 %conv
ret i32 %retval.0
}