AArch64: add BFC alias for the BFI/BFM instructions.

Unlike 32-bit ARM, AArch64 can use wzr/xzr to implement this without the need
for a separate instruction.

rdar://18679590

llvm-svn: 236245
This commit is contained in:
Tim Northover 2015-04-30 18:28:58 +00:00
parent f16b28762e
commit db249b5492
5 changed files with 100 additions and 8 deletions

View File

@ -3644,6 +3644,60 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Op3.getEndLoc(), getContext());
}
}
} else if (NumOperands == 4 && Tok == "bfc") {
// FIXME: Horrible hack to handle BFC->BFM alias.
AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
if (LSBCE && WidthCE) {
uint64_t LSB = LSBCE->getValue();
uint64_t Width = WidthCE->getValue();
uint64_t RegWidth = 0;
if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
Op1.getReg()))
RegWidth = 64;
else
RegWidth = 32;
if (LSB >= RegWidth)
return Error(LSBOp.getStartLoc(),
"expected integer in range [0, 31]");
if (Width < 1 || Width > RegWidth)
return Error(WidthOp.getStartLoc(),
"expected integer in range [1, 32]");
uint64_t ImmR = 0;
if (RegWidth == 32)
ImmR = (32 - LSB) & 0x1f;
else
ImmR = (64 - LSB) & 0x3f;
uint64_t ImmS = Width - 1;
if (ImmR != 0 && ImmS >= ImmR)
return Error(WidthOp.getStartLoc(),
"requested insert overflows register");
const MCExpr *ImmRExpr = MCConstantExpr::Create(ImmR, getContext());
const MCExpr *ImmSExpr = MCConstantExpr::Create(ImmS, getContext());
Operands[0] = AArch64Operand::CreateToken(
"bfm", false, Op.getStartLoc(), getContext());
Operands[2] = AArch64Operand::CreateReg(
RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
SMLoc(), getContext());
Operands[3] = AArch64Operand::CreateImm(
ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
Operands.emplace_back(
AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
WidthOp.getEndLoc(), getContext()));
}
}
} else if (NumOperands == 5) {
// FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
// UBFIZ -> UBFM aliases.
@ -3675,8 +3729,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
"expected integer in range [1, 32]");
uint64_t NewOp3Val = 0;
if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
Op1.getReg()))
if (RegWidth == 32)
NewOp3Val = (32 - Op3Val) & 0x1f;
else
NewOp3Val = (64 - Op3Val) & 0x3f;

View File

