-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[MachineBlockPlacement][X86] Use max of MDAlign and TLIAlign to align Loops. #71026
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
82e7581
cd4371a
b43d6b7
45301a6
eb59788
8306999
4e49ba6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ | |
|
||
#include "llvm/CodeGen/MachineBasicBlock.h" | ||
#include "llvm/CodeGen/MachineFunctionPass.h" | ||
#include "llvm/IR/CFG.h" | ||
#include "llvm/IR/DebugLoc.h" | ||
#include "llvm/Support/GenericLoopInfo.h" | ||
|
||
|
@@ -57,7 +58,7 @@ class MachineLoop : public LoopBase<MachineBasicBlock, MachineLoop> { | |
/// loop test. This will return the latch block if it's one of the exiting | ||
/// blocks. Otherwise, return the exiting block. Return 'null' when | ||
/// multiple exiting blocks are present. | ||
MachineBasicBlock *findLoopControlBlock(); | ||
MachineBasicBlock *findLoopControlBlock() const; | ||
|
||
/// Return the debug location of the start of this loop. | ||
/// This looks for a BB terminating instruction with a known debug | ||
|
@@ -66,6 +67,14 @@ class MachineLoop : public LoopBase<MachineBasicBlock, MachineLoop> { | |
/// it returns an unknown location. | ||
DebugLoc getStartLoc() const; | ||
|
||
/// Find the llvm.loop metadata for this loop. | ||
/// If each branch to the header of this loop contains the same llvm.loop | ||
/// metadata, then this metadata node is returned. Otherwise, if any | ||
/// latch instruction does not contain the llvm.loop metadata or | ||
/// multiple latch instructions contain different llvm.loop metadata nodes, | ||
/// then null is returned. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why null? Should we use the max value of alignment if multiple latch instructions contain different There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is allowed to not set this loop metadata node from front end and patch wants to set a default alignment for such situation. |
||
MDNode *getLoopID() const; | ||
|
||
/// Returns true if the instruction is loop invariant. | ||
/// I.e., all virtual register operands are defined outside of the loop, | ||
/// physical registers aren't accessed explicitly, and there are no side | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -88,7 +88,7 @@ MachineBasicBlock *MachineLoop::getBottomBlock() { | |
return BotMBB; | ||
} | ||
|
||
MachineBasicBlock *MachineLoop::findLoopControlBlock() { | ||
MachineBasicBlock *MachineLoop::findLoopControlBlock() const { | ||
if (MachineBasicBlock *Latch = getLoopLatch()) { | ||
if (isLoopExiting(Latch)) | ||
return Latch; | ||
|
@@ -151,6 +151,53 @@ MachineLoopInfo::findLoopPreheader(MachineLoop *L, bool SpeculativePreheader, | |
return Preheader; | ||
} | ||
|
||
MDNode *MachineLoop::getLoopID() const { | ||
MDNode *LoopID = nullptr; | ||
if (const auto *MBB = findLoopControlBlock()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Downstream we noticed that the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From my understanding, if the Loop has one existing BB, the loop metadata is supposed to be attached there? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the quick response, @FreddyLeaf! I don't see this reflected in the Edit: It might be best to mirror the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Emm, looks like my understanding is outdated. I agree to mirror the middle end's implementation. Would you help do a refinement on this? |
||
// If there is a single latch block, then the metadata | ||
// node is attached to its terminating instruction. | ||
const auto *BB = MBB->getBasicBlock(); | ||
if (!BB) | ||
return nullptr; | ||
if (const auto *TI = BB->getTerminator()) | ||
LoopID = TI->getMetadata(LLVMContext::MD_loop); | ||
} else if (const auto *MBB = getHeader()) { | ||
// There seem to be multiple latch blocks, so we have to | ||
// visit all predecessors of the loop header and check | ||
// their terminating instructions for the metadata. | ||
if (const auto *Header = MBB->getBasicBlock()) { | ||
// Walk over all blocks in the loop. | ||
for (const auto *MBB : this->blocks()) { | ||
const auto *BB = MBB->getBasicBlock(); | ||
if (!BB) | ||
return nullptr; | ||
const auto *TI = BB->getTerminator(); | ||
if (!TI) | ||
return nullptr; | ||
MDNode *MD = nullptr; | ||
// Check if this terminating instruction jumps to the loop header. | ||
for (const auto *Succ : successors(TI)) { | ||
if (Succ == Header) { | ||
// This is a jump to the header - gather the metadata from it. | ||
MD = TI->getMetadata(LLVMContext::MD_loop); | ||
break; | ||
} | ||
} | ||
if (!MD) | ||
return nullptr; | ||
if (!LoopID) | ||
LoopID = MD; | ||
else if (MD != LoopID) | ||
return nullptr; | ||
} | ||
} | ||
} | ||
if (LoopID && | ||
(LoopID->getNumOperands() == 0 || LoopID->getOperand(0) != LoopID)) | ||
LoopID = nullptr; | ||
return LoopID; | ||
} | ||
|
||
bool MachineLoop::isLoopInvariant(MachineInstr &I) const { | ||
MachineFunction *MF = I.getParent()->getParent(); | ||
MachineRegisterInfo *MRI = &MF->getRegInfo(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | ||
; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu | FileCheck %s -check-prefixes=CHECK,ALIGN | ||
; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu -align-loops=32 | FileCheck %s -check-prefixes=CHECK,ALIGN32 | ||
; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu -align-loops=256 | FileCheck %s -check-prefixes=CHECK,ALIGN256 | ||
|
||
; This test is to check if .p2align can be correctly generated by considerring | ||
; 1. -align-loops=N from llc option | ||
; 2. loop metadata node !{!"llvm.loop.align", i32 64} | ||
; The test IR is generated from below simple C file: | ||
; $ clang -S -emit-llvm loop.c | ||
; $ cat loop.c | ||
; void bar(void); | ||
; void var(void); | ||
; void foo(int a) { | ||
; for (int i = 0; i < a; ++i) | ||
; bar(); | ||
; for (int i = 0; i < a; ++i) | ||
; var(); | ||
; } | ||
; The difference between test1 and test2 is test2 only set one loop metadata node for the second loop. | ||
|
||
; CHECK-LABEL: test1: | ||
; ALIGN: .p2align 6, 0x90 | ||
; ALIGN-NEXT: .LBB0_2: # %for.body | ||
; ALIGN: .p2align 9, 0x90 | ||
; ALIGN-NEXT: .LBB0_3: # %for.body | ||
|
||
; ALIGN32: .p2align 6, 0x90 | ||
; ALIGN32-NEXT: .LBB0_2: # %for.body | ||
; ALIGN32: .p2align 9, 0x90 | ||
; ALIGN32-NEXT: .LBB0_3: # %for.body | ||
|
||
; ALIGN256: .p2align 8, 0x90 | ||
; ALIGN256-NEXT: .LBB0_2: # %for.body | ||
; ALIGN256: .p2align 9, 0x90 | ||
; ALIGN256-NEXT: .LBB0_3: # %for.body | ||
|
||
define void @test1(i32 %a) nounwind { | ||
entry: | ||
%cmp12 = icmp sgt i32 %a, 0 | ||
br i1 %cmp12, label %for.body, label %for.cond.cleanup4 | ||
|
||
for.body: ; preds = %entry, %for.body | ||
%i.013 = phi i32 [ %inc, %for.body ], [ 0, %entry ] | ||
tail call void @bar() | ||
%inc = add nuw nsw i32 %i.013, 1 | ||
%exitcond.not = icmp eq i32 %inc, %a | ||
br i1 %exitcond.not, label %for.body5, label %for.body, !llvm.loop !0 | ||
|
||
for.cond.cleanup4: ; preds = %for.body5, %entry | ||
ret void | ||
|
||
for.body5: ; preds = %for.body, %for.body5 | ||
%i1.015 = phi i32 [ %inc7, %for.body5 ], [ 0, %for.body ] | ||
tail call void @var() | ||
%inc7 = add nuw nsw i32 %i1.015, 1 | ||
%exitcond16.not = icmp eq i32 %inc7, %a | ||
br i1 %exitcond16.not, label %for.cond.cleanup4, label %for.body5, !llvm.loop !2 | ||
} | ||
|
||
; CHECK-LABEL: test2: | ||
; ALIGN: .p2align 4, 0x90 | ||
; ALIGN-NEXT: .LBB1_2: # %for.body | ||
; ALIGN: .p2align 9, 0x90 | ||
; ALIGN-NEXT: .LBB1_3: # %for.body | ||
|
||
; ALIGN32: .p2align 5, 0x90 | ||
; ALIGN32-NEXT: .LBB1_2: # %for.body | ||
; ALIGN32: .p2align 9, 0x90 | ||
; ALIGN32-NEXT: .LBB1_3: # %for.body | ||
|
||
; ALIGN256: .p2align 8, 0x90 | ||
; ALIGN256-NEXT: .LBB1_2: # %for.body | ||
; ALIGN256: .p2align 9, 0x90 | ||
; ALIGN256-NEXT: .LBB1_3: # %for.body | ||
define void @test2(i32 %a) nounwind { | ||
entry: | ||
%cmp12 = icmp sgt i32 %a, 0 | ||
br i1 %cmp12, label %for.body, label %for.cond.cleanup4 | ||
|
||
for.body: ; preds = %entry, %for.body | ||
%i.013 = phi i32 [ %inc, %for.body ], [ 0, %entry ] | ||
tail call void @bar() | ||
%inc = add nuw nsw i32 %i.013, 1 | ||
%exitcond.not = icmp eq i32 %inc, %a | ||
br i1 %exitcond.not, label %for.body5, label %for.body | ||
|
||
for.cond.cleanup4: ; preds = %for.body5, %entry | ||
ret void | ||
|
||
for.body5: ; preds = %for.body, %for.body5 | ||
%i1.015 = phi i32 [ %inc7, %for.body5 ], [ 0, %for.body ] | ||
tail call void @var() | ||
%inc7 = add nuw nsw i32 %i1.015, 1 | ||
%exitcond16.not = icmp eq i32 %inc7, %a | ||
br i1 %exitcond16.not, label %for.cond.cleanup4, label %for.body5, !llvm.loop !2 | ||
} | ||
|
||
declare void @bar() | ||
declare void @var() | ||
|
||
!0 = distinct !{!0, !1} | ||
!1 = !{!"llvm.loop.align", i32 64} | ||
!2 = distinct !{!2, !3} | ||
!3 = !{!"llvm.loop.align", i32 512} |
Uh oh!
There was an error while loading. Please reload this page.