diff options
author | Tim Northover <tnorthover@apple.com> | 2014-04-18 09:31:07 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2014-04-18 09:31:07 +0000 |
commit | 66643da8fc5f05c3efc23cb2c168e3b57b7ab9b4 (patch) | |
tree | cd65af196c2ade83b390442c1f08817fa4e46f29 /lib | |
parent | 937290d7ed33e1955e2a76649678acfa5e69ede1 (diff) | |
download | llvm-66643da8fc5f05c3efc23cb2c168e3b57b7ab9b4.tar.gz llvm-66643da8fc5f05c3efc23cb2c168e3b57b7ab9b4.tar.bz2 llvm-66643da8fc5f05c3efc23cb2c168e3b57b7ab9b4.tar.xz |
AArch64/ARM64: emit all vector FP comparisons as such.
ARM64 was scalarizing some vector comparisons which don't quite map to
AArch64's compare and mask instructions. AArch64's approach of sacrificing a
little efficiency to emulate them with the limited set available was better, so
I ported it across.
More "inspired by" than copy/paste since the backend's internal expectations
were a bit different, but the tests were invaluable.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206570 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/ARM64/ARM64ISelLowering.cpp | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/lib/Target/ARM64/ARM64ISelLowering.cpp b/lib/Target/ARM64/ARM64ISelLowering.cpp index 835e2b0db2..d4898ae523 100644 --- a/lib/Target/ARM64/ARM64ISelLowering.cpp +++ b/lib/Target/ARM64/ARM64ISelLowering.cpp @@ -865,6 +865,39 @@ static void changeFPCCToARM64CC(ISD::CondCode CC, ARM64CC::CondCode &CondCode, } } +/// changeVectorFPCCToARM64CC - Convert a DAG fp condition code to an ARM64 CC +/// usable with the vector instructions. Fewer operations are available without +/// a real NZCV register, so we have to use less efficient combinations to get +/// the same effect. +static void changeVectorFPCCToARM64CC(ISD::CondCode CC, + ARM64CC::CondCode &CondCode, + ARM64CC::CondCode &CondCode2, + bool &Invert) { + Invert = false; + switch (CC) { + default: + // Mostly the scalar mappings work fine. + changeFPCCToARM64CC(CC, CondCode, CondCode2); + break; + case ISD::SETUO: + Invert = true; // Fallthrough + case ISD::SETO: + CondCode = ARM64CC::MI; + CondCode2 = ARM64CC::GE; + break; + case ISD::SETUEQ: + case ISD::SETULT: + case ISD::SETULE: + case ISD::SETUGT: + case ISD::SETUGE: + // All of the compare-mask comparisons are ordered, but we can switch + // between the two by a double inversion. E.g. ULE == !OGT. + Invert = true; + changeFPCCToARM64CC(getSetCCInverse(CC, false), CondCode, CondCode2); + break; + } +} + static bool isLegalArithImmed(uint64_t C) { // Matches ARM64DAGToDAGISel::SelectArithImmed(). return (C >> 12 == 0) || ((C & 0xFFFULL) == 0 && C >> 24 == 0); @@ -5389,12 +5422,13 @@ SDValue ARM64TargetLowering::LowerVSETCC(SDValue Op, SelectionDAG &DAG) const { // Unfortunately, the mapping of LLVM FP CC's onto ARM64 CC's isn't totally // clean. Some of them require two branches to implement. ARM64CC::CondCode CC1, CC2; - changeFPCCToARM64CC(CC, CC1, CC2); + bool ShouldInvert; + changeVectorFPCCToARM64CC(CC, CC1, CC2, ShouldInvert); bool NoNaNs = getTargetMachine().Options.NoNaNsFPMath; - SDValue Cmp1 = + SDValue Cmp = EmitVectorComparison(LHS, RHS, CC1, NoNaNs, Op.getValueType(), dl, DAG); - if (!Cmp1.getNode()) + if (!Cmp.getNode()) return SDValue(); if (CC2 != ARM64CC::AL) { @@ -5403,10 +5437,13 @@ SDValue ARM64TargetLowering::LowerVSETCC(SDValue Op, SelectionDAG &DAG) const { if (!Cmp2.getNode()) return SDValue(); - return DAG.getNode(ISD::OR, dl, Cmp1.getValueType(), Cmp1, Cmp2); + Cmp = DAG.getNode(ISD::OR, dl, Cmp.getValueType(), Cmp, Cmp2); } - return Cmp1; + if (ShouldInvert) + return Cmp = DAG.getNOT(dl, Cmp, Cmp.getValueType()); + + return Cmp; } /// getTgtMemIntrinsic - Represent NEON load and store intrinsics as |