From 7f6fe7c02c75559b4719d66e769339ef8ad64258 Mon Sep 17 00:00:00 2001 From: Jessica Paquette Date: Mon, 29 Apr 2019 20:58:17 +0000 Subject: [PATCH] [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 --- .../Target/AArch64/AArch64InstructionSelector.cpp | 73 ++++++++++++++++++++-- llvm/test/CodeGen/AArch64/arm64-crypto.ll | 2 + 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp index 7f5bc27..ae668dd 100644 --- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -101,6 +101,7 @@ private: MachineRegisterInfo &MRI) const; bool selectIntrinsicWithSideEffects(MachineInstr &I, MachineRegisterInfo &MRI) const; + bool selectIntrinsic(MachineInstr &I, MachineRegisterInfo &MRI) const; bool selectVectorICmp(MachineInstr &I, MachineRegisterInfo &MRI) const; bool selectIntrinsicTrunc(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: return STI.isTargetDarwin() ? selectVaStartDarwin(I, MF, MRI) : selectVaStartAAPCS(I, MF, MRI); + case TargetOpcode::G_INTRINSIC: + return selectIntrinsic(I, MRI); case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: return selectIntrinsicWithSideEffects(I, MRI); case TargetOpcode::G_IMPLICIT_DEF: { @@ -3083,6 +3086,17 @@ bool AArch64InstructionSelector::selectBuildVector( 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 /// intrinsic. static unsigned getStlxrOpcode(unsigned NumBytesToStore) { @@ -3101,12 +3115,9 @@ static unsigned getStlxrOpcode(unsigned NumBytesToStore) { bool AArch64InstructionSelector::selectIntrinsicWithSideEffects( MachineInstr &I, MachineRegisterInfo &MRI) const { // Find the intrinsic ID. - auto IntrinOp = find_if(I.operands(), [&](const MachineOperand &Op) { - return Op.isIntrinsicID(); - }); - if (IntrinOp == I.operands_end()) + unsigned IntrinID = findIntrinsicID(I); + if (!IntrinID) return false; - unsigned IntrinID = IntrinOp->getIntrinsicID(); MachineIRBuilder MIRBuilder(I); // Select the instruction. @@ -3148,6 +3159,58 @@ bool AArch64InstructionSelector::selectIntrinsicWithSideEffects( 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 /// 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. diff --git a/llvm/test/CodeGen/AArch64/arm64-crypto.ll b/llvm/test/CodeGen/AArch64/arm64-crypto.ll index 615f2a8..1def758 100644 --- a/llvm/test/CodeGen/AArch64/arm64-crypto.ll +++ b/llvm/test/CodeGen/AArch64/arm64-crypto.ll @@ -1,4 +1,5 @@ ; 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.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 } +; FALLBACK-NOT: remark{{.*}}test_sha1h define i32 @test_sha1h(i32 %hash_e) { ; CHECK-LABEL: test_sha1h: ; CHECK: fmov [[HASH_E:s[0-9]+]], w0 -- 2.7.4