forked from OSchip/llvm-project
[AArch64] Select SBFIZ or UBFIZ instead of left + right shifts
And rename LSB to Immr / MSB to Imms to match the ARM ARM terminology. llvm-svn: 241803
This commit is contained in:
parent
8143bc25ee
commit
f40f99e3a4
|
@ -1495,7 +1495,7 @@ static bool isSeveralBitsExtractOpFromShr(SDNode *N, unsigned &Opc,
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0,
|
static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0,
|
||||||
unsigned &LSB, unsigned &MSB,
|
unsigned &Immr, unsigned &Imms,
|
||||||
bool BiggerPattern) {
|
bool BiggerPattern) {
|
||||||
assert((N->getOpcode() == ISD::SRA || N->getOpcode() == ISD::SRL) &&
|
assert((N->getOpcode() == ISD::SRA || N->getOpcode() == ISD::SRL) &&
|
||||||
"N must be a SHR/SRA operation to call this function");
|
"N must be a SHR/SRA operation to call this function");
|
||||||
|
@ -1509,7 +1509,7 @@ static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0,
|
||||||
"Type checking must have been done before calling this function");
|
"Type checking must have been done before calling this function");
|
||||||
|
|
||||||
// Check for AND + SRL doing several bits extract.
|
// Check for AND + SRL doing several bits extract.
|
||||||
if (isSeveralBitsExtractOpFromShr(N, Opc, Opd0, LSB, MSB))
|
if (isSeveralBitsExtractOpFromShr(N, Opc, Opd0, Immr, Imms))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// we're looking for a shift of a shift
|
// we're looking for a shift of a shift
|
||||||
|
@ -1549,13 +1549,9 @@ static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0,
|
||||||
|
|
||||||
assert(Srl_imm > 0 && Srl_imm < VT.getSizeInBits() &&
|
assert(Srl_imm > 0 && Srl_imm < VT.getSizeInBits() &&
|
||||||
"bad amount in shift node!");
|
"bad amount in shift node!");
|
||||||
// Note: The width operand is encoded as width-1.
|
int immr = Srl_imm - Shl_imm;
|
||||||
unsigned Width = VT.getSizeInBits() - Trunc_bits - Srl_imm - 1;
|
Immr = immr < 0 ? immr + VT.getSizeInBits() : immr;
|
||||||
int sLSB = Srl_imm - Shl_imm;
|
Imms = VT.getSizeInBits() - Shl_imm - Trunc_bits - 1;
|
||||||
if (sLSB < 0)
|
|
||||||
return false;
|
|
||||||
LSB = sLSB;
|
|
||||||
MSB = LSB + Width;
|
|
||||||
// SRA requires a signed extraction
|
// SRA requires a signed extraction
|
||||||
if (VT == MVT::i32)
|
if (VT == MVT::i32)
|
||||||
Opc = N->getOpcode() == ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
|
Opc = N->getOpcode() == ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
|
||||||
|
@ -1565,7 +1561,7 @@ static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0,
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc,
|
static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc,
|
||||||
SDValue &Opd0, unsigned &LSB, unsigned &MSB,
|
SDValue &Opd0, unsigned &Immr, unsigned &Imms,
|
||||||
unsigned NumberOfIgnoredLowBits = 0,
|
unsigned NumberOfIgnoredLowBits = 0,
|
||||||
bool BiggerPattern = false) {
|
bool BiggerPattern = false) {
|
||||||
if (N->getValueType(0) != MVT::i32 && N->getValueType(0) != MVT::i64)
|
if (N->getValueType(0) != MVT::i32 && N->getValueType(0) != MVT::i64)
|
||||||
|
@ -1577,11 +1573,11 @@ static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc,
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case ISD::AND:
|
case ISD::AND:
|
||||||
return isBitfieldExtractOpFromAnd(CurDAG, N, Opc, Opd0, LSB, MSB,
|
return isBitfieldExtractOpFromAnd(CurDAG, N, Opc, Opd0, Immr, Imms,
|
||||||
NumberOfIgnoredLowBits, BiggerPattern);
|
NumberOfIgnoredLowBits, BiggerPattern);
|
||||||
case ISD::SRL:
|
case ISD::SRL:
|
||||||
case ISD::SRA:
|
case ISD::SRA:
|
||||||
return isBitfieldExtractOpFromShr(N, Opc, Opd0, LSB, MSB, BiggerPattern);
|
return isBitfieldExtractOpFromShr(N, Opc, Opd0, Immr, Imms, BiggerPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned NOpc = N->getMachineOpcode();
|
unsigned NOpc = N->getMachineOpcode();
|
||||||
|
@ -1594,8 +1590,8 @@ static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc,
|
||||||
case AArch64::UBFMXri:
|
case AArch64::UBFMXri:
|
||||||
Opc = NOpc;
|
Opc = NOpc;
|
||||||
Opd0 = N->getOperand(0);
|
Opd0 = N->getOperand(0);
|
||||||
LSB = cast<ConstantSDNode>(N->getOperand(1).getNode())->getZExtValue();
|
Immr = cast<ConstantSDNode>(N->getOperand(1).getNode())->getZExtValue();
|
||||||
MSB = cast<ConstantSDNode>(N->getOperand(2).getNode())->getZExtValue();
|
Imms = cast<ConstantSDNode>(N->getOperand(2).getNode())->getZExtValue();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Unreachable
|
// Unreachable
|
||||||
|
@ -1603,9 +1599,9 @@ static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc,
|
||||||
}
|
}
|
||||||
|
|
||||||
SDNode *AArch64DAGToDAGISel::SelectBitfieldExtractOp(SDNode *N) {
|
SDNode *AArch64DAGToDAGISel::SelectBitfieldExtractOp(SDNode *N) {
|
||||||
unsigned Opc, LSB, MSB;
|
unsigned Opc, Immr, Imms;
|
||||||
SDValue Opd0;
|
SDValue Opd0;
|
||||||
if (!isBitfieldExtractOp(CurDAG, N, Opc, Opd0, LSB, MSB))
|
if (!isBitfieldExtractOp(CurDAG, N, Opc, Opd0, Immr, Imms))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
EVT VT = N->getValueType(0);
|
EVT VT = N->getValueType(0);
|
||||||
|
@ -1614,8 +1610,8 @@ SDNode *AArch64DAGToDAGISel::SelectBitfieldExtractOp(SDNode *N) {
|
||||||
// If the bit extract operation is 64bit but the original type is 32bit, we
|
// If the bit extract operation is 64bit but the original type is 32bit, we
|
||||||
// need to add one EXTRACT_SUBREG.
|
// need to add one EXTRACT_SUBREG.
|
||||||
if ((Opc == AArch64::SBFMXri || Opc == AArch64::UBFMXri) && VT == MVT::i32) {
|
if ((Opc == AArch64::SBFMXri || Opc == AArch64::UBFMXri) && VT == MVT::i32) {
|
||||||
SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(LSB, dl, MVT::i64),
|
SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
|
||||||
CurDAG->getTargetConstant(MSB, dl, MVT::i64)};
|
CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
|
||||||
|
|
||||||
SDNode *BFM = CurDAG->getMachineNode(Opc, dl, MVT::i64, Ops64);
|
SDNode *BFM = CurDAG->getMachineNode(Opc, dl, MVT::i64, Ops64);
|
||||||
SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
|
SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
|
||||||
|
@ -1625,8 +1621,8 @@ SDNode *AArch64DAGToDAGISel::SelectBitfieldExtractOp(SDNode *N) {
|
||||||
return Node;
|
return Node;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(LSB, dl, VT),
|
SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
|
||||||
CurDAG->getTargetConstant(MSB, dl, VT)};
|
CurDAG->getTargetConstant(Imms, dl, VT)};
|
||||||
return CurDAG->SelectNodeTo(N, Opc, VT, Ops);
|
return CurDAG->SelectNodeTo(N, Opc, VT, Ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
; RUN: llc -mtriple=arm64-apple-ios < %s | FileCheck %s
|
||||||
|
|
||||||
|
define i64 @sbfiz64(i64 %v) {
|
||||||
|
; CHECK-LABEL: sbfiz64:
|
||||||
|
; CHECK: sbfiz x0, x0, #1, #16
|
||||||
|
%shl = shl i64 %v, 48
|
||||||
|
%shr = ashr i64 %shl, 47
|
||||||
|
ret i64 %shr
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @sbfiz32(i32 %v) {
|
||||||
|
; CHECK-LABEL: sbfiz32:
|
||||||
|
; CHECK: sbfiz w0, w0, #1, #14
|
||||||
|
%shl = shl i32 %v, 18
|
||||||
|
%shr = ashr i32 %shl, 17
|
||||||
|
ret i32 %shr
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @ubfiz64(i64 %v) {
|
||||||
|
; CHECK-LABEL: ubfiz64:
|
||||||
|
; CHECK: ubfiz x0, x0, #36, #11
|
||||||
|
%shl = shl i64 %v, 53
|
||||||
|
%shr = lshr i64 %shl, 17
|
||||||
|
ret i64 %shr
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @ubfiz32(i32 %v) {
|
||||||
|
; CHECK-LABEL: ubfiz32:
|
||||||
|
; CHECK: ubfiz w0, w0, #6, #24
|
||||||
|
%shl = shl i32 %v, 8
|
||||||
|
%shr = lshr i32 %shl, 2
|
||||||
|
ret i32 %shr
|
||||||
|
}
|
Loading…
Reference in New Issue