@@ -1272,6 +1272,9 @@ static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn,
1272
1272
// nvvm.bitcast.{f2i,i2f,ll2d,d2ll}
1273
1273
Expand =
1274
1274
Name == " f2i" || Name == " i2f" || Name == " ll2d" || Name == " d2ll" ;
1275
+ else if (Name.consume_front (" rotate." ))
1276
+ // nvvm.rotate.{b32,b64,right.b64}
1277
+ Expand = Name == " b32" || Name == " b64" || Name == " right.b64" ;
1275
1278
else
1276
1279
Expand = false ;
1277
1280
@@ -2258,6 +2261,108 @@ void llvm::UpgradeInlineAsmString(std::string *AsmStr) {
2258
2261
}
2259
2262
}
2260
2263
2264
+ static Value *upgradeNVVMIntrinsicCall (StringRef Name, CallBase *CI,
2265
+ Function *F, IRBuilder<> &Builder) {
2266
+ Value *Rep = nullptr ;
2267
+
2268
+ if (Name == " abs.i" || Name == " abs.ll" ) {
2269
+ Value *Arg = CI->getArgOperand (0 );
2270
+ Value *Neg = Builder.CreateNeg (Arg, " neg" );
2271
+ Value *Cmp = Builder.CreateICmpSGE (
2272
+ Arg, llvm::Constant::getNullValue (Arg->getType ()), " abs.cond" );
2273
+ Rep = Builder.CreateSelect (Cmp, Arg, Neg, " abs" );
2274
+ } else if (Name.starts_with (" atomic.load.add.f32.p" ) ||
2275
+ Name.starts_with (" atomic.load.add.f64.p" )) {
2276
+ Value *Ptr = CI->getArgOperand (0 );
2277
+ Value *Val = CI->getArgOperand (1 );
2278
+ Rep = Builder.CreateAtomicRMW (AtomicRMWInst::FAdd, Ptr, Val, MaybeAlign (),
2279
+ AtomicOrdering::SequentiallyConsistent);
2280
+ } else if (Name.consume_front (" max." ) &&
2281
+ (Name == " s" || Name == " i" || Name == " ll" || Name == " us" ||
2282
+ Name == " ui" || Name == " ull" )) {
2283
+ Value *Arg0 = CI->getArgOperand (0 );
2284
+ Value *Arg1 = CI->getArgOperand (1 );
2285
+ Value *Cmp = Name.starts_with (" u" )
2286
+ ? Builder.CreateICmpUGE (Arg0, Arg1, " max.cond" )
2287
+ : Builder.CreateICmpSGE (Arg0, Arg1, " max.cond" );
2288
+ Rep = Builder.CreateSelect (Cmp, Arg0, Arg1, " max" );
2289
+ } else if (Name.consume_front (" min." ) &&
2290
+ (Name == " s" || Name == " i" || Name == " ll" || Name == " us" ||
2291
+ Name == " ui" || Name == " ull" )) {
2292
+ Value *Arg0 = CI->getArgOperand (0 );
2293
+ Value *Arg1 = CI->getArgOperand (1 );
2294
+ Value *Cmp = Name.starts_with (" u" )
2295
+ ? Builder.CreateICmpULE (Arg0, Arg1, " min.cond" )
2296
+ : Builder.CreateICmpSLE (Arg0, Arg1, " min.cond" );
2297
+ Rep = Builder.CreateSelect (Cmp, Arg0, Arg1, " min" );
2298
+ } else if (Name == " clz.ll" ) {
2299
+ // llvm.nvvm.clz.ll returns an i32, but llvm.ctlz.i64 returns an i64.
2300
+ Value *Arg = CI->getArgOperand (0 );
2301
+ Value *Ctlz = Builder.CreateCall (
2302
+ Intrinsic::getDeclaration (F->getParent (), Intrinsic::ctlz,
2303
+ {Arg->getType ()}),
2304
+ {Arg, Builder.getFalse ()}, " ctlz" );
2305
+ Rep = Builder.CreateTrunc (Ctlz, Builder.getInt32Ty (), " ctlz.trunc" );
2306
+ } else if (Name == " popc.ll" ) {
2307
+ // llvm.nvvm.popc.ll returns an i32, but llvm.ctpop.i64 returns an
2308
+ // i64.
2309
+ Value *Arg = CI->getArgOperand (0 );
2310
+ Value *Popc = Builder.CreateCall (
2311
+ Intrinsic::getDeclaration (F->getParent (), Intrinsic::ctpop,
2312
+ {Arg->getType ()}),
2313
+ Arg, " ctpop" );
2314
+ Rep = Builder.CreateTrunc (Popc, Builder.getInt32Ty (), " ctpop.trunc" );
2315
+ } else if (Name == " h2f" ) {
2316
+ Rep = Builder.CreateCall (
2317
+ Intrinsic::getDeclaration (F->getParent (), Intrinsic::convert_from_fp16,
2318
+ {Builder.getFloatTy ()}),
2319
+ CI->getArgOperand (0 ), " h2f" );
2320
+ } else if (Name.consume_front (" bitcast." ) &&
2321
+ (Name == " f2i" || Name == " i2f" || Name == " ll2d" ||
2322
+ Name == " d2ll" )) {
2323
+ Rep = Builder.CreateBitCast (CI->getArgOperand (0 ), CI->getType ());
2324
+ } else if (Name == " rotate.b32" ) {
2325
+ Value *Arg = CI->getOperand (0 );
2326
+ Value *ShiftAmt = CI->getOperand (1 );
2327
+ Rep = Builder.CreateIntrinsic (Builder.getInt32Ty (), Intrinsic::fshl,
2328
+ {Arg, Arg, ShiftAmt});
2329
+ } else if (Name == " rotate.b64" ) {
2330
+ Type *Int64Ty = Builder.getInt64Ty ();
2331
+ Value *Arg = CI->getOperand (0 );
2332
+ Value *ZExtShiftAmt = Builder.CreateZExt (CI->getOperand (1 ), Int64Ty);
2333
+ Rep = Builder.CreateIntrinsic (Int64Ty, Intrinsic::fshl,
2334
+ {Arg, Arg, ZExtShiftAmt});
2335
+ } else if (Name == " rotate.right.b64" ) {
2336
+ Type *Int64Ty = Builder.getInt64Ty ();
2337
+ Value *Arg = CI->getOperand (0 );
2338
+ Value *ZExtShiftAmt = Builder.CreateZExt (CI->getOperand (1 ), Int64Ty);
2339
+ Rep = Builder.CreateIntrinsic (Int64Ty, Intrinsic::fshr,
2340
+ {Arg, Arg, ZExtShiftAmt});
2341
+ } else {
2342
+ Intrinsic::ID IID = shouldUpgradeNVPTXBF16Intrinsic (Name);
2343
+ if (IID != Intrinsic::not_intrinsic &&
2344
+ !F->getReturnType ()->getScalarType ()->isBFloatTy ()) {
2345
+ rename (F);
2346
+ Function *NewFn = Intrinsic::getDeclaration (F->getParent (), IID);
2347
+ SmallVector<Value *, 2 > Args;
2348
+ for (size_t I = 0 ; I < NewFn->arg_size (); ++I) {
2349
+ Value *Arg = CI->getArgOperand (I);
2350
+ Type *OldType = Arg->getType ();
2351
+ Type *NewType = NewFn->getArg (I)->getType ();
2352
+ Args.push_back (
2353
+ (OldType->isIntegerTy () && NewType->getScalarType ()->isBFloatTy ())
2354
+ ? Builder.CreateBitCast (Arg, NewType)
2355
+ : Arg);
2356
+ }
2357
+ Rep = Builder.CreateCall (NewFn, Args);
2358
+ if (F->getReturnType ()->isIntegerTy ())
2359
+ Rep = Builder.CreateBitCast (Rep, F->getReturnType ());
2360
+ }
2361
+ }
2362
+
2363
+ return Rep;
2364
+ }
2365
+
2261
2366
static Value *upgradeX86IntrinsicCall (StringRef Name, CallBase *CI, Function *F,
2262
2367
IRBuilder<> &Builder) {
2263
2368
LLVMContext &C = F->getContext ();
@@ -4208,85 +4313,8 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
4208
4313
4209
4314
if (!IsX86 && Name == " stackprotectorcheck" ) {
4210
4315
Rep = nullptr ;
4211
- } else if (IsNVVM && (Name == " abs.i" || Name == " abs.ll" )) {
4212
- Value *Arg = CI->getArgOperand (0 );
4213
- Value *Neg = Builder.CreateNeg (Arg, " neg" );
4214
- Value *Cmp = Builder.CreateICmpSGE (
4215
- Arg, llvm::Constant::getNullValue (Arg->getType ()), " abs.cond" );
4216
- Rep = Builder.CreateSelect (Cmp, Arg, Neg, " abs" );
4217
- } else if (IsNVVM && (Name.starts_with (" atomic.load.add.f32.p" ) ||
4218
- Name.starts_with (" atomic.load.add.f64.p" ))) {
4219
- Value *Ptr = CI->getArgOperand (0 );
4220
- Value *Val = CI->getArgOperand (1 );
4221
- Rep = Builder.CreateAtomicRMW (AtomicRMWInst::FAdd, Ptr, Val, MaybeAlign (),
4222
- AtomicOrdering::SequentiallyConsistent);
4223
- } else if (IsNVVM && Name.consume_front (" max." ) &&
4224
- (Name == " s" || Name == " i" || Name == " ll" || Name == " us" ||
4225
- Name == " ui" || Name == " ull" )) {
4226
- Value *Arg0 = CI->getArgOperand (0 );
4227
- Value *Arg1 = CI->getArgOperand (1 );
4228
- Value *Cmp = Name.starts_with (" u" )
4229
- ? Builder.CreateICmpUGE (Arg0, Arg1, " max.cond" )
4230
- : Builder.CreateICmpSGE (Arg0, Arg1, " max.cond" );
4231
- Rep = Builder.CreateSelect (Cmp, Arg0, Arg1, " max" );
4232
- } else if (IsNVVM && Name.consume_front (" min." ) &&
4233
- (Name == " s" || Name == " i" || Name == " ll" || Name == " us" ||
4234
- Name == " ui" || Name == " ull" )) {
4235
- Value *Arg0 = CI->getArgOperand (0 );
4236
- Value *Arg1 = CI->getArgOperand (1 );
4237
- Value *Cmp = Name.starts_with (" u" )
4238
- ? Builder.CreateICmpULE (Arg0, Arg1, " min.cond" )
4239
- : Builder.CreateICmpSLE (Arg0, Arg1, " min.cond" );
4240
- Rep = Builder.CreateSelect (Cmp, Arg0, Arg1, " min" );
4241
- } else if (IsNVVM && Name == " clz.ll" ) {
4242
- // llvm.nvvm.clz.ll returns an i32, but llvm.ctlz.i64 returns an i64.
4243
- Value *Arg = CI->getArgOperand (0 );
4244
- Value *Ctlz = Builder.CreateCall (
4245
- Intrinsic::getDeclaration (F->getParent (), Intrinsic::ctlz,
4246
- {Arg->getType ()}),
4247
- {Arg, Builder.getFalse ()}, " ctlz" );
4248
- Rep = Builder.CreateTrunc (Ctlz, Builder.getInt32Ty (), " ctlz.trunc" );
4249
- } else if (IsNVVM && Name == " popc.ll" ) {
4250
- // llvm.nvvm.popc.ll returns an i32, but llvm.ctpop.i64 returns an
4251
- // i64.
4252
- Value *Arg = CI->getArgOperand (0 );
4253
- Value *Popc = Builder.CreateCall (
4254
- Intrinsic::getDeclaration (F->getParent (), Intrinsic::ctpop,
4255
- {Arg->getType ()}),
4256
- Arg, " ctpop" );
4257
- Rep = Builder.CreateTrunc (Popc, Builder.getInt32Ty (), " ctpop.trunc" );
4258
4316
} else if (IsNVVM) {
4259
- if (Name == " h2f" ) {
4260
- Rep =
4261
- Builder.CreateCall (Intrinsic::getDeclaration (
4262
- F->getParent (), Intrinsic::convert_from_fp16,
4263
- {Builder.getFloatTy ()}),
4264
- CI->getArgOperand (0 ), " h2f" );
4265
- } else if (Name.consume_front (" bitcast." ) &&
4266
- (Name == " f2i" || Name == " i2f" || Name == " ll2d" ||
4267
- Name == " d2ll" )) {
4268
- Rep = Builder.CreateBitCast (CI->getArgOperand (0 ), CI->getType ());
4269
- } else {
4270
- Intrinsic::ID IID = shouldUpgradeNVPTXBF16Intrinsic (Name);
4271
- if (IID != Intrinsic::not_intrinsic &&
4272
- !F->getReturnType ()->getScalarType ()->isBFloatTy ()) {
4273
- rename (F);
4274
- NewFn = Intrinsic::getDeclaration (F->getParent (), IID);
4275
- SmallVector<Value *, 2 > Args;
4276
- for (size_t I = 0 ; I < NewFn->arg_size (); ++I) {
4277
- Value *Arg = CI->getArgOperand (I);
4278
- Type *OldType = Arg->getType ();
4279
- Type *NewType = NewFn->getArg (I)->getType ();
4280
- Args.push_back ((OldType->isIntegerTy () &&
4281
- NewType->getScalarType ()->isBFloatTy ())
4282
- ? Builder.CreateBitCast (Arg, NewType)
4283
- : Arg);
4284
- }
4285
- Rep = Builder.CreateCall (NewFn, Args);
4286
- if (F->getReturnType ()->isIntegerTy ())
4287
- Rep = Builder.CreateBitCast (Rep, F->getReturnType ());
4288
- }
4289
- }
4317
+ Rep = upgradeNVVMIntrinsicCall (Name, CI, F, Builder);
4290
4318
} else if (IsX86) {
4291
4319
Rep = upgradeX86IntrinsicCall (Name, CI, F, Builder);
4292
4320
} else if (IsARM) {
0 commit comments