From 4e2b66100518432e1e4fa8c603601fd946c1f945 Mon Sep 17 00:00:00 2001 From: David Xu Date: Tue, 2 Sep 2014 09:33:56 +0000 Subject: [PATCH] Merge Extend and Shift into a UBFX git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216899 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AArch64/AArch64ISelDAGToDAG.cpp | 28 ++++++++++++---------- test/CodeGen/AArch64/andandshift.ll | 28 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 test/CodeGen/AArch64/andandshift.ll diff --git a/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp index 5a624e381ca..c6bdf566c13 100644 --- a/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -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 diff --git a/test/CodeGen/AArch64/andandshift.ll b/test/CodeGen/AArch64/andandshift.ll new file mode 100644 index 00000000000..e2c7a098908 --- /dev/null +++ b/test/CodeGen/AArch64/andandshift.ll @@ -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 +} + + -- 2.34.1