1 //===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "CGLoopInfo.h" 10 #include "clang/AST/ASTContext.h" 11 #include "clang/AST/Attr.h" 12 #include "clang/AST/Expr.h" 13 #include "clang/Basic/CodeGenOptions.h" 14 #include "llvm/IR/BasicBlock.h" 15 #include "llvm/IR/CFG.h" 16 #include "llvm/IR/Constants.h" 17 #include "llvm/IR/InstrTypes.h" 18 #include "llvm/IR/Instructions.h" 19 #include "llvm/IR/Metadata.h" 20 using namespace clang::CodeGen; 21 using namespace llvm; 22 23 MDNode * 24 LoopInfo::createLoopPropertiesMetadata(ArrayRef<Metadata *> LoopProperties) { 25 LLVMContext &Ctx = Header->getContext(); 26 SmallVector<Metadata *, 4> NewLoopProperties; 27 NewLoopProperties.push_back(nullptr); 28 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end()); 29 30 MDNode *LoopID = MDNode::getDistinct(Ctx, NewLoopProperties); 31 LoopID->replaceOperandWith(0, LoopID); 32 return LoopID; 33 } 34 35 MDNode *LoopInfo::createPipeliningMetadata(const LoopAttributes &Attrs, 36 ArrayRef<Metadata *> LoopProperties, 37 bool &HasUserTransforms) { 38 LLVMContext &Ctx = Header->getContext(); 39 40 Optional<bool> Enabled; 41 if (Attrs.PipelineDisabled) 42 Enabled = false; 43 else if (Attrs.PipelineInitiationInterval != 0) 44 Enabled = true; 45 46 if (Enabled != true) { 47 SmallVector<Metadata *, 4> NewLoopProperties; 48 if (Enabled == false) { 49 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end()); 50 NewLoopProperties.push_back( 51 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.pipeline.disable"), 52 ConstantAsMetadata::get(ConstantInt::get( 53 llvm::Type::getInt1Ty(Ctx), 1))})); 54 LoopProperties = NewLoopProperties; 55 } 56 return createLoopPropertiesMetadata(LoopProperties); 57 } 58 59 SmallVector<Metadata *, 4> Args; 60 Args.push_back(nullptr); 61 Args.append(LoopProperties.begin(), LoopProperties.end()); 62 63 if (Attrs.PipelineInitiationInterval > 0) { 64 Metadata *Vals[] = { 65 MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"), 66 ConstantAsMetadata::get(ConstantInt::get( 67 llvm::Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))}; 68 Args.push_back(MDNode::get(Ctx, Vals)); 69 } 70 71 // No follow-up: This is the last transformation. 72 73 MDNode *LoopID = MDNode::getDistinct(Ctx, Args); 74 LoopID->replaceOperandWith(0, LoopID); 75 HasUserTransforms = true; 76 return LoopID; 77 } 78 79 MDNode * 80 LoopInfo::createPartialUnrollMetadata(const LoopAttributes &Attrs, 81 ArrayRef<Metadata *> LoopProperties, 82 bool &HasUserTransforms) { 83 LLVMContext &Ctx = Header->getContext(); 84 85 Optional<bool> Enabled; 86 if (Attrs.UnrollEnable == LoopAttributes::Disable) 87 Enabled = false; 88 else if (Attrs.UnrollEnable == LoopAttributes::Full) 89 Enabled = None; 90 else if (Attrs.UnrollEnable != LoopAttributes::Unspecified || 91 Attrs.UnrollCount != 0) 92 Enabled = true; 93 94 if (Enabled != true) { 95 // createFullUnrollMetadata will already have added llvm.loop.unroll.disable 96 // if unrolling is disabled. 97 return createPipeliningMetadata(Attrs, LoopProperties, HasUserTransforms); 98 } 99 100 SmallVector<Metadata *, 4> FollowupLoopProperties; 101 102 // Apply all loop properties to the unrolled loop. 103 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end()); 104 105 // Don't unroll an already unrolled loop. 106 FollowupLoopProperties.push_back( 107 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable"))); 108 109 bool FollowupHasTransforms = false; 110 MDNode *Followup = createPipeliningMetadata(Attrs, FollowupLoopProperties, 111 FollowupHasTransforms); 112 113 SmallVector<Metadata *, 4> Args; 114 Args.push_back(nullptr); 115 Args.append(LoopProperties.begin(), LoopProperties.end()); 116 117 // Setting unroll.count 118 if (Attrs.UnrollCount > 0) { 119 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"), 120 ConstantAsMetadata::get(ConstantInt::get( 121 llvm::Type::getInt32Ty(Ctx), Attrs.UnrollCount))}; 122 Args.push_back(MDNode::get(Ctx, Vals)); 123 } 124 125 // Setting unroll.full or unroll.disable 126 if (Attrs.UnrollEnable == LoopAttributes::Enable) { 127 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.enable")}; 128 Args.push_back(MDNode::get(Ctx, Vals)); 129 } 130 131 if (FollowupHasTransforms) 132 Args.push_back(MDNode::get( 133 Ctx, {MDString::get(Ctx, "llvm.loop.unroll.followup_all"), Followup})); 134 135 MDNode *LoopID = MDNode::getDistinct(Ctx, Args); 136 LoopID->replaceOperandWith(0, LoopID); 137 HasUserTransforms = true; 138 return LoopID; 139 } 140 141 MDNode * 142 LoopInfo::createUnrollAndJamMetadata(const LoopAttributes &Attrs, 143 ArrayRef<Metadata *> LoopProperties, 144 bool &HasUserTransforms) { 145 LLVMContext &Ctx = Header->getContext(); 146 147 Optional<bool> Enabled; 148 if (Attrs.UnrollAndJamEnable == LoopAttributes::Disable) 149 Enabled = false; 150 else if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable || 151 Attrs.UnrollAndJamCount != 0) 152 Enabled = true; 153 154 if (Enabled != true) { 155 SmallVector<Metadata *, 4> NewLoopProperties; 156 if (Enabled == false) { 157 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end()); 158 NewLoopProperties.push_back(MDNode::get( 159 Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable"))); 160 LoopProperties = NewLoopProperties; 161 } 162 return createPartialUnrollMetadata(Attrs, LoopProperties, 163 HasUserTransforms); 164 } 165 166 SmallVector<Metadata *, 4> FollowupLoopProperties; 167 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end()); 168 FollowupLoopProperties.push_back( 169 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable"))); 170 171 bool FollowupHasTransforms = false; 172 MDNode *Followup = createPartialUnrollMetadata(Attrs, FollowupLoopProperties, 173 FollowupHasTransforms); 174 175 SmallVector<Metadata *, 4> Args; 176 Args.push_back(nullptr); 177 Args.append(LoopProperties.begin(), LoopProperties.end()); 178 179 // Setting unroll_and_jam.count 180 if (Attrs.UnrollAndJamCount > 0) { 181 Metadata *Vals[] = { 182 MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"), 183 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx), 184 Attrs.UnrollAndJamCount))}; 185 Args.push_back(MDNode::get(Ctx, Vals)); 186 } 187 188 if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable) { 189 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.enable")}; 190 Args.push_back(MDNode::get(Ctx, Vals)); 191 } 192 193 if (FollowupHasTransforms) 194 Args.push_back(MDNode::get( 195 Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_outer"), 196 Followup})); 197 198 if (UnrollAndJamInnerFollowup) 199 Args.push_back(MDNode::get( 200 Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_inner"), 201 UnrollAndJamInnerFollowup})); 202 203 MDNode *LoopID = MDNode::getDistinct(Ctx, Args); 204 LoopID->replaceOperandWith(0, LoopID); 205 HasUserTransforms = true; 206 return LoopID; 207 } 208 209 MDNode * 210 LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs, 211 ArrayRef<Metadata *> LoopProperties, 212 bool &HasUserTransforms) { 213 LLVMContext &Ctx = Header->getContext(); 214 215 Optional<bool> Enabled; 216 if (Attrs.VectorizeEnable == LoopAttributes::Disable) 217 Enabled = false; 218 else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified || 219 Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified || 220 Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0 || 221 Attrs.VectorizeScalable != LoopAttributes::Unspecified) 222 Enabled = true; 223 224 if (Enabled != true) { 225 SmallVector<Metadata *, 4> NewLoopProperties; 226 if (Enabled == false) { 227 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end()); 228 NewLoopProperties.push_back( 229 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"), 230 ConstantAsMetadata::get(ConstantInt::get( 231 llvm::Type::getInt1Ty(Ctx), 0))})); 232 LoopProperties = NewLoopProperties; 233 } 234 return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms); 235 } 236 237 // Apply all loop properties to the vectorized loop. 238 SmallVector<Metadata *, 4> FollowupLoopProperties; 239 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end()); 240 241 // Don't vectorize an already vectorized loop. 242 FollowupLoopProperties.push_back( 243 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized"))); 244 245 bool FollowupHasTransforms = false; 246 MDNode *Followup = createUnrollAndJamMetadata(Attrs, FollowupLoopProperties, 247 FollowupHasTransforms); 248 249 SmallVector<Metadata *, 4> Args; 250 Args.push_back(nullptr); 251 Args.append(LoopProperties.begin(), LoopProperties.end()); 252 253 // Setting vectorize.predicate when it has been specified and vectorization 254 // has not been disabled. 255 bool IsVectorPredicateEnabled = false; 256 if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified) { 257 IsVectorPredicateEnabled = 258 (Attrs.VectorizePredicateEnable == LoopAttributes::Enable); 259 260 Metadata *Vals[] = { 261 MDString::get(Ctx, "llvm.loop.vectorize.predicate.enable"), 262 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt1Ty(Ctx), 263 IsVectorPredicateEnabled))}; 264 Args.push_back(MDNode::get(Ctx, Vals)); 265 } 266 267 // Setting vectorize.width 268 if (Attrs.VectorizeWidth > 0) { 269 Metadata *Vals[] = { 270 MDString::get(Ctx, "llvm.loop.vectorize.width"), 271 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx), 272 Attrs.VectorizeWidth))}; 273 274 Args.push_back(MDNode::get(Ctx, Vals)); 275 } 276 277 if (Attrs.VectorizeScalable != LoopAttributes::Unspecified) { 278 bool IsScalable = Attrs.VectorizeScalable == LoopAttributes::Enable; 279 Metadata *Vals[] = { 280 MDString::get(Ctx, "llvm.loop.vectorize.scalable.enable"), 281 ConstantAsMetadata::get( 282 ConstantInt::get(llvm::Type::getInt1Ty(Ctx), IsScalable))}; 283 Args.push_back(MDNode::get(Ctx, Vals)); 284 } 285 286 // Setting interleave.count 287 if (Attrs.InterleaveCount > 0) { 288 Metadata *Vals[] = { 289 MDString::get(Ctx, "llvm.loop.interleave.count"), 290 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx), 291 Attrs.InterleaveCount))}; 292 Args.push_back(MDNode::get(Ctx, Vals)); 293 } 294 295 // vectorize.enable is set if: 296 // 1) loop hint vectorize.enable is set, or 297 // 2) it is implied when vectorize.predicate is set, or 298 // 3) it is implied when vectorize.width is set to a value > 1 299 // 4) it is implied when vectorize.scalable.enable is true 300 // 5) it is implied when vectorize.width is unset (0) and the user 301 // explicitly requested fixed-width vectorization, i.e. 302 // vectorize.scalable.enable is false. 303 if (Attrs.VectorizeEnable != LoopAttributes::Unspecified || 304 (IsVectorPredicateEnabled && Attrs.VectorizeWidth != 1) || 305 Attrs.VectorizeWidth > 1 || 306 Attrs.VectorizeScalable == LoopAttributes::Enable || 307 (Attrs.VectorizeScalable == LoopAttributes::Disable && 308 Attrs.VectorizeWidth != 1)) { 309 bool AttrVal = Attrs.VectorizeEnable != LoopAttributes::Disable; 310 Args.push_back( 311 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"), 312 ConstantAsMetadata::get(ConstantInt::get( 313 llvm::Type::getInt1Ty(Ctx), AttrVal))})); 314 } 315 316 if (FollowupHasTransforms) 317 Args.push_back(MDNode::get( 318 Ctx, 319 {MDString::get(Ctx, "llvm.loop.vectorize.followup_all"), Followup})); 320 321 MDNode *LoopID = MDNode::getDistinct(Ctx, Args); 322 LoopID->replaceOperandWith(0, LoopID); 323 HasUserTransforms = true; 324 return LoopID; 325 } 326 327 MDNode * 328 LoopInfo::createLoopDistributeMetadata(const LoopAttributes &Attrs, 329 ArrayRef<Metadata *> LoopProperties, 330 bool &HasUserTransforms) { 331 LLVMContext &Ctx = Header->getContext(); 332 333 Optional<bool> Enabled; 334 if (Attrs.DistributeEnable == LoopAttributes::Disable) 335 Enabled = false; 336 if (Attrs.DistributeEnable == LoopAttributes::Enable) 337 Enabled = true; 338 339 if (Enabled != true) { 340 SmallVector<Metadata *, 4> NewLoopProperties; 341 if (Enabled == false) { 342 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end()); 343 NewLoopProperties.push_back( 344 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"), 345 ConstantAsMetadata::get(ConstantInt::get( 346 llvm::Type::getInt1Ty(Ctx), 0))})); 347 LoopProperties = NewLoopProperties; 348 } 349 return createLoopVectorizeMetadata(Attrs, LoopProperties, 350 HasUserTransforms); 351 } 352 353 bool FollowupHasTransforms = false; 354 MDNode *Followup = 355 createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms); 356 357 SmallVector<Metadata *, 4> Args; 358 Args.push_back(nullptr); 359 Args.append(LoopProperties.begin(), LoopProperties.end()); 360 361 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"), 362 ConstantAsMetadata::get(ConstantInt::get( 363 llvm::Type::getInt1Ty(Ctx), 364 (Attrs.DistributeEnable == LoopAttributes::Enable)))}; 365 Args.push_back(MDNode::get(Ctx, Vals)); 366 367 if (FollowupHasTransforms) 368 Args.push_back(MDNode::get( 369 Ctx, 370 {MDString::get(Ctx, "llvm.loop.distribute.followup_all"), Followup})); 371 372 MDNode *LoopID = MDNode::getDistinct(Ctx, Args); 373 LoopID->replaceOperandWith(0, LoopID); 374 HasUserTransforms = true; 375 return LoopID; 376 } 377 378 MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs, 379 ArrayRef<Metadata *> LoopProperties, 380 bool &HasUserTransforms) { 381 LLVMContext &Ctx = Header->getContext(); 382 383 Optional<bool> Enabled; 384 if (Attrs.UnrollEnable == LoopAttributes::Disable) 385 Enabled = false; 386 else if (Attrs.UnrollEnable == LoopAttributes::Full) 387 Enabled = true; 388 389 if (Enabled != true) { 390 SmallVector<Metadata *, 4> NewLoopProperties; 391 if (Enabled == false) { 392 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end()); 393 NewLoopProperties.push_back( 394 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable"))); 395 LoopProperties = NewLoopProperties; 396 } 397 return createLoopDistributeMetadata(Attrs, LoopProperties, 398 HasUserTransforms); 399 } 400 401 SmallVector<Metadata *, 4> Args; 402 Args.push_back(nullptr); 403 Args.append(LoopProperties.begin(), LoopProperties.end()); 404 Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full"))); 405 406 // No follow-up: there is no loop after full unrolling. 407 // TODO: Warn if there are transformations after full unrolling. 408 409 MDNode *LoopID = MDNode::getDistinct(Ctx, Args); 410 LoopID->replaceOperandWith(0, LoopID); 411 HasUserTransforms = true; 412 return LoopID; 413 } 414 415 MDNode *LoopInfo::createMetadata( 416 const LoopAttributes &Attrs, 417 llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties, 418 bool &HasUserTransforms) { 419 SmallVector<Metadata *, 3> LoopProperties; 420 421 // If we have a valid start debug location for the loop, add it. 422 if (StartLoc) { 423 LoopProperties.push_back(StartLoc.getAsMDNode()); 424 425 // If we also have a valid end debug location for the loop, add it. 426 if (EndLoc) 427 LoopProperties.push_back(EndLoc.getAsMDNode()); 428 } 429 430 LLVMContext &Ctx = Header->getContext(); 431 if (Attrs.MustProgress) 432 LoopProperties.push_back( 433 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.mustprogress"))); 434 435 assert(!!AccGroup == Attrs.IsParallel && 436 "There must be an access group iff the loop is parallel"); 437 if (Attrs.IsParallel) { 438 LoopProperties.push_back(MDNode::get( 439 Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup})); 440 } 441 442 LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(), 443 AdditionalLoopProperties.end()); 444 return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms); 445 } 446 447 LoopAttributes::LoopAttributes(bool IsParallel) 448 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified), 449 UnrollEnable(LoopAttributes::Unspecified), 450 UnrollAndJamEnable(LoopAttributes::Unspecified), 451 VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0), 452 VectorizeScalable(LoopAttributes::Unspecified), InterleaveCount(0), 453 UnrollCount(0), UnrollAndJamCount(0), 454 DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false), 455 PipelineInitiationInterval(0), MustProgress(false) {} 456 457 void LoopAttributes::clear() { 458 IsParallel = false; 459 VectorizeWidth = 0; 460 VectorizeScalable = LoopAttributes::Unspecified; 461 InterleaveCount = 0; 462 UnrollCount = 0; 463 UnrollAndJamCount = 0; 464 VectorizeEnable = LoopAttributes::Unspecified; 465 UnrollEnable = LoopAttributes::Unspecified; 466 UnrollAndJamEnable = LoopAttributes::Unspecified; 467 VectorizePredicateEnable = LoopAttributes::Unspecified; 468 DistributeEnable = LoopAttributes::Unspecified; 469 PipelineDisabled = false; 470 PipelineInitiationInterval = 0; 471 MustProgress = false; 472 } 473 474 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs, 475 const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc, 476 LoopInfo *Parent) 477 : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc), 478 Parent(Parent) { 479 480 if (Attrs.IsParallel) { 481 // Create an access group for this loop. 482 LLVMContext &Ctx = Header->getContext(); 483 AccGroup = MDNode::getDistinct(Ctx, {}); 484 } 485 486 if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 && 487 Attrs.VectorizeScalable == LoopAttributes::Unspecified && 488 Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 && 489 Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled && 490 Attrs.PipelineInitiationInterval == 0 && 491 Attrs.VectorizePredicateEnable == LoopAttributes::Unspecified && 492 Attrs.VectorizeEnable == LoopAttributes::Unspecified && 493 Attrs.UnrollEnable == LoopAttributes::Unspecified && 494 Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified && 495 Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc && 496 !EndLoc && !Attrs.MustProgress) 497 return; 498 499 TempLoopID = MDNode::getTemporary(Header->getContext(), None); 500 } 501 502 void LoopInfo::finish() { 503 // We did not annotate the loop body instructions because there are no 504 // attributes for this loop. 505 if (!TempLoopID) 506 return; 507 508 MDNode *LoopID; 509 LoopAttributes CurLoopAttr = Attrs; 510 LLVMContext &Ctx = Header->getContext(); 511 512 if (Parent && (Parent->Attrs.UnrollAndJamEnable || 513 Parent->Attrs.UnrollAndJamCount != 0)) { 514 // Parent unroll-and-jams this loop. 515 // Split the transformations in those that happens before the unroll-and-jam 516 // and those after. 517 518 LoopAttributes BeforeJam, AfterJam; 519 520 BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel; 521 522 BeforeJam.VectorizeWidth = Attrs.VectorizeWidth; 523 BeforeJam.VectorizeScalable = Attrs.VectorizeScalable; 524 BeforeJam.InterleaveCount = Attrs.InterleaveCount; 525 BeforeJam.VectorizeEnable = Attrs.VectorizeEnable; 526 BeforeJam.DistributeEnable = Attrs.DistributeEnable; 527 BeforeJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable; 528 529 switch (Attrs.UnrollEnable) { 530 case LoopAttributes::Unspecified: 531 case LoopAttributes::Disable: 532 BeforeJam.UnrollEnable = Attrs.UnrollEnable; 533 AfterJam.UnrollEnable = Attrs.UnrollEnable; 534 break; 535 case LoopAttributes::Full: 536 BeforeJam.UnrollEnable = LoopAttributes::Full; 537 break; 538 case LoopAttributes::Enable: 539 AfterJam.UnrollEnable = LoopAttributes::Enable; 540 break; 541 } 542 543 AfterJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable; 544 AfterJam.UnrollCount = Attrs.UnrollCount; 545 AfterJam.PipelineDisabled = Attrs.PipelineDisabled; 546 AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval; 547 548 // If this loop is subject of an unroll-and-jam by the parent loop, and has 549 // an unroll-and-jam annotation itself, we have to decide whether to first 550 // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The 551 // UnrollAndJam pass processes loops from inner to outer, so we apply the 552 // inner first. 553 BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount; 554 BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable; 555 556 // Set the inner followup metadata to process by the outer loop. Only 557 // consider the first inner loop. 558 if (!Parent->UnrollAndJamInnerFollowup) { 559 // Splitting the attributes into a BeforeJam and an AfterJam part will 560 // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam) 561 // to be forwarded to the AfterJam part. We detect the situation here and 562 // add it manually. 563 SmallVector<Metadata *, 1> BeforeLoopProperties; 564 if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified || 565 BeforeJam.VectorizePredicateEnable != LoopAttributes::Unspecified || 566 BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0 || 567 BeforeJam.VectorizeScalable == LoopAttributes::Enable) 568 BeforeLoopProperties.push_back( 569 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized"))); 570 571 bool InnerFollowupHasTransform = false; 572 MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties, 573 InnerFollowupHasTransform); 574 if (InnerFollowupHasTransform) 575 Parent->UnrollAndJamInnerFollowup = InnerFollowup; 576 } 577 578 CurLoopAttr = BeforeJam; 579 } 580 581 bool HasUserTransforms = false; 582 LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms); 583 TempLoopID->replaceAllUsesWith(LoopID); 584 } 585 586 void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc, 587 const llvm::DebugLoc &EndLoc) { 588 Active.emplace_back( 589 new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc, 590 Active.empty() ? nullptr : Active.back().get())); 591 // Clear the attributes so nested loops do not inherit them. 592 StagedAttrs.clear(); 593 } 594 595 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx, 596 const clang::CodeGenOptions &CGOpts, 597 ArrayRef<const clang::Attr *> Attrs, 598 const llvm::DebugLoc &StartLoc, 599 const llvm::DebugLoc &EndLoc, bool MustProgress) { 600 // Identify loop hint attributes from Attrs. 601 for (const auto *Attr : Attrs) { 602 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr); 603 const OpenCLUnrollHintAttr *OpenCLHint = 604 dyn_cast<OpenCLUnrollHintAttr>(Attr); 605 606 // Skip non loop hint attributes 607 if (!LH && !OpenCLHint) { 608 continue; 609 } 610 611 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll; 612 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable; 613 unsigned ValueInt = 1; 614 // Translate opencl_unroll_hint attribute argument to 615 // equivalent LoopHintAttr enums. 616 // OpenCL v2.0 s6.11.5: 617 // 0 - enable unroll (no argument). 618 // 1 - disable unroll. 619 // other positive integer n - unroll by n. 620 if (OpenCLHint) { 621 ValueInt = OpenCLHint->getUnrollHint(); 622 if (ValueInt == 0) { 623 State = LoopHintAttr::Enable; 624 } else if (ValueInt != 1) { 625 Option = LoopHintAttr::UnrollCount; 626 State = LoopHintAttr::Numeric; 627 } 628 } else if (LH) { 629 auto *ValueExpr = LH->getValue(); 630 if (ValueExpr) { 631 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx); 632 ValueInt = ValueAPS.getSExtValue(); 633 } 634 635 Option = LH->getOption(); 636 State = LH->getState(); 637 } 638 switch (State) { 639 case LoopHintAttr::Disable: 640 switch (Option) { 641 case LoopHintAttr::Vectorize: 642 // Disable vectorization by specifying a width of 1. 643 setVectorizeWidth(1); 644 setVectorizeScalable(LoopAttributes::Unspecified); 645 break; 646 case LoopHintAttr::Interleave: 647 // Disable interleaving by speciyfing a count of 1. 648 setInterleaveCount(1); 649 break; 650 case LoopHintAttr::Unroll: 651 setUnrollState(LoopAttributes::Disable); 652 break; 653 case LoopHintAttr::UnrollAndJam: 654 setUnrollAndJamState(LoopAttributes::Disable); 655 break; 656 case LoopHintAttr::VectorizePredicate: 657 setVectorizePredicateState(LoopAttributes::Disable); 658 break; 659 case LoopHintAttr::Distribute: 660 setDistributeState(false); 661 break; 662 case LoopHintAttr::PipelineDisabled: 663 setPipelineDisabled(true); 664 break; 665 case LoopHintAttr::UnrollCount: 666 case LoopHintAttr::UnrollAndJamCount: 667 case LoopHintAttr::VectorizeWidth: 668 case LoopHintAttr::InterleaveCount: 669 case LoopHintAttr::PipelineInitiationInterval: 670 llvm_unreachable("Options cannot be disabled."); 671 break; 672 } 673 break; 674 case LoopHintAttr::Enable: 675 switch (Option) { 676 case LoopHintAttr::Vectorize: 677 case LoopHintAttr::Interleave: 678 setVectorizeEnable(true); 679 break; 680 case LoopHintAttr::Unroll: 681 setUnrollState(LoopAttributes::Enable); 682 break; 683 case LoopHintAttr::UnrollAndJam: 684 setUnrollAndJamState(LoopAttributes::Enable); 685 break; 686 case LoopHintAttr::VectorizePredicate: 687 setVectorizePredicateState(LoopAttributes::Enable); 688 break; 689 case LoopHintAttr::Distribute: 690 setDistributeState(true); 691 break; 692 case LoopHintAttr::UnrollCount: 693 case LoopHintAttr::UnrollAndJamCount: 694 case LoopHintAttr::VectorizeWidth: 695 case LoopHintAttr::InterleaveCount: 696 case LoopHintAttr::PipelineDisabled: 697 case LoopHintAttr::PipelineInitiationInterval: 698 llvm_unreachable("Options cannot enabled."); 699 break; 700 } 701 break; 702 case LoopHintAttr::AssumeSafety: 703 switch (Option) { 704 case LoopHintAttr::Vectorize: 705 case LoopHintAttr::Interleave: 706 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores. 707 setParallel(true); 708 setVectorizeEnable(true); 709 break; 710 case LoopHintAttr::Unroll: 711 case LoopHintAttr::UnrollAndJam: 712 case LoopHintAttr::VectorizePredicate: 713 case LoopHintAttr::UnrollCount: 714 case LoopHintAttr::UnrollAndJamCount: 715 case LoopHintAttr::VectorizeWidth: 716 case LoopHintAttr::InterleaveCount: 717 case LoopHintAttr::Distribute: 718 case LoopHintAttr::PipelineDisabled: 719 case LoopHintAttr::PipelineInitiationInterval: 720 llvm_unreachable("Options cannot be used to assume mem safety."); 721 break; 722 } 723 break; 724 case LoopHintAttr::Full: 725 switch (Option) { 726 case LoopHintAttr::Unroll: 727 setUnrollState(LoopAttributes::Full); 728 break; 729 case LoopHintAttr::UnrollAndJam: 730 setUnrollAndJamState(LoopAttributes::Full); 731 break; 732 case LoopHintAttr::Vectorize: 733 case LoopHintAttr::Interleave: 734 case LoopHintAttr::UnrollCount: 735 case LoopHintAttr::UnrollAndJamCount: 736 case LoopHintAttr::VectorizeWidth: 737 case LoopHintAttr::InterleaveCount: 738 case LoopHintAttr::Distribute: 739 case LoopHintAttr::PipelineDisabled: 740 case LoopHintAttr::PipelineInitiationInterval: 741 case LoopHintAttr::VectorizePredicate: 742 llvm_unreachable("Options cannot be used with 'full' hint."); 743 break; 744 } 745 break; 746 case LoopHintAttr::FixedWidth: 747 case LoopHintAttr::ScalableWidth: 748 switch (Option) { 749 case LoopHintAttr::VectorizeWidth: 750 setVectorizeScalable(State == LoopHintAttr::ScalableWidth 751 ? LoopAttributes::Enable 752 : LoopAttributes::Disable); 753 if (LH->getValue()) 754 setVectorizeWidth(ValueInt); 755 break; 756 default: 757 llvm_unreachable("Options cannot be used with 'scalable' hint."); 758 break; 759 } 760 break; 761 case LoopHintAttr::Numeric: 762 switch (Option) { 763 case LoopHintAttr::InterleaveCount: 764 setInterleaveCount(ValueInt); 765 break; 766 case LoopHintAttr::UnrollCount: 767 setUnrollCount(ValueInt); 768 break; 769 case LoopHintAttr::UnrollAndJamCount: 770 setUnrollAndJamCount(ValueInt); 771 break; 772 case LoopHintAttr::PipelineInitiationInterval: 773 setPipelineInitiationInterval(ValueInt); 774 break; 775 case LoopHintAttr::Unroll: 776 case LoopHintAttr::UnrollAndJam: 777 case LoopHintAttr::VectorizePredicate: 778 case LoopHintAttr::Vectorize: 779 case LoopHintAttr::VectorizeWidth: 780 case LoopHintAttr::Interleave: 781 case LoopHintAttr::Distribute: 782 case LoopHintAttr::PipelineDisabled: 783 llvm_unreachable("Options cannot be assigned a value."); 784 break; 785 } 786 break; 787 } 788 } 789 790 setMustProgress(MustProgress); 791 792 if (CGOpts.OptimizationLevel > 0) 793 // Disable unrolling for the loop, if unrolling is disabled (via 794 // -fno-unroll-loops) and no pragmas override the decision. 795 if (!CGOpts.UnrollLoops && 796 (StagedAttrs.UnrollEnable == LoopAttributes::Unspecified && 797 StagedAttrs.UnrollCount == 0)) 798 setUnrollState(LoopAttributes::Disable); 799 800 /// Stage the attributes. 801 push(Header, StartLoc, EndLoc); 802 } 803 804 void LoopInfoStack::pop() { 805 assert(!Active.empty() && "No active loops to pop"); 806 Active.back()->finish(); 807 Active.pop_back(); 808 } 809 810 void LoopInfoStack::InsertHelper(Instruction *I) const { 811 if (I->mayReadOrWriteMemory()) { 812 SmallVector<Metadata *, 4> AccessGroups; 813 for (const auto &AL : Active) { 814 // Here we assume that every loop that has an access group is parallel. 815 if (MDNode *Group = AL->getAccessGroup()) 816 AccessGroups.push_back(Group); 817 } 818 MDNode *UnionMD = nullptr; 819 if (AccessGroups.size() == 1) 820 UnionMD = cast<MDNode>(AccessGroups[0]); 821 else if (AccessGroups.size() >= 2) 822 UnionMD = MDNode::get(I->getContext(), AccessGroups); 823 I->setMetadata("llvm.access.group", UnionMD); 824 } 825 826 if (!hasInfo()) 827 return; 828 829 const LoopInfo &L = getInfo(); 830 if (!L.getLoopID()) 831 return; 832 833 if (I->isTerminator()) { 834 for (BasicBlock *Succ : successors(I)) 835 if (Succ == L.getHeader()) { 836 I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID()); 837 break; 838 } 839 return; 840 } 841 } 842