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