|
13 | 13 | #include "llvm/ADT/STLExtras.h"
|
14 | 14 | #include "llvm/ADT/SetVector.h"
|
15 | 15 | #include "llvm/ADT/SmallBitVector.h"
|
| 16 | +#include "llvm/ADT/SmallVector.h" |
16 | 17 | #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
|
17 | 18 | #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
|
18 | 19 | #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
|
|
26 | 27 | #include "llvm/CodeGen/MachineDominators.h"
|
27 | 28 | #include "llvm/CodeGen/MachineFunction.h"
|
28 | 29 | #include "llvm/CodeGen/MachineInstr.h"
|
| 30 | +#include "llvm/CodeGen/MachineInstrBuilder.h" |
29 | 31 | #include "llvm/CodeGen/MachineMemOperand.h"
|
30 | 32 | #include "llvm/CodeGen/MachineRegisterInfo.h"
|
31 | 33 | #include "llvm/CodeGen/RegisterBankInfo.h"
|
@@ -2147,6 +2149,80 @@ static Register peekThroughBitcast(Register Reg,
|
2147 | 2149 | return Reg;
|
2148 | 2150 | }
|
2149 | 2151 |
|
| 2152 | +bool CombinerHelper::matchCombineShuffleVectorBuildVector( |
| 2153 | + MachineInstr &MI, SmallVectorImpl<Register> &Operands) { |
| 2154 | + assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR && |
| 2155 | + "Expected a shuffle vector"); |
| 2156 | + auto &ShuffleVector = cast<GShuffleVector>(MI); |
| 2157 | + Register SrcReg1 = peekThroughBitcast(ShuffleVector.getSourceReg(0), MRI); |
| 2158 | + Register SrcReg2 = peekThroughBitcast(ShuffleVector.getSourceReg(1), MRI); |
| 2159 | + |
| 2160 | + // Check if the Source registers are either merges or implicit definitions |
| 2161 | + auto *SrcInstr1 = getOpcodeDef<GBuildVector>(SrcReg1, MRI); |
| 2162 | + auto *SrcInstr2 = getOpcodeDef<GBuildVector>(SrcReg2, MRI); |
| 2163 | + auto *IsUndef1 = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, SrcReg1, MRI); |
| 2164 | + auto *IsUndef2 = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, SrcReg2, MRI); |
| 2165 | + |
| 2166 | + // Our inputs need to be either be build vectors or undefined, register inputs |
| 2167 | + // break this optimization. You could maybe do something clever were you |
| 2168 | + // concatenate vectors to save half a build vector. |
| 2169 | + if ((!SrcInstr1 && !IsUndef1) || (!SrcInstr2 && !IsUndef2)) |
| 2170 | + return false; |
| 2171 | + |
| 2172 | + if (IsUndef1 && IsUndef2) |
| 2173 | + return true; |
| 2174 | + |
| 2175 | + Register UndefReg; |
| 2176 | + if (SrcInstr1 || SrcInstr2) |
| 2177 | + UndefReg = MRI.createGenericVirtualRegister(MRI.getType(SrcReg1)); |
| 2178 | + |
| 2179 | + // Since our inputs to shufflevector must be of the same size, we can reuse |
| 2180 | + // the size of the defined register. |
| 2181 | + const unsigned NumElements = (SrcInstr1 != 0) ? SrcInstr1->getNumSources() |
| 2182 | + : SrcInstr2->getNumSources(); |
| 2183 | + for (unsigned Idx = 0; Idx < NumElements; ++Idx) { |
| 2184 | + const Register Elt = |
| 2185 | + (SrcInstr1 != 0) ? SrcInstr1->getSourceReg(Idx) : UndefReg; |
| 2186 | + Operands.push_back(Elt); |
| 2187 | + } |
| 2188 | + |
| 2189 | + for (unsigned Idx = 0; Idx < NumElements; ++Idx) { |
| 2190 | + const Register Elt = |
| 2191 | + (SrcInstr2 != 0) ? SrcInstr2->getSourceReg(Idx) : UndefReg; |
| 2192 | + Operands.push_back(Elt); |
| 2193 | + } |
| 2194 | + |
| 2195 | + return true; |
| 2196 | +} |
| 2197 | + |
| 2198 | +void CombinerHelper::applyCombineShuffleVectorBuildVector( |
| 2199 | + MachineInstr &MI, SmallVectorImpl<Register> &Operands) { |
| 2200 | + assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR && |
| 2201 | + "Expected a shuffle vector"); |
| 2202 | + auto &ShuffleVector = cast<GShuffleVector>(MI); |
| 2203 | + Register SrcReg1 = peekThroughBitcast(ShuffleVector.getSourceReg(0), MRI); |
| 2204 | + Register SrcReg2 = peekThroughBitcast(ShuffleVector.getSourceReg(1), MRI); |
| 2205 | + |
| 2206 | + // Check if the Source registers are either merges or implicit definitions |
| 2207 | + auto *IsUndef1 = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, SrcReg1, MRI); |
| 2208 | + auto *IsUndef2 = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, SrcReg2, MRI); |
| 2209 | + |
| 2210 | + // If they're both undefined, we will just return an undefined as well. |
| 2211 | + if (IsUndef1 && IsUndef2) { |
| 2212 | + Builder.buildUndef(ShuffleVector.getReg(0)); |
| 2213 | + MI.eraseFromParent(); |
| 2214 | + return; |
| 2215 | + } |
| 2216 | + |
| 2217 | + const ArrayRef<int> ShiftMask = MI.getOperand(3).getShuffleMask(); |
| 2218 | + SmallVector<Register, 8> Arguments; |
| 2219 | + for (int Index : ShiftMask) |
| 2220 | + Arguments.push_back(Operands[Index]); |
| 2221 | + |
| 2222 | + Builder.buildBuildVector(ShuffleVector.getOperand(0), Arguments); |
| 2223 | + MI.eraseFromParent(); |
| 2224 | +} |
| 2225 | + |
2150 | 2226 | bool CombinerHelper::matchCombineUnmergeMergeToPlainValues(
|
2151 | 2227 | MachineInstr &MI, SmallVectorImpl<Register> &Operands) {
|
2152 | 2228 | assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
|
|
0 commit comments