[GlobalISel][AArch64] Select llvm.aarch64.crypto.sha1h
This was falling back and gives us a reason to create a selectIntrinsic function which we would need eventually anyway. Update arm64-crypto.ll to show that we correctly select it. Also factor out the code for finding an intrinsic ID. llvm-svn: 359501
This commit is contained in:
parent
bb92282b29
commit
7f6fe7c02c
|
@ -101,6 +101,7 @@ private:
|
||||||
MachineRegisterInfo &MRI) const;
|
MachineRegisterInfo &MRI) const;
|
||||||
bool selectIntrinsicWithSideEffects(MachineInstr &I,
|
bool selectIntrinsicWithSideEffects(MachineInstr &I,
|
||||||
MachineRegisterInfo &MRI) const;
|
MachineRegisterInfo &MRI) const;
|
||||||
|
bool selectIntrinsic(MachineInstr &I, MachineRegisterInfo &MRI) const;
|
||||||
bool selectVectorICmp(MachineInstr &I, MachineRegisterInfo &MRI) const;
|
bool selectVectorICmp(MachineInstr &I, MachineRegisterInfo &MRI) const;
|
||||||
bool selectIntrinsicTrunc(MachineInstr &I, MachineRegisterInfo &MRI) const;
|
bool selectIntrinsicTrunc(MachineInstr &I, MachineRegisterInfo &MRI) const;
|
||||||
bool selectIntrinsicRound(MachineInstr &I, MachineRegisterInfo &MRI) const;
|
bool selectIntrinsicRound(MachineInstr &I, MachineRegisterInfo &MRI) const;
|
||||||
|
@ -1855,6 +1856,8 @@ bool AArch64InstructionSelector::select(MachineInstr &I,
|
||||||
case TargetOpcode::G_VASTART:
|
case TargetOpcode::G_VASTART:
|
||||||
return STI.isTargetDarwin() ? selectVaStartDarwin(I, MF, MRI)
|
return STI.isTargetDarwin() ? selectVaStartDarwin(I, MF, MRI)
|
||||||
: selectVaStartAAPCS(I, MF, MRI);
|
: selectVaStartAAPCS(I, MF, MRI);
|
||||||
|
case TargetOpcode::G_INTRINSIC:
|
||||||
|
return selectIntrinsic(I, MRI);
|
||||||
case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
|
case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
|
||||||
return selectIntrinsicWithSideEffects(I, MRI);
|
return selectIntrinsicWithSideEffects(I, MRI);
|
||||||
case TargetOpcode::G_IMPLICIT_DEF: {
|
case TargetOpcode::G_IMPLICIT_DEF: {
|
||||||
|
@ -3083,6 +3086,17 @@ bool AArch64InstructionSelector::selectBuildVector(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function to find an intrinsic ID on an a MachineInstr. Returns the
|
||||||
|
/// ID if it exists, and 0 otherwise.
|
||||||
|
static unsigned findIntrinsicID(MachineInstr &I) {
|
||||||
|
auto IntrinOp = find_if(I.operands(), [&](const MachineOperand &Op) {
|
||||||
|
return Op.isIntrinsicID();
|
||||||
|
});
|
||||||
|
if (IntrinOp == I.operands_end())
|
||||||
|
return 0;
|
||||||
|
return IntrinOp->getIntrinsicID();
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper function to emit the correct opcode for a llvm.aarch64.stlxr
|
/// Helper function to emit the correct opcode for a llvm.aarch64.stlxr
|
||||||
/// intrinsic.
|
/// intrinsic.
|
||||||
static unsigned getStlxrOpcode(unsigned NumBytesToStore) {
|
static unsigned getStlxrOpcode(unsigned NumBytesToStore) {
|
||||||
|
@ -3101,12 +3115,9 @@ static unsigned getStlxrOpcode(unsigned NumBytesToStore) {
|
||||||
bool AArch64InstructionSelector::selectIntrinsicWithSideEffects(
|
bool AArch64InstructionSelector::selectIntrinsicWithSideEffects(
|
||||||
MachineInstr &I, MachineRegisterInfo &MRI) const {
|
MachineInstr &I, MachineRegisterInfo &MRI) const {
|
||||||
// Find the intrinsic ID.
|
// Find the intrinsic ID.
|
||||||
auto IntrinOp = find_if(I.operands(), [&](const MachineOperand &Op) {
|
unsigned IntrinID = findIntrinsicID(I);
|
||||||
return Op.isIntrinsicID();
|
if (!IntrinID)
|
||||||
});
|
|
||||||
if (IntrinOp == I.operands_end())
|
|
||||||
return false;
|
return false;
|
||||||
unsigned IntrinID = IntrinOp->getIntrinsicID();
|
|
||||||
MachineIRBuilder MIRBuilder(I);
|
MachineIRBuilder MIRBuilder(I);
|
||||||
|
|
||||||
// Select the instruction.
|
// Select the instruction.
|
||||||
|
@ -3148,6 +3159,58 @@ bool AArch64InstructionSelector::selectIntrinsicWithSideEffects(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AArch64InstructionSelector::selectIntrinsic(
|
||||||
|
MachineInstr &I, MachineRegisterInfo &MRI) const {
|
||||||
|
unsigned IntrinID = findIntrinsicID(I);
|
||||||
|
if (!IntrinID)
|
||||||
|
return false;
|
||||||
|
MachineIRBuilder MIRBuilder(I);
|
||||||
|
|
||||||
|
switch (IntrinID) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case Intrinsic::aarch64_crypto_sha1h:
|
||||||
|
unsigned DstReg = I.getOperand(0).getReg();
|
||||||
|
unsigned SrcReg = I.getOperand(2).getReg();
|
||||||
|
|
||||||
|
// FIXME: Should this be an assert?
|
||||||
|
if (MRI.getType(DstReg).getSizeInBits() != 32 ||
|
||||||
|
MRI.getType(SrcReg).getSizeInBits() != 32)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// The operation has to happen on FPRs. Set up some new FPR registers for
|
||||||
|
// the source and destination if they are on GPRs.
|
||||||
|
if (RBI.getRegBank(SrcReg, MRI, TRI)->getID() != AArch64::FPRRegBankID) {
|
||||||
|
SrcReg = MRI.createVirtualRegister(&AArch64::FPR32RegClass);
|
||||||
|
MIRBuilder.buildCopy({SrcReg}, {I.getOperand(2)});
|
||||||
|
|
||||||
|
// Make sure the copy ends up getting constrained properly.
|
||||||
|
RBI.constrainGenericRegister(I.getOperand(2).getReg(),
|
||||||
|
AArch64::GPR32RegClass, MRI);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RBI.getRegBank(DstReg, MRI, TRI)->getID() != AArch64::FPRRegBankID)
|
||||||
|
DstReg = MRI.createVirtualRegister(&AArch64::FPR32RegClass);
|
||||||
|
|
||||||
|
// Actually insert the instruction.
|
||||||
|
auto SHA1Inst = MIRBuilder.buildInstr(AArch64::SHA1Hrr, {DstReg}, {SrcReg});
|
||||||
|
constrainSelectedInstRegOperands(*SHA1Inst, TII, TRI, RBI);
|
||||||
|
|
||||||
|
// Did we create a new register for the destination?
|
||||||
|
if (DstReg != I.getOperand(0).getReg()) {
|
||||||
|
// Yep. Copy the result of the instruction back into the original
|
||||||
|
// destination.
|
||||||
|
MIRBuilder.buildCopy({I.getOperand(0)}, {DstReg});
|
||||||
|
RBI.constrainGenericRegister(I.getOperand(0).getReg(),
|
||||||
|
AArch64::GPR32RegClass, MRI);
|
||||||
|
}
|
||||||
|
|
||||||
|
I.eraseFromParent();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// SelectArithImmed - Select an immediate value that can be represented as
|
/// SelectArithImmed - Select an immediate value that can be represented as
|
||||||
/// a 12-bit value shifted left by either 0 or 12. If so, return true with
|
/// a 12-bit value shifted left by either 0 or 12. If so, return true with
|
||||||
/// Val set to the 12-bit value and Shift set to the shifter operand.
|
/// Val set to the 12-bit value and Shift set to the shifter operand.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: llc -mtriple=arm64-eabi -mattr=crypto -aarch64-neon-syntax=apple -o - %s | FileCheck %s
|
; RUN: llc -mtriple=arm64-eabi -mattr=crypto -aarch64-neon-syntax=apple -o - %s | FileCheck %s
|
||||||
|
; RUN: llc -mtriple=arm64-eabi -global-isel -global-isel-abort=2 -pass-remarks-missed=gisel* -mattr=crypto -aarch64-neon-syntax=apple -o - %s 2>&1 | FileCheck %s --check-prefixes=CHECK,FALLBACK
|
||||||
|
|
||||||
declare <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %data, <16 x i8> %key)
|
declare <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %data, <16 x i8> %key)
|
||||||
declare <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %data, <16 x i8> %key)
|
declare <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %data, <16 x i8> %key)
|
||||||
|
@ -77,6 +78,7 @@ define <4 x i32> @test_sha1m(<4 x i32> %hash_abcd, i32 %hash_e, <4 x i32> %wk) {
|
||||||
ret <4 x i32> %res
|
ret <4 x i32> %res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; FALLBACK-NOT: remark{{.*}}test_sha1h
|
||||||
define i32 @test_sha1h(i32 %hash_e) {
|
define i32 @test_sha1h(i32 %hash_e) {
|
||||||
; CHECK-LABEL: test_sha1h:
|
; CHECK-LABEL: test_sha1h:
|
||||||
; CHECK: fmov [[HASH_E:s[0-9]+]], w0
|
; CHECK: fmov [[HASH_E:s[0-9]+]], w0
|
||||||
|
|
Loading…
Reference in New Issue