llvm.org GIT mirror llvm / 55d4200
Recognize inline asm 'rev /bin/bash, ' as a bswap intrinsic call. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123048 91177308-0d34-0410-b5e6-96231b3b80d8 Evan Cheng 9 years ago
8 changed file(s) with 117 addition(s) and 55 deletion(s). Raw diff Collapse all Expand all
4747 /// be capable of handling this kind of change.
4848 ///
4949 void LowerIntrinsicCall(CallInst *CI);
50
51 /// LowerToByteSwap - Replace a call instruction into a call to bswap
52 /// intrinsic. Return false if it has determined the call is not a
53 /// simple integer bswap.
54 static bool LowerToByteSwap(CallInst *CI);
5055 };
5156 }
5257
537537 "Lowering should have eliminated any uses of the intrinsic call!");
538538 CI->eraseFromParent();
539539 }
540
541 bool IntrinsicLowering::LowerToByteSwap(CallInst *CI) {
542 // Verify this is a simple bswap.
543 if (CI->getNumArgOperands() != 1 ||
544 CI->getType() != CI->getArgOperand(0)->getType() ||
545 !CI->getType()->isIntegerTy())
546 return false;
547
548 const IntegerType *Ty = dyn_cast(CI->getType());
549 if (!Ty)
550 return false;
551
552 // Okay, we can do this xform, do so now.
553 const Type *Tys[] = { Ty };
554 Module *M = CI->getParent()->getParent()->getParent();
555 Constant *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Tys, 1);
556
557 Value *Op = CI->getArgOperand(0);
558 Op = CallInst::Create(Int, Op, CI->getName(), CI);
559
560 CI->replaceAllUsesWith(Op);
561 CI->eraseFromParent();
562 return true;
563 }
20702070 if (!ItinData || ItinData->isEmpty())
20712071 return DefTID.mayLoad() ? 3 : 1;
20722072
2073
20742073 const TargetInstrDesc &UseTID = UseMI->getDesc();
20752074 const MachineOperand &DefMO = DefMI->getOperand(DefIdx);
20762075 if (DefMO.getReg() == ARM::CPSR) {
3232 #include "llvm/Intrinsics.h"
3333 #include "llvm/Type.h"
3434 #include "llvm/CodeGen/CallingConvLower.h"
35 #include "llvm/CodeGen/IntrinsicLowering.h"
3536 #include "llvm/CodeGen/MachineBasicBlock.h"
3637 #include "llvm/CodeGen/MachineFrameInfo.h"
3738 #include "llvm/CodeGen/MachineFunction.h"
4243 #include "llvm/MC/MCSectionMachO.h"
4344 #include "llvm/Target/TargetOptions.h"
4445 #include "llvm/ADT/VectorExtras.h"
46 #include "llvm/ADT/StringExtras.h"
4547 #include "llvm/ADT/Statistic.h"
4648 #include "llvm/Support/CommandLine.h"
4749 #include "llvm/Support/ErrorHandling.h"
60916093 // ARM Inline Assembly Support
60926094 //===----------------------------------------------------------------------===//
60936095
6096 bool ARMTargetLowering::ExpandInlineAsm(CallInst *CI) const {
6097 // Looking for "rev" which is V6+.
6098 if (!Subtarget->hasV6Ops())
6099 return false;
6100
6101 InlineAsm *IA = cast(CI->getCalledValue());
6102 std::string AsmStr = IA->getAsmString();
6103 SmallVector AsmPieces;
6104 SplitString(AsmStr, AsmPieces, ";\n");
6105
6106 switch (AsmPieces.size()) {
6107 default: return false;
6108 case 1:
6109 AsmStr = AsmPieces[0];
6110 AsmPieces.clear();
6111 SplitString(AsmStr, AsmPieces, " \t,");
6112
6113 // rev $0, $1
6114 if (AsmPieces.size() == 3 &&
6115 AsmPieces[0] == "rev" && AsmPieces[1] == "$0" && AsmPieces[2] == "$1" &&
6116 IA->getConstraintString().compare(0, 4, "=l,l") == 0) {
6117 const IntegerType *Ty = dyn_cast(CI->getType());
6118 if (Ty && Ty->getBitWidth() == 32)
6119 return IntrinsicLowering::LowerToByteSwap(CI);
6120 }
6121 break;
6122 }
6123
6124 return false;
6125 }
6126
60946127 /// getConstraintType - Given a constraint letter, return the type of
60956128 /// constraint it is for this target.
60966129 ARMTargetLowering::ConstraintType
255255 const SelectionDAG &DAG,
256256 unsigned Depth) const;
257257
258
259 virtual bool ExpandInlineAsm(CallInst *CI) const;
258260
259261 ConstraintType getConstraintType(const std::string &Constraint) const;
260262
2727 #include "llvm/Instructions.h"
2828 #include "llvm/Intrinsics.h"
2929 #include "llvm/LLVMContext.h"
30 #include "llvm/CodeGen/IntrinsicLowering.h"
3031 #include "llvm/CodeGen/MachineFrameInfo.h"
3132 #include "llvm/CodeGen/MachineFunction.h"
3233 #include "llvm/CodeGen/MachineInstrBuilder.h"
1172811729 // X86 Inline Assembly Support
1172911730 //===----------------------------------------------------------------------===//
1173011731
11731 static bool LowerToBSwap(CallInst *CI) {
11732 // FIXME: this should verify that we are targetting a 486 or better. If not,
11733 // we will turn this bswap into something that will be lowered to logical ops
11734 // instead of emitting the bswap asm. For now, we don't support 486 or lower
11735 // so don't worry about this.
11736
11737 // Verify this is a simple bswap.
11738 if (CI->getNumArgOperands() != 1 ||
11739 CI->getType() != CI->getArgOperand(0)->getType() ||
11740 !CI->getType()->isIntegerTy())
11741 return false;
11742
11743 const IntegerType *Ty = dyn_cast(CI->getType());
11744 if (!Ty || Ty->getBitWidth() % 16 != 0)
11745 return false;
11746
11747 // Okay, we can do this xform, do so now.
11748 const Type *Tys[] = { Ty };
11749 Module *M = CI->getParent()->getParent()->getParent();
11750 Constant *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Tys, 1);
11751
11752 Value *Op = CI->getArgOperand(0);
11753 Op = CallInst::Create(Int, Op, CI->getName(), CI);
11754
11755 CI->replaceAllUsesWith(Op);
11756 CI->eraseFromParent();
11757 return true;
11758 }
11759
1176011732 bool X86TargetLowering::ExpandInlineAsm(CallInst *CI) const {
1176111733 InlineAsm *IA = cast(CI->getCalledValue());
11762 InlineAsm::ConstraintInfoVector Constraints = IA->ParseConstraints();
1176311734
1176411735 std::string AsmStr = IA->getAsmString();
1176511736
1177411745 AsmPieces.clear();
1177511746 SplitString(AsmStr, AsmPieces, " \t"); // Split with whitespace.
1177611747
11748 // FIXME: this should verify that we are targetting a 486 or better. If not,
11749 // we will turn this bswap into something that will be lowered to logical ops
11750 // instead of emitting the bswap asm. For now, we don't support 486 or lower
11751 // so don't worry about this.
1177711752 // bswap $0
1177811753 if (AsmPieces.size() == 2 &&
1177911754 (AsmPieces[0] == "bswap" ||
1178311758 AsmPieces[1] == "${0:q}")) {
1178411759 // No need to check constraints, nothing other than the equivalent of
1178511760 // "=r,0" would be valid here.
11786 return LowerToBSwap(CI);
11761 const IntegerType *Ty = dyn_cast(CI->getType());
11762 if (!Ty || Ty->getBitWidth() % 16 != 0)
11763 return false;
11764 return IntrinsicLowering::LowerToByteSwap(CI);
1178711765 }
1178811766 // rorw $$8, ${0:w} --> llvm.bswap.i16
1178911767 if (CI->getType()->isIntegerTy(16) &&
1179311771 AsmPieces[2] == "${0:w}" &&
1179411772 IA->getConstraintString().compare(0, 5, "=r,0,") == 0) {
1179511773 AsmPieces.clear();
11796 const std::string &Constraints = IA->getConstraintString();
11797 SplitString(StringRef(Constraints).substr(5), AsmPieces, ",");
11774 const std::string &ConstraintsStr = IA->getConstraintString();
11775 SplitString(StringRef(ConstraintsStr).substr(5), AsmPieces, ",");
1179811776 std::sort(AsmPieces.begin(), AsmPieces.end());
1179911777 if (AsmPieces.size() == 4 &&
1180011778 AsmPieces[0] == "~{cc}" &&
1180111779 AsmPieces[1] == "~{dirflag}" &&
1180211780 AsmPieces[2] == "~{flags}" &&
1180311781 AsmPieces[3] == "~{fpsr}") {
11804 return LowerToBSwap(CI);
11782 const IntegerType *Ty = dyn_cast(CI->getType());
11783 if (!Ty || Ty->getBitWidth() % 16 != 0)
11784 return false;
11785 return IntrinsicLowering::LowerToByteSwap(CI);
1180511786 }
1180611787 }
1180711788 break;
1182111802 if (Words.size() == 3 && Words[0] == "rorw" && Words[1] == "$$8" &&
1182211803 Words[2] == "${0:w}") {
1182311804 AsmPieces.clear();
11824 const std::string &Constraints = IA->getConstraintString();
11825 SplitString(StringRef(Constraints).substr(5), AsmPieces, ",");
11805 const std::string &ConstraintsStr = IA->getConstraintString();
11806 SplitString(StringRef(ConstraintsStr).substr(5), AsmPieces, ",");
1182611807 std::sort(AsmPieces.begin(), AsmPieces.end());
1182711808 if (AsmPieces.size() == 4 &&
1182811809 AsmPieces[0] == "~{cc}" &&
1182911810 AsmPieces[1] == "~{dirflag}" &&
1183011811 AsmPieces[2] == "~{flags}" &&
1183111812 AsmPieces[3] == "~{fpsr}") {
11832 return LowerToBSwap(CI);
11813 const IntegerType *Ty = dyn_cast(CI->getType());
11814 if (!Ty || Ty->getBitWidth() % 16 != 0)
11815 return false;
11816 return IntrinsicLowering::LowerToByteSwap(CI);
1183311817 }
1183411818 }
1183511819 }
1183611820 }
1183711821 }
11838 if (CI->getType()->isIntegerTy(64) &&
11839 Constraints.size() >= 2 &&
11840 Constraints[0].Codes.size() == 1 && Constraints[0].Codes[0] == "A" &&
11841 Constraints[1].Codes.size() == 1 && Constraints[1].Codes[0] == "0") {
11842 // bswap %eax / bswap %edx / xchgl %eax, %edx -> llvm.bswap.i64
11843 SmallVector Words;
11844 SplitString(AsmPieces[0], Words, " \t");
11845 if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%eax") {
11846 Words.clear();
11847 SplitString(AsmPieces[1], Words, " \t");
11848 if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%edx") {
11822
11823 if (CI->getType()->isIntegerTy(64)) {
11824 InlineAsm::ConstraintInfoVector Constraints = IA->ParseConstraints();
11825 if (Constraints.size() >= 2 &&
11826 Constraints[0].Codes.size() == 1 && Constraints[0].Codes[0] == "A" &&
11827 Constraints[1].Codes.size() == 1 && Constraints[1].Codes[0] == "0") {
11828 // bswap %eax / bswap %edx / xchgl %eax, %edx -> llvm.bswap.i64
11829 SmallVector Words;
11830 SplitString(AsmPieces[0], Words, " \t");
11831 if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%eax") {
1184911832 Words.clear();
11850 SplitString(AsmPieces[2], Words, " \t,");
11851 if (Words.size() == 3 && Words[0] == "xchgl" && Words[1] == "%eax" &&
11852 Words[2] == "%edx") {
11853 return LowerToBSwap(CI);
11833 SplitString(AsmPieces[1], Words, " \t");
11834 if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%edx") {
11835 Words.clear();
11836 SplitString(AsmPieces[2], Words, " \t,");
11837 if (Words.size() == 3 && Words[0] == "xchgl" && Words[1] == "%eax" &&
11838 Words[2] == "%edx") {
11839 const IntegerType *Ty = dyn_cast(CI->getType());
11840 if (!Ty || Ty->getBitWidth() % 16 != 0)
11841 return false;
11842 return IntrinsicLowering::LowerToByteSwap(CI);
11843 }
1185411844 }
1185511845 }
1185611846 }
0 ; RUN: llc < %s -mtriple=arm-apple-darwin -mattr=+v6 | FileCheck %s
1
2 define i32 @t1(i32 %x) nounwind {
3 ; CHECK: t1:
4 ; CHECK-NOT: InlineAsm
5 ; CHECK: rev
6 %asmtmp = tail call i32 asm "rev $0, $1\0A", "=l,l"(i32 %x) nounwind
7 ret i32 %asmtmp
8 }
None ; RUN: llc < %s -march=x86-64 > %t
1 ; RUN: not grep APP %t
0 ; RUN: llc < %s -mtriple=x86_64-apple-darwin > %t
1 ; RUN: not grep InlineAsm %t
22 ; RUN: FileCheck %s < %t
33
44 ; CHECK: foo: