6
6
//
7
7
// ===----------------------------------------------------------------------===//
8
8
//
9
- // Replaces instructions to LLVM vector intrinsics (i.e., the frem instruction
10
- // or calls to LLVM intrinsics with vector operands) with matching calls to
11
- // functions from a vector library (e.g., libmvec, SVML) according to
12
- // TargetLibraryInfo.
9
+ // Replaces LLVM IR instructions with vector operands (i.e., the frem
10
+ // instruction or calls to LLVM intrinsics) with matching calls to functions
11
+ // from a vector library (e.g libmvec, SVML) using TargetLibraryInfo interface
13
12
//
14
13
// ===----------------------------------------------------------------------===//
15
14
@@ -70,7 +69,7 @@ Function *getTLIFunction(Module *M, FunctionType *VectorFTy,
70
69
return TLIFunc;
71
70
}
72
71
73
- // / Replace the Instruction \p I with a call to the corresponding function from
72
+ // / Replace the instruction \p I with a call to the corresponding function from
74
73
// / the vector library ( \p TLIVecFunc ).
75
74
static void replaceWithTLIFunction (Instruction &I, VFInfo &Info,
76
75
Function *TLIVecFunc) {
@@ -84,7 +83,7 @@ static void replaceWithTLIFunction(Instruction &I, VFInfo &Info,
84
83
Constant::getAllOnesValue (MaskTy));
85
84
}
86
85
87
- // Preserve the operand bundles for CallInsts .
86
+ // If it is a call instruction, preserve the operand bundles.
88
87
SmallVector<OperandBundleDef, 1 > OpBundles;
89
88
if (CI)
90
89
CI->getOperandBundlesAsDefs (OpBundles);
@@ -98,65 +97,63 @@ static void replaceWithTLIFunction(Instruction &I, VFInfo &Info,
98
97
99
98
// / Returns true when successfully replaced \p I with a suitable function taking
100
99
// / vector arguments, based on available mappings in the \p TLI. Currently only
101
- // / works when \p I is a call to vectorized intrinsic or the frem Instruction .
100
+ // / works when \p I is a call to vectorized intrinsic or the frem instruction .
102
101
static bool replaceWithCallToVeclib (const TargetLibraryInfo &TLI,
103
102
Instruction &I) {
104
103
std::string ScalarName;
105
- ElementCount VF = ElementCount::getFixed (0 );
104
+ ElementCount EC = ElementCount::getFixed (0 );
106
105
CallInst *CI = dyn_cast<CallInst>(&I);
107
106
SmallVector<Type *, 8 > ScalarArgTypes;
107
+ // Compute the argument types of the corresponding scalar call, the scalar
108
+ // function name, and EC. For CI, it additionally checks if in the vector
109
+ // call, all vector operands have the same EC.
108
110
if (CI) {
109
111
Intrinsic::ID IID = Intrinsic::not_intrinsic;
110
112
IID = CI->getCalledFunction ()->getIntrinsicID ();
111
- // Compute arguments types of the corresponding scalar call. Additionally
112
- // checks if in the vector call, all vector operands have the same EC.
113
- for (auto Arg : enumerate(CI ? CI->args () : I.operands ())) {
113
+ for (auto Arg : enumerate(CI->args ())) {
114
114
auto *ArgTy = Arg.value ()->getType ();
115
- if (CI && isVectorIntrinsicWithScalarOpAtArg (IID, Arg.index ())) {
115
+ if (isVectorIntrinsicWithScalarOpAtArg (IID, Arg.index ())) {
116
116
ScalarArgTypes.push_back (ArgTy);
117
- } else {
118
- auto *VectorArgTy = dyn_cast<VectorType>(ArgTy);
119
- // We are expecting only VectorTypes, as:
120
- // - with a CallInst, scalar operands are handled earlier
121
- // - with the frem Instruction, both operands must be vectors.
122
- if (!VectorArgTy)
123
- return false ;
124
- ScalarArgTypes.push_back (ArgTy->getScalarType ());
117
+ } else if (auto *VectorArgTy = dyn_cast<VectorType>(ArgTy)) {
118
+ ScalarArgTypes.push_back (VectorArgTy->getElementType ());
125
119
// Disallow vector arguments with different VFs. When processing the
126
120
// first vector argument, store it's VF, and for the rest ensure that
127
121
// they match it.
128
- if (VF .isZero ())
129
- VF = VectorArgTy->getElementCount ();
130
- else if (VF != VectorArgTy->getElementCount ())
122
+ if (EC .isZero ())
123
+ EC = VectorArgTy->getElementCount ();
124
+ else if (EC != VectorArgTy->getElementCount ())
131
125
return false ;
132
- }
126
+ } else
127
+ // Exit when it is supposed to be a vector argument but it isn't.
128
+ return false ;
133
129
}
134
130
// Try to reconstruct the name for the scalar version of the instruction,
135
131
// using scalar argument types.
136
132
ScalarName = Intrinsic::isOverloaded (IID)
137
133
? Intrinsic::getName (IID, ScalarArgTypes, I.getModule ())
138
134
: Intrinsic::getName (IID).str ();
139
135
} else {
136
+ assert (I.getType ()->isVectorTy () && " Instruction must use vectors" );
140
137
LibFunc Func;
141
138
auto *ScalarTy = I.getType ()->getScalarType ();
142
139
if (!TLI.getLibFunc (I.getOpcode (), ScalarTy, Func))
143
140
return false ;
144
141
ScalarName = TLI.getName (Func);
145
142
ScalarArgTypes = {ScalarTy, ScalarTy};
146
143
if (auto *VTy = dyn_cast<VectorType>(I.getType ()))
147
- VF = VTy->getElementCount ();
144
+ EC = VTy->getElementCount ();
148
145
}
149
146
150
147
// Try to find the mapping for the scalar version of this intrinsic and the
151
148
// exact vector width of the call operands in the TargetLibraryInfo. First,
152
149
// check with a non-masked variant, and if that fails try with a masked one.
153
150
const VecDesc *VD =
154
- TLI.getVectorMappingInfo (ScalarName, VF , /* Masked*/ false );
155
- if (!VD && !(VD = TLI.getVectorMappingInfo (ScalarName, VF , /* Masked*/ true )))
151
+ TLI.getVectorMappingInfo (ScalarName, EC , /* Masked*/ false );
152
+ if (!VD && !(VD = TLI.getVectorMappingInfo (ScalarName, EC , /* Masked*/ true )))
156
153
return false ;
157
154
158
155
LLVM_DEBUG (dbgs () << DEBUG_TYPE << " : Found TLI mapping from: `" << ScalarName
159
- << " ` and vector width " << VF << " to: `"
156
+ << " ` and vector width " << EC << " to: `"
160
157
<< VD->getVectorFnName () << " `.\n " );
161
158
162
159
// Replace the call to the intrinsic with a call to the vector library
@@ -183,16 +180,16 @@ static bool replaceWithCallToVeclib(const TargetLibraryInfo &TLI,
183
180
return true ;
184
181
}
185
182
186
- // / Supported Instructions \p I are either frem or CallInsts to Intrinsics .
183
+ // / Supported instructions \p I are either frem or CallInsts to intrinsics .
187
184
static bool isSupportedInstruction (Instruction *I) {
188
185
if (auto *CI = dyn_cast<CallInst>(I)) {
189
- if (! CI->getCalledFunction () ||
190
- CI->getCalledFunction ()->getIntrinsicID () = = Intrinsic::not_intrinsic)
191
- return false ;
192
- } else if (I->getOpcode () != Instruction::FRem)
193
- return false ;
186
+ if (CI->getCalledFunction () &&
187
+ CI->getCalledFunction ()->getIntrinsicID () ! = Intrinsic::not_intrinsic)
188
+ return true ;
189
+ } else if (I->getOpcode () == Instruction::FRem && I-> getType ()-> isVectorTy () )
190
+ return true ;
194
191
195
- return true ;
192
+ return false ;
196
193
}
197
194
198
195
static bool runImpl (const TargetLibraryInfo &TLI, Function &F) {
0 commit comments