1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu | FileCheck %s -check-prefixes=CHECK,ALIGN 3; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu -align-loops=32 | FileCheck %s -check-prefixes=CHECK,ALIGN32 4; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu -align-loops=256 | FileCheck %s -check-prefixes=CHECK,ALIGN256 5 6; This test is to check if .p2align can be correctly generated by considerring 7; 1. -align-loops=N from llc option 8; 2. loop metadata node !{!"llvm.loop.align", i32 64} 9; The test IR is generated from below simple C file: 10; $ clang -S -emit-llvm loop.c 11; $ cat loop.c 12; void bar(void); 13; void var(void); 14; void foo(int a) { 15; for (int i = 0; i < a; ++i) 16; bar(); 17; for (int i = 0; i < a; ++i) 18; var(); 19; } 20; The difference between test1 and test2 is test2 only set one loop metadata node for the second loop. 21 22; CHECK-LABEL: test1: 23; ALIGN: .p2align 6 24; ALIGN-NEXT: .LBB0_2: # %for.body 25; ALIGN: .p2align 9 26; ALIGN-NEXT: .LBB0_3: # %for.body 27 28; ALIGN32: .p2align 6 29; ALIGN32-NEXT: .LBB0_2: # %for.body 30; ALIGN32: .p2align 9 31; ALIGN32-NEXT: .LBB0_3: # %for.body 32 33; ALIGN256: .p2align 8 34; ALIGN256-NEXT: .LBB0_2: # %for.body 35; ALIGN256: .p2align 9 36; ALIGN256-NEXT: .LBB0_3: # %for.body 37 38define void @test1(i32 %a) nounwind { 39entry: 40 %cmp12 = icmp sgt i32 %a, 0 41 br i1 %cmp12, label %for.body, label %for.cond.cleanup4 42 43for.body: ; preds = %entry, %for.body 44 %i.013 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 45 tail call void @bar() 46 %inc = add nuw nsw i32 %i.013, 1 47 %exitcond.not = icmp eq i32 %inc, %a 48 br i1 %exitcond.not, label %for.body5, label %for.body, !llvm.loop !0 49 50for.cond.cleanup4: ; preds = %for.body5, %entry 51 ret void 52 53for.body5: ; preds = %for.body, %for.body5 54 %i1.015 = phi i32 [ %inc7, %for.body5 ], [ 0, %for.body ] 55 tail call void @var() 56 %inc7 = add nuw nsw i32 %i1.015, 1 57 %exitcond16.not = icmp eq i32 %inc7, %a 58 br i1 %exitcond16.not, label %for.cond.cleanup4, label %for.body5, !llvm.loop !2 59} 60 61; CHECK-LABEL: test2: 62; ALIGN: .p2align 4 63; ALIGN-NEXT: .LBB1_2: # %for.body 64; ALIGN: .p2align 9 65; ALIGN-NEXT: .LBB1_3: # %for.body 66 67; ALIGN32: .p2align 5 68; ALIGN32-NEXT: .LBB1_2: # %for.body 69; ALIGN32: .p2align 9 70; ALIGN32-NEXT: .LBB1_3: # %for.body 71 72; ALIGN256: .p2align 8 73; ALIGN256-NEXT: .LBB1_2: # %for.body 74; ALIGN256: .p2align 9 75; ALIGN256-NEXT: .LBB1_3: # %for.body 76define void @test2(i32 %a) nounwind { 77entry: 78 %cmp12 = icmp sgt i32 %a, 0 79 br i1 %cmp12, label %for.body, label %for.cond.cleanup4 80 81for.body: ; preds = %entry, %for.body 82 %i.013 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 83 tail call void @bar() 84 %inc = add nuw nsw i32 %i.013, 1 85 %exitcond.not = icmp eq i32 %inc, %a 86 br i1 %exitcond.not, label %for.body5, label %for.body 87 88for.cond.cleanup4: ; preds = %for.body5, %entry 89 ret void 90 91for.body5: ; preds = %for.body, %for.body5 92 %i1.015 = phi i32 [ %inc7, %for.body5 ], [ 0, %for.body ] 93 tail call void @var() 94 %inc7 = add nuw nsw i32 %i1.015, 1 95 %exitcond16.not = icmp eq i32 %inc7, %a 96 br i1 %exitcond16.not, label %for.cond.cleanup4, label %for.body5, !llvm.loop !2 97} 98 99; test3 and test4 is to check if .p2align can be correctly set on loops with 100; multi latches. The IR is generated from below simple C file: 101; $ clang -O0 -S -emit-llvm loop.c 102; $ cat loop.c 103; int test3() { 104; int i = 0; 105; [[clang::code_align(32)]] 106; while (i < 10) { 107; if (i % 2) { 108; continue; 109; } 110; i++; 111; } 112; } 113; CHECK-LABEL: test3_multilatch: 114; ALIGN: .p2align 6 115; ALIGN-NEXT: .LBB2_1: # %while.cond 116define dso_local i32 @test3_multilatch() #0 { 117entry: 118 %retval = alloca i32, align 4 119 %i = alloca i32, align 4 120 store i32 0, ptr %retval, align 4 121 store i32 0, ptr %i, align 4 122 br label %while.cond 123 124while.cond: ; preds = %if.end, %if.then, %entry 125 %0 = load i32, ptr %i, align 4 126 %cmp = icmp slt i32 %0, 10 127 br i1 %cmp, label %while.body, label %while.end 128 129while.body: ; preds = %while.cond 130 %1 = load i32, ptr %i, align 4 131 %rem = srem i32 %1, 2 132 %tobool = icmp ne i32 %rem, 0 133 br i1 %tobool, label %if.then, label %if.end 134 135if.then: ; preds = %while.body 136 br label %while.cond, !llvm.loop !0 137 138if.end: ; preds = %while.body 139 %2 = load i32, ptr %i, align 4 140 %inc = add nsw i32 %2, 1 141 store i32 %inc, ptr %i, align 4 142 br label %while.cond, !llvm.loop !0 143 144while.end: ; preds = %while.cond 145 %3 = load i32, ptr %retval, align 4 146 ret i32 %3 147} 148 149; CHECK-LABEL: test4_multilatch: 150; ALIGN: .p2align 6 151; ALIGN-NEXT: .LBB3_4: # %bb4 152define void @test4_multilatch(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { 153entry: 154 br label %bb1 155 156bb1: ; preds = %bb2, %bb4, %entry 157 call void @bar() 158 %cmp3 = icmp sgt i32 %c, 10 159 br i1 %cmp3, label %bb3, label %bb4 160 161bb2: ; preds = %bb3 162 call void @bar() 163 %cmp1 = icmp sgt i32 %a, 11 164 br i1 %cmp1, label %bb1, label %exit, !llvm.loop !0 165 166bb3: ; preds = %bb1 167 call void @bar() 168 %cmp2 = icmp sgt i32 %b, 12 169 br i1 %cmp2, label %bb2, label %exit 170 171bb4: ; preds = %bb1 172 call void @bar() 173 %cmp4 = icmp sgt i32 %d, 14 174 br i1 %cmp4, label %bb1, label %exit 175 176exit: ; preds = %bb2, %bb3, %bb4 177 ret void 178} 179 180declare void @bar() 181declare void @var() 182 183!0 = distinct !{!0, !1} 184!1 = !{!"llvm.loop.align", i32 64} 185!2 = distinct !{!2, !3} 186!3 = !{!"llvm.loop.align", i32 512} 187