@ -162,11 +162,23 @@ void AArch64InstPrinter::printInst(const MCInst *MI, raw_ostream &O,
int ImmR = MI->getOperand(3).getImm();
int ImmS = MI->getOperand(4).getImm();
// BFI alias
if (ImmS < ImmR) {
if ((Op2.getReg() == AArch64::WZR || Op2.getReg() == AArch64::XZR) &&
(ImmR == 0 || ImmS < ImmR)) {
// BFC takes precedence over its entire range, sligtly differently to BFI.
int BitWidth = Opcode == AArch64::BFMXri ? 64 : 32;
int LSB = (BitWidth - ImmR) % BitWidth;
int Width = ImmS + 1;
O << "\tbfc\t" << getRegisterName(Op0.getReg())
<< ", #" << LSB << ", #" << Width;
printAnnotation(O, Annot);
return;
} else if (ImmS < ImmR) {
// BFI alias
int BitWidth = Opcode == AArch64::BFMXri ? 64 : 32;
int LSB = (BitWidth - ImmR) % BitWidth;
int Width = ImmS + 1;
O << "\tbfi\t" << getRegisterName(Op0.getReg()) << ", "
<< getRegisterName(Op2.getReg()) << ", #" << LSB << ", #" << Width;
printAnnotation(O, Annot);

View File

@ -1088,6 +1088,23 @@
// CHECK-ERROR-NEXT: ubfx w3, wsp, #10, #8
// CHECK-ERROR-NEXT: ^
bfc wsp, #3, #6
bfc w4, #2, #31
bfc sp, #0, #1
bfc x6, #0, #0
// CHECK-ERROR: error: invalid operand for instruction
// CHECK-ERROR-NEXT: bfc wsp, #3, #6
// CHECK-ERROR-NEXT: ^
// CHECK-ERROR-NEXT: error: requested insert overflows register
// CHECK-ERROR-NEXT: bfc w4, #2, #31
// CHECK-ERROR-NEXT: ^
// CHECK-ERROR-NEXT: error: invalid operand for instruction
// CHECK-ERROR-NEXT: bfc sp, #0, #1
// CHECK-ERROR-NEXT: ^
// CHECK-ERROR-NEXT: error: expected integer in range [1, 32]
// CHECK-ERROR-NEXT: bfc x6, #0, #0
// CHECK-ERROR-NEXT: ^
//------------------------------------------------------------------------------
// Compare & branch (immediate)
//------------------------------------------------------------------------------

View File

@ -978,7 +978,7 @@ _func:
bfm x5, x6, #12, #63
// CHECK: bfi x4, x5, #52, #11 // encoding: [0xa4,0x28,0x4c,0xb3]
// CHECK: bfxil xzr, x4, #0, #1 // encoding: [0x9f,0x00,0x40,0xb3]
// CHECK: bfi x4, xzr, #1, #6 // encoding: [0xe4,0x17,0x7f,0xb3]
// CHECK: bfc x4, #1, #6 // encoding: [0xe4,0x17,0x7f,0xb3]
// CHECK: bfxil x5, x6, #12, #52 // encoding: [0xc5,0xfc,0x4c,0xb3]
sxtb w1, w2
@ -1078,7 +1078,7 @@ _func:
// CHECK: bfxil w9, w10, #0, #32 // encoding: [0x49,0x7d,0x00,0x33]
// CHECK: bfi w11, w12, #31, #1 // encoding: [0x8b,0x01,0x01,0x33]
// CHECK: bfi w13, w14, #29, #3 // encoding: [0xcd,0x09,0x03,0x33]
// CHECK: bfi xzr, xzr, #10, #11 // encoding: [0xff,0x2b,0x76,0xb3]
// CHECK: bfc xzr, #10, #11 // encoding: [0xff,0x2b,0x76,0xb3]
bfxil w9, w10, #0, #1
bfxil x2, x3, #63, #1
@ -1132,6 +1132,16 @@ _func:
// CHECK: lsr w11, w12, #31 // encoding: [0x8b,0x7d,0x1f,0x53]
// CHECK: lsr w13, w14, #29 // encoding: [0xcd,0x7d,0x1d,0x53]
// CHECK: ubfx xzr, xzr, #10, #11 // encoding: [0xff,0x53,0x4a,0xd3]
bfc w3, #0, #32
bfc wzr, #31, #1
bfc x0, #5, #9
bfc xzr, #63, #1
// CHECK: bfc w3, #0, #32 // encoding: [0xe3,0x7f,0x00,0x33]
// CHECK: bfc wzr, #31, #1 // encoding: [0xff,0x03,0x01,0x33]
// CHECK: bfc x0, #5, #9 // encoding: [0xe0,0x23,0x7b,0xb3]
// CHECK: bfc xzr, #63, #1 // encoding: [0xff,0x03,0x41,0xb3]
//------------------------------------------------------------------------------
// Compare & branch (immediate)
//------------------------------------------------------------------------------

View File

@ -622,7 +622,7 @@
# CHECK: bfi x4, x5, #52, #11
# CHECK: bfxil xzr, x4, #0, #1
# CHECK: bfi x4, xzr, #1, #6
# CHECK: bfc x4, #1, #6
# CHECK: bfxil x5, x6, #12, #52
0xa4 0x28 0x4c 0xb3
0x9f 0x0 0x40 0xb3
@ -715,7 +715,7 @@
# CHECK: bfxil w9, w10, #0, #32
# CHECK: bfi w11, w12, #31, #1
# CHECK: bfi w13, w14, #29, #3
# CHECK: bfi xzr, xzr, #10, #11
# CHECK: bfc xzr, #10, #11
0x49 0x1 0x0 0x33
0x62 0x0 0x41 0xb3
0x93 0xfe 0x40 0xb3