mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-24 22:24:54 +00:00
Update ARM DAGtoDAG for matching UBFX instruction for unsigned bitfield
extraction. This fixes PR5998. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@102144 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -142,7 +142,7 @@ private:
|
|||||||
unsigned *QOpcodes1);
|
unsigned *QOpcodes1);
|
||||||
|
|
||||||
/// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.
|
/// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM.
|
||||||
SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, unsigned Opc);
|
SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned);
|
||||||
|
|
||||||
/// SelectCMOVOp - Select CMOV instructions for ARM.
|
/// SelectCMOVOp - Select CMOV instructions for ARM.
|
||||||
SDNode *SelectCMOVOp(SDNode *N);
|
SDNode *SelectCMOVOp(SDNode *N);
|
||||||
@@ -1248,10 +1248,42 @@ SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
|
SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N,
|
||||||
unsigned Opc) {
|
bool isSigned) {
|
||||||
if (!Subtarget->hasV6T2Ops())
|
if (!Subtarget->hasV6T2Ops())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
unsigned Opc = isSigned ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX)
|
||||||
|
: (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX);
|
||||||
|
|
||||||
|
|
||||||
|
// For unsigned extracts, check for a shift right and mask
|
||||||
|
unsigned And_imm = 0;
|
||||||
|
if (N->getOpcode() == ISD::AND) {
|
||||||
|
if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) {
|
||||||
|
|
||||||
|
// The immediate is a mask of the low bits iff imm & (imm+1) == 0
|
||||||
|
if (And_imm & (And_imm + 1))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
unsigned Srl_imm = 0;
|
||||||
|
if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL,
|
||||||
|
Srl_imm)) {
|
||||||
|
assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
|
||||||
|
|
||||||
|
unsigned Width = CountTrailingOnes_32(And_imm);
|
||||||
|
unsigned LSB = Srl_imm;
|
||||||
|
SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
|
||||||
|
SDValue Ops[] = { N->getOperand(0).getOperand(0),
|
||||||
|
CurDAG->getTargetConstant(LSB, MVT::i32),
|
||||||
|
CurDAG->getTargetConstant(Width, MVT::i32),
|
||||||
|
getAL(CurDAG), Reg0 };
|
||||||
|
return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we're looking for a shift of a shift
|
||||||
unsigned Shl_imm = 0;
|
unsigned Shl_imm = 0;
|
||||||
if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
|
if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) {
|
||||||
assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
|
assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
|
||||||
@@ -1515,13 +1547,11 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ISD::SRL:
|
case ISD::SRL:
|
||||||
if (SDNode *I = SelectV6T2BitfieldExtractOp(N,
|
if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
|
||||||
Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX))
|
|
||||||
return I;
|
return I;
|
||||||
break;
|
break;
|
||||||
case ISD::SRA:
|
case ISD::SRA:
|
||||||
if (SDNode *I = SelectV6T2BitfieldExtractOp(N,
|
if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true))
|
||||||
Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX))
|
|
||||||
return I;
|
return I;
|
||||||
break;
|
break;
|
||||||
case ISD::MUL:
|
case ISD::MUL:
|
||||||
@@ -1565,6 +1595,10 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ISD::AND: {
|
case ISD::AND: {
|
||||||
|
// Check for unsigned bitfield extract
|
||||||
|
if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false))
|
||||||
|
return I;
|
||||||
|
|
||||||
// (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
|
// (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
|
||||||
// of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
|
// of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
|
||||||
// are entirely contributed by c2 and lower 16-bits are entirely contributed
|
// are entirely contributed by c2 and lower 16-bits are entirely contributed
|
||||||
|
28
test/CodeGen/ARM/bfx.ll
Normal file
28
test/CodeGen/ARM/bfx.ll
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
; RUN: llc < %s -march=arm -mattr=+v7a | FileCheck %s
|
||||||
|
|
||||||
|
define i32 @sbfx1(i32 %a) {
|
||||||
|
; CHECK: sbfx1
|
||||||
|
; CHECK: sbfx r0, r0, #7, #11
|
||||||
|
%t1 = lshr i32 %a, 7
|
||||||
|
%t2 = trunc i32 %t1 to i11
|
||||||
|
%t3 = sext i11 %t2 to i32
|
||||||
|
ret i32 %t3
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @ubfx1(i32 %a) {
|
||||||
|
; CHECK: ubfx1
|
||||||
|
; CHECK: ubfx r0, r0, #7, #11
|
||||||
|
%t1 = lshr i32 %a, 7
|
||||||
|
%t2 = trunc i32 %t1 to i11
|
||||||
|
%t3 = zext i11 %t2 to i32
|
||||||
|
ret i32 %t3
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @ubfx2(i32 %a) {
|
||||||
|
; CHECK: ubfx2
|
||||||
|
; CHECK: ubfx r0, r0, #7, #11
|
||||||
|
%t1 = lshr i32 %a, 7
|
||||||
|
%t2 = and i32 %t1, 2047
|
||||||
|
ret i32 %t2
|
||||||
|
}
|
||||||
|
|
28
test/CodeGen/Thumb2/bfx.ll
Normal file
28
test/CodeGen/Thumb2/bfx.ll
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
; RUN: llc < %s -march=thumb -mattr=+thumb2 | FileCheck %s
|
||||||
|
|
||||||
|
define i32 @sbfx1(i32 %a) {
|
||||||
|
; CHECK: sbfx1
|
||||||
|
; CHECK: sbfx r0, r0, #7, #11
|
||||||
|
%t1 = lshr i32 %a, 7
|
||||||
|
%t2 = trunc i32 %t1 to i11
|
||||||
|
%t3 = sext i11 %t2 to i32
|
||||||
|
ret i32 %t3
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @ubfx1(i32 %a) {
|
||||||
|
; CHECK: ubfx1
|
||||||
|
; CHECK: ubfx r0, r0, #7, #11
|
||||||
|
%t1 = lshr i32 %a, 7
|
||||||
|
%t2 = trunc i32 %t1 to i11
|
||||||
|
%t3 = zext i11 %t2 to i32
|
||||||
|
ret i32 %t3
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @ubfx2(i32 %a) {
|
||||||
|
; CHECK: ubfx2
|
||||||
|
; CHECK: ubfx r0, r0, #7, #11
|
||||||
|
%t1 = lshr i32 %a, 7
|
||||||
|
%t2 = and i32 %t1, 2047
|
||||||
|
ret i32 %t2
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user