Skip to content

Commit d9559aa

Browse files
[TLI] ReplaceWithVecLib: drop Instruction support
Refactor the pass to only support IntrinsicInst calls. ReplaceWithVecLib used to support instructions, as AArch64 was using this pass to replace a vectorized frem instruction to the fmod vector library call (through TLI). As this replacement is now done by the codegen (#83859), there is no need for this pass to support instructions. Additionally, removed 'frem' tests from: - AArch64/replace-with-veclib-armpl.ll - AArch64/replace-with-veclib-sleef-scalable.ll - AArch64/replace-with-veclib-sleef.l Such testing is done at codegen level: - #83859
1 parent a934ddc commit d9559aa

File tree

5 files changed

+75
-184
lines changed

5 files changed

+75
-184
lines changed

llvm/lib/CodeGen/ReplaceWithVeclib.cpp

Lines changed: 71 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88
//
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.
9+
// Replaces calls to LLVM Intrinsics with matching calls to functions from a
10+
// vector library (e.g libmvec, SVML) using TargetLibraryInfo interface.
1211
//
1312
//===----------------------------------------------------------------------===//
1413

@@ -25,6 +24,7 @@
2524
#include "llvm/IR/DerivedTypes.h"
2625
#include "llvm/IR/IRBuilder.h"
2726
#include "llvm/IR/InstIterator.h"
27+
#include "llvm/IR/IntrinsicInst.h"
2828
#include "llvm/IR/VFABIDemangler.h"
2929
#include "llvm/Support/TypeSize.h"
3030
#include "llvm/Transforms/Utils/ModuleUtils.h"
@@ -70,84 +70,68 @@ Function *getTLIFunction(Module *M, FunctionType *VectorFTy,
7070
return TLIFunc;
7171
}
7272

73-
/// Replace the instruction \p I with a call to the corresponding function from
74-
/// the vector library (\p TLIVecFunc).
75-
static void replaceWithTLIFunction(Instruction &I, VFInfo &Info,
73+
/// Replace the intrinsic call \p II to \p TLIVecFunc, which is the
74+
/// corresponding function from the vector library.
75+
static void replaceWithTLIFunction(IntrinsicInst *II, VFInfo &Info,
7676
Function *TLIVecFunc) {
77-
IRBuilder<> IRBuilder(&I);
78-
auto *CI = dyn_cast<CallInst>(&I);
79-
SmallVector<Value *> Args(CI ? CI->args() : I.operands());
77+
IRBuilder<> IRBuilder(II);
78+
SmallVector<Value *> Args(II->args());
8079
if (auto OptMaskpos = Info.getParamIndexForOptionalMask()) {
8180
auto *MaskTy =
82-
VectorType::get(Type::getInt1Ty(I.getContext()), Info.Shape.VF);
81+
VectorType::get(Type::getInt1Ty(II->getContext()), Info.Shape.VF);
8382
Args.insert(Args.begin() + OptMaskpos.value(),
8483
Constant::getAllOnesValue(MaskTy));
8584
}
8685

87-
// If it is a call instruction, preserve the operand bundles.
86+
// Preserve the operand bundles.
8887
SmallVector<OperandBundleDef, 1> OpBundles;
89-
if (CI)
90-
CI->getOperandBundlesAsDefs(OpBundles);
88+
II->getOperandBundlesAsDefs(OpBundles);
9189

9290
auto *Replacement = IRBuilder.CreateCall(TLIVecFunc, Args, OpBundles);
93-
I.replaceAllUsesWith(Replacement);
91+
II->replaceAllUsesWith(Replacement);
9492
// Preserve fast math flags for FP math.
9593
if (isa<FPMathOperator>(Replacement))
96-
Replacement->copyFastMathFlags(&I);
94+
Replacement->copyFastMathFlags(II);
9795
}
9896

99-
/// Returns true when successfully replaced \p I with a suitable function taking
100-
/// 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.
97+
/// Returns true when successfully replaced \p II, which is a call to a
98+
/// vectorized intrinsic, with a suitable function taking vector arguments,
99+
/// based on available mappings in the \p TLI.
102100
static bool replaceWithCallToVeclib(const TargetLibraryInfo &TLI,
103-
Instruction &I) {
101+
IntrinsicInst *II) {
102+
assert(II != nullptr && "Intrinsic cannot be null");
104103
// At the moment VFABI assumes the return type is always widened unless it is
105104
// a void type.
106-
auto *VTy = dyn_cast<VectorType>(I.getType());
105+
auto *VTy = dyn_cast<VectorType>(II->getType());
107106
ElementCount EC(VTy ? VTy->getElementCount() : ElementCount::getFixed(0));
108-
109-
// Compute the argument types of the corresponding scalar call and the scalar
110-
// function name. For calls, it additionally finds the function to replace
111-
// and checks that all vector operands match the previously found EC.
107+
// Compute the argument types of the corresponding scalar call and check that
108+
// all vector operands match the previously found EC.
112109
SmallVector<Type *, 8> ScalarArgTypes;
113-
std::string ScalarName;
114-
Function *FuncToReplace = nullptr;
115-
auto *CI = dyn_cast<CallInst>(&I);
116-
if (CI) {
117-
FuncToReplace = CI->getCalledFunction();
118-
Intrinsic::ID IID = FuncToReplace->getIntrinsicID();
119-
assert(IID != Intrinsic::not_intrinsic && "Not an intrinsic");
120-
for (auto Arg : enumerate(CI->args())) {
121-
auto *ArgTy = Arg.value()->getType();
122-
if (isVectorIntrinsicWithScalarOpAtArg(IID, Arg.index())) {
123-
ScalarArgTypes.push_back(ArgTy);
124-
} else if (auto *VectorArgTy = dyn_cast<VectorType>(ArgTy)) {
125-
ScalarArgTypes.push_back(VectorArgTy->getElementType());
126-
// When return type is void, set EC to the first vector argument, and
127-
// disallow vector arguments with different ECs.
128-
if (EC.isZero())
129-
EC = VectorArgTy->getElementCount();
130-
else if (EC != VectorArgTy->getElementCount())
131-
return false;
132-
} else
133-
// Exit when it is supposed to be a vector argument but it isn't.
110+
Intrinsic::ID IID = II->getIntrinsicID();
111+
for (auto Arg : enumerate(II->args())) {
112+
auto *ArgTy = Arg.value()->getType();
113+
if (isVectorIntrinsicWithScalarOpAtArg(IID, Arg.index())) {
114+
ScalarArgTypes.push_back(ArgTy);
115+
} else if (auto *VectorArgTy = dyn_cast<VectorType>(ArgTy)) {
116+
ScalarArgTypes.push_back(VectorArgTy->getElementType());
117+
// When return type is void, set EC to the first vector argument, and
118+
// disallow vector arguments with different ECs.
119+
if (EC.isZero())
120+
EC = VectorArgTy->getElementCount();
121+
else if (EC != VectorArgTy->getElementCount())
134122
return false;
135-
}
136-
// Try to reconstruct the name for the scalar version of the instruction,
137-
// using scalar argument types.
138-
ScalarName = Intrinsic::isOverloaded(IID)
139-
? Intrinsic::getName(IID, ScalarArgTypes, I.getModule())
140-
: Intrinsic::getName(IID).str();
141-
} else {
142-
assert(VTy && "Return type must be a vector");
143-
auto *ScalarTy = VTy->getScalarType();
144-
LibFunc Func;
145-
if (!TLI.getLibFunc(I.getOpcode(), ScalarTy, Func))
123+
} else
124+
// Exit when it is supposed to be a vector argument but it isn't.
146125
return false;
147-
ScalarName = TLI.getName(Func);
148-
ScalarArgTypes = {ScalarTy, ScalarTy};
149126
}
150127

128+
// Try to reconstruct the name for the scalar version of the instruction,
129+
// using scalar argument types.
130+
std::string ScalarName =
131+
Intrinsic::isOverloaded(IID)
132+
? Intrinsic::getName(IID, ScalarArgTypes, II->getModule())
133+
: Intrinsic::getName(IID).str();
134+
151135
// Try to find the mapping for the scalar version of this intrinsic and the
152136
// exact vector width of the call operands in the TargetLibraryInfo. First,
153137
// check with a non-masked variant, and if that fails try with a masked one.
@@ -162,7 +146,7 @@ static bool replaceWithCallToVeclib(const TargetLibraryInfo &TLI,
162146

163147
// Replace the call to the intrinsic with a call to the vector library
164148
// function.
165-
Type *ScalarRetTy = I.getType()->getScalarType();
149+
Type *ScalarRetTy = II->getType()->getScalarType();
166150
FunctionType *ScalarFTy =
167151
FunctionType::get(ScalarRetTy, ScalarArgTypes, /*isVarArg*/ false);
168152
const std::string MangledName = VD->getVectorFunctionABIVariantString();
@@ -174,68 +158,52 @@ static bool replaceWithCallToVeclib(const TargetLibraryInfo &TLI,
174158
// specification when being created, this is why we need to add extra check to
175159
// make sure that the operands of the vector function obtained via VFABI match
176160
// the operands of the original vector instruction.
177-
if (CI) {
178-
for (auto &VFParam : OptInfo->Shape.Parameters) {
179-
if (VFParam.ParamKind == VFParamKind::GlobalPredicate)
180-
continue;
161+
for (auto &VFParam : OptInfo->Shape.Parameters) {
162+
if (VFParam.ParamKind == VFParamKind::GlobalPredicate)
163+
continue;
181164

182-
// tryDemangleForVFABI must return valid ParamPos, otherwise it could be
183-
// a bug in the VFABI parser.
184-
assert(VFParam.ParamPos < CI->arg_size() &&
185-
"ParamPos has invalid range.");
186-
Type *OrigTy = CI->getArgOperand(VFParam.ParamPos)->getType();
187-
if (OrigTy->isVectorTy() != (VFParam.ParamKind == VFParamKind::Vector)) {
188-
LLVM_DEBUG(dbgs() << DEBUG_TYPE << ": Will not replace: " << ScalarName
189-
<< ". Wrong type at index " << VFParam.ParamPos
190-
<< ": " << *OrigTy << "\n");
191-
return false;
192-
}
165+
// tryDemangleForVFABI must return valid ParamPos, otherwise it could be
166+
// a bug in the VFABI parser.
167+
assert(VFParam.ParamPos < II->arg_size() && "ParamPos has invalid range");
168+
Type *OrigTy = II->getArgOperand(VFParam.ParamPos)->getType();
169+
if (OrigTy->isVectorTy() != (VFParam.ParamKind == VFParamKind::Vector)) {
170+
LLVM_DEBUG(dbgs() << DEBUG_TYPE << ": Will not replace: " << ScalarName
171+
<< ". Wrong type at index " << VFParam.ParamPos << ": "
172+
<< *OrigTy << "\n");
173+
return false;
193174
}
194175
}
195176

196177
FunctionType *VectorFTy = VFABI::createFunctionType(*OptInfo, ScalarFTy);
197178
if (!VectorFTy)
198179
return false;
199180

200-
Function *TLIFunc = getTLIFunction(I.getModule(), VectorFTy,
201-
VD->getVectorFnName(), FuncToReplace);
202-
203-
replaceWithTLIFunction(I, *OptInfo, TLIFunc);
181+
Function *TLIFunc =
182+
getTLIFunction(II->getModule(), VectorFTy, VD->getVectorFnName(),
183+
II->getCalledFunction());
184+
replaceWithTLIFunction(II, *OptInfo, TLIFunc);
204185
LLVM_DEBUG(dbgs() << DEBUG_TYPE << ": Replaced call to `" << ScalarName
205186
<< "` with call to `" << TLIFunc->getName() << "`.\n");
206187
++NumCallsReplaced;
207188
return true;
208189
}
209190

210-
/// Supported instruction \p I must be a vectorized frem or a call to an
211-
/// intrinsic that returns either void or a vector.
212-
static bool isSupportedInstruction(Instruction *I) {
213-
Type *Ty = I->getType();
214-
if (auto *CI = dyn_cast<CallInst>(I))
215-
return (Ty->isVectorTy() || Ty->isVoidTy()) && CI->getCalledFunction() &&
216-
CI->getCalledFunction()->getIntrinsicID() !=
217-
Intrinsic::not_intrinsic;
218-
if (I->getOpcode() == Instruction::FRem && Ty->isVectorTy())
219-
return true;
220-
return false;
221-
}
222-
223191
static bool runImpl(const TargetLibraryInfo &TLI, Function &F) {
224-
bool Changed = false;
225192
SmallVector<Instruction *> ReplacedCalls;
226193
for (auto &I : instructions(F)) {
227-
if (!isSupportedInstruction(&I))
228-
continue;
229-
if (replaceWithCallToVeclib(TLI, I)) {
230-
ReplacedCalls.push_back(&I);
231-
Changed = true;
194+
// Process only intrinsic calls that return void or a vector.
195+
if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
196+
if (!II->getType()->isVectorTy() && !II->getType()->isVoidTy())
197+
continue;
198+
199+
if (replaceWithCallToVeclib(TLI, II))
200+
ReplacedCalls.push_back(&I);
232201
}
233202
}
234-
// Erase the calls to the intrinsics that have been replaced
235-
// with calls to the vector library.
236-
for (auto *CI : ReplacedCalls)
237-
CI->eraseFromParent();
238-
return Changed;
203+
// Erase any intrinsic calls that were replaced with vector library calls.
204+
for (auto *I : ReplacedCalls)
205+
I->eraseFromParent();
206+
return !ReplacedCalls.empty();
239207
}
240208

241209
////////////////////////////////////////////////////////////////////////////////
@@ -246,7 +214,7 @@ PreservedAnalyses ReplaceWithVeclib::run(Function &F,
246214
const TargetLibraryInfo &TLI = AM.getResult<TargetLibraryAnalysis>(F);
247215
auto Changed = runImpl(TLI, F);
248216
if (Changed) {
249-
LLVM_DEBUG(dbgs() << "Instructions replaced with vector libraries: "
217+
LLVM_DEBUG(dbgs() << "Intrinsic calls replaced with vector libraries: "
250218
<< NumCallsReplaced << "\n");
251219

252220
PreservedAnalyses PA;

llvm/test/CodeGen/AArch64/replace-with-veclib-armpl.ll

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ declare <vscale x 2 x double> @llvm.cos.nxv2f64(<vscale x 2 x double>)
1515
declare <vscale x 4 x float> @llvm.cos.nxv4f32(<vscale x 4 x float>)
1616

1717
;.
18-
; CHECK: @llvm.compiler.used = appending global [36 x ptr] [ptr @armpl_vcosq_f64, ptr @armpl_vcosq_f32, ptr @armpl_svcos_f64_x, ptr @armpl_svcos_f32_x, ptr @armpl_vexpq_f64, ptr @armpl_vexpq_f32, ptr @armpl_svexp_f64_x, ptr @armpl_svexp_f32_x, ptr @armpl_vexp10q_f64, ptr @armpl_vexp10q_f32, ptr @armpl_svexp10_f64_x, ptr @armpl_svexp10_f32_x, ptr @armpl_vexp2q_f64, ptr @armpl_vexp2q_f32, ptr @armpl_svexp2_f64_x, ptr @armpl_svexp2_f32_x, ptr @armpl_vlogq_f64, ptr @armpl_vlogq_f32, ptr @armpl_svlog_f64_x, ptr @armpl_svlog_f32_x, ptr @armpl_vlog10q_f64, ptr @armpl_vlog10q_f32, ptr @armpl_svlog10_f64_x, ptr @armpl_svlog10_f32_x, ptr @armpl_vlog2q_f64, ptr @armpl_vlog2q_f32, ptr @armpl_svlog2_f64_x, ptr @armpl_svlog2_f32_x, ptr @armpl_vsinq_f64, ptr @armpl_vsinq_f32, ptr @armpl_svsin_f64_x, ptr @armpl_svsin_f32_x, ptr @armpl_vfmodq_f64, ptr @armpl_vfmodq_f32, ptr @armpl_svfmod_f64_x, ptr @armpl_svfmod_f32_x], section "llvm.metadata"
18+
; CHECK: @llvm.compiler.used = appending global [32 x ptr] [ptr @armpl_vcosq_f64, ptr @armpl_vcosq_f32, ptr @armpl_svcos_f64_x, ptr @armpl_svcos_f32_x, ptr @armpl_vexpq_f64, ptr @armpl_vexpq_f32, ptr @armpl_svexp_f64_x, ptr @armpl_svexp_f32_x, ptr @armpl_vexp10q_f64, ptr @armpl_vexp10q_f32, ptr @armpl_svexp10_f64_x, ptr @armpl_svexp10_f32_x, ptr @armpl_vexp2q_f64, ptr @armpl_vexp2q_f32, ptr @armpl_svexp2_f64_x, ptr @armpl_svexp2_f32_x, ptr @armpl_vlogq_f64, ptr @armpl_vlogq_f32, ptr @armpl_svlog_f64_x, ptr @armpl_svlog_f32_x, ptr @armpl_vlog10q_f64, ptr @armpl_vlog10q_f32, ptr @armpl_svlog10_f64_x, ptr @armpl_svlog10_f32_x, ptr @armpl_vlog2q_f64, ptr @armpl_vlog2q_f32, ptr @armpl_svlog2_f64_x, ptr @armpl_svlog2_f32_x, ptr @armpl_vsinq_f64, ptr @armpl_vsinq_f32, ptr @armpl_svsin_f64_x, ptr @armpl_svsin_f32_x], section "llvm.metadata"
1919
;.
2020
define <2 x double> @llvm_cos_f64(<2 x double> %in) {
2121
; CHECK-LABEL: define <2 x double> @llvm_cos_f64
@@ -424,47 +424,6 @@ define <vscale x 4 x float> @llvm_sin_vscale_f32(<vscale x 4 x float> %in) #0 {
424424
ret <vscale x 4 x float> %1
425425
}
426426

427-
428-
define <2 x double> @frem_f64(<2 x double> %in) {
429-
; CHECK-LABEL: define <2 x double> @frem_f64
430-
; CHECK-SAME: (<2 x double> [[IN:%.*]]) {
431-
; CHECK-NEXT: [[TMP1:%.*]] = call <2 x double> @armpl_vfmodq_f64(<2 x double> [[IN]], <2 x double> [[IN]])
432-
; CHECK-NEXT: ret <2 x double> [[TMP1]]
433-
;
434-
%1= frem <2 x double> %in, %in
435-
ret <2 x double> %1
436-
}
437-
438-
define <4 x float> @frem_f32(<4 x float> %in) {
439-
; CHECK-LABEL: define <4 x float> @frem_f32
440-
; CHECK-SAME: (<4 x float> [[IN:%.*]]) {
441-
; CHECK-NEXT: [[TMP1:%.*]] = call <4 x float> @armpl_vfmodq_f32(<4 x float> [[IN]], <4 x float> [[IN]])
442-
; CHECK-NEXT: ret <4 x float> [[TMP1]]
443-
;
444-
%1= frem <4 x float> %in, %in
445-
ret <4 x float> %1
446-
}
447-
448-
define <vscale x 2 x double> @frem_vscale_f64(<vscale x 2 x double> %in) #0 {
449-
; CHECK-LABEL: define <vscale x 2 x double> @frem_vscale_f64
450-
; CHECK-SAME: (<vscale x 2 x double> [[IN:%.*]]) #[[ATTR1]] {
451-
; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 2 x double> @armpl_svfmod_f64_x(<vscale x 2 x double> [[IN]], <vscale x 2 x double> [[IN]], <vscale x 2 x i1> shufflevector (<vscale x 2 x i1> insertelement (<vscale x 2 x i1> poison, i1 true, i64 0), <vscale x 2 x i1> poison, <vscale x 2 x i32> zeroinitializer))
452-
; CHECK-NEXT: ret <vscale x 2 x double> [[TMP1]]
453-
;
454-
%1= frem <vscale x 2 x double> %in, %in
455-
ret <vscale x 2 x double> %1
456-
}
457-
458-
define <vscale x 4 x float> @frem_vscale_f32(<vscale x 4 x float> %in) #0 {
459-
; CHECK-LABEL: define <vscale x 4 x float> @frem_vscale_f32
460-
; CHECK-SAME: (<vscale x 4 x float> [[IN:%.*]]) #[[ATTR1]] {
461-
; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 4 x float> @armpl_svfmod_f32_x(<vscale x 4 x float> [[IN]], <vscale x 4 x float> [[IN]], <vscale x 4 x i1> shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i64 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer))
462-
; CHECK-NEXT: ret <vscale x 4 x float> [[TMP1]]
463-
;
464-
%1= frem <vscale x 4 x float> %in, %in
465-
ret <vscale x 4 x float> %1
466-
}
467-
468427
attributes #0 = { "target-features"="+sve" }
469428
;.
470429
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

llvm/test/CodeGen/AArch64/replace-with-veclib-sleef-scalable.ll

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
target triple = "aarch64-unknown-linux-gnu"
55

66
;.
7-
; CHECK: @llvm.compiler.used = appending global [18 x ptr] [ptr @_ZGVsMxv_cos, ptr @_ZGVsMxv_cosf, ptr @_ZGVsMxv_exp, ptr @_ZGVsMxv_expf, ptr @_ZGVsMxv_exp10, ptr @_ZGVsMxv_exp10f, ptr @_ZGVsMxv_exp2, ptr @_ZGVsMxv_exp2f, ptr @_ZGVsMxv_log, ptr @_ZGVsMxv_logf, ptr @_ZGVsMxv_log10, ptr @_ZGVsMxv_log10f, ptr @_ZGVsMxv_log2, ptr @_ZGVsMxv_log2f, ptr @_ZGVsMxv_sin, ptr @_ZGVsMxv_sinf, ptr @_ZGVsMxvv_fmod, ptr @_ZGVsMxvv_fmodf], section "llvm.metadata"
7+
; CHECK: @llvm.compiler.used = appending global [16 x ptr] [ptr @_ZGVsMxv_cos, ptr @_ZGVsMxv_cosf, ptr @_ZGVsMxv_exp, ptr @_ZGVsMxv_expf, ptr @_ZGVsMxv_exp10, ptr @_ZGVsMxv_exp10f, ptr @_ZGVsMxv_exp2, ptr @_ZGVsMxv_exp2f, ptr @_ZGVsMxv_log, ptr @_ZGVsMxv_logf, ptr @_ZGVsMxv_log10, ptr @_ZGVsMxv_log10f, ptr @_ZGVsMxv_log2, ptr @_ZGVsMxv_log2f, ptr @_ZGVsMxv_sin, ptr @_ZGVsMxv_sinf], section "llvm.metadata"
88
;.
99
define <vscale x 2 x double> @llvm_ceil_vscale_f64(<vscale x 2 x double> %in) {
1010
; CHECK-LABEL: @llvm_ceil_vscale_f64(
@@ -384,24 +384,6 @@ define <vscale x 4 x float> @llvm_trunc_vscale_f32(<vscale x 4 x float> %in) {
384384
ret <vscale x 4 x float> %1
385385
}
386386

387-
define <vscale x 2 x double> @frem_f64(<vscale x 2 x double> %in) {
388-
; CHECK-LABEL: @frem_f64(
389-
; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 2 x double> @_ZGVsMxvv_fmod(<vscale x 2 x double> [[IN:%.*]], <vscale x 2 x double> [[IN]], <vscale x 2 x i1> shufflevector (<vscale x 2 x i1> insertelement (<vscale x 2 x i1> poison, i1 true, i64 0), <vscale x 2 x i1> poison, <vscale x 2 x i32> zeroinitializer))
390-
; CHECK-NEXT: ret <vscale x 2 x double> [[TMP1]]
391-
;
392-
%1= frem <vscale x 2 x double> %in, %in
393-
ret <vscale x 2 x double> %1
394-
}
395-
396-
define <vscale x 4 x float> @frem_f32(<vscale x 4 x float> %in) {
397-
; CHECK-LABEL: @frem_f32(
398-
; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 4 x float> @_ZGVsMxvv_fmodf(<vscale x 4 x float> [[IN:%.*]], <vscale x 4 x float> [[IN]], <vscale x 4 x i1> shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i64 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer))
399-
; CHECK-NEXT: ret <vscale x 4 x float> [[TMP1]]
400-
;
401-
%1= frem <vscale x 4 x float> %in, %in
402-
ret <vscale x 4 x float> %1
403-
}
404-
405387
declare <vscale x 2 x double> @llvm.ceil.nxv2f64(<vscale x 2 x double>)
406388
declare <vscale x 4 x float> @llvm.ceil.nxv4f32(<vscale x 4 x float>)
407389
declare <vscale x 2 x double> @llvm.copysign.nxv2f64(<vscale x 2 x double>, <vscale x 2 x double>)

0 commit comments

Comments
 (0)