[llvm] 153144b - [SimplifyCFG] Preserve metadata when unconditionalizing branches (constant condition).

Michael Kruse via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 26 08:57:37 PDT 2021


Author: Michael Kruse
Date: 2021-04-26T10:57:31-05:00
New Revision: 153144be40855ca1e35e1bfca082e10f553bb2e5

URL: https://github.com/llvm/llvm-project/commit/153144be40855ca1e35e1bfca082e10f553bb2e5
DIFF: https://github.com/llvm/llvm-project/commit/153144be40855ca1e35e1bfca082e10f553bb2e5.diff

LOG: [SimplifyCFG] Preserve metadata when unconditionalizing branches (constant condition).

When replacing a conditional branch by an unconditional one because the condition is a constant, transfer the metadata to the new branch instruction.

Part of fix for llvm.org/PR50060

Reviewed By: lebedev.ri

Differential Revision: https://reviews.llvm.org/D101141

Added: 
    llvm/test/Transforms/SimplifyCFG/pr50060-constantfold-loopid.ll

Modified: 
    llvm/lib/Transforms/Utils/Local.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 255bb8dd4a9f..b61c369734df 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -167,7 +167,12 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions,
       OldDest->removePredecessor(BB);
 
       // Replace the conditional branch with an unconditional one.
-      Builder.CreateBr(Destination);
+      BranchInst *NewBI = Builder.CreateBr(Destination);
+
+      // Transfer the metadata to the new branch instruction.
+      NewBI->copyMetadata(*BI, {LLVMContext::MD_loop, LLVMContext::MD_dbg,
+                                LLVMContext::MD_annotation});
+
       BI->eraseFromParent();
       if (DTU)
         DTU->applyUpdates({{DominatorTree::Delete, BB, OldDest}});

diff  --git a/llvm/test/Transforms/SimplifyCFG/pr50060-constantfold-loopid.ll b/llvm/test/Transforms/SimplifyCFG/pr50060-constantfold-loopid.ll
new file mode 100644
index 000000000000..2f12e1098430
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/pr50060-constantfold-loopid.ll
@@ -0,0 +1,158 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+;
+; The branch in the latch do.cond is conditional by a constant and the
+; conditional branch replaced by an unconditional one.
+; Ensure that the llvm.loop metadata is transferred to the new branch
+; (In for.cond.cleanup after further simplifications).
+;
+; llvm.org/PR50060
+;
+
+ at n = dso_local global i32 0, align 4
+ at C = dso_local global i32 0, align 4
+
+; Function Attrs: nounwind
+define dso_local void @_Z6test01v() addrspace(1) #0 {
+; CHECK-LABEL: @_Z6test01v(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[J:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    [[I:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    br label [[DO_BODY:%.*]]
+; CHECK:       do.body:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @C, align 4, !tbaa [[TBAA2:![0-9]+]]
+; CHECK-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i32* [[J]] to i8*
+; CHECK-NEXT:    call addrspace(1) void @llvm.lifetime.start.p0i8(i64 4, i8* [[TMP1]]) #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    store i32 0, i32* [[J]], align 4, !tbaa [[TBAA2]]
+; CHECK-NEXT:    br label [[FOR_COND:%.*]]
+; CHECK:       for.cond:
+; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[J]], align 4, !tbaa [[TBAA2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP2]], 3
+; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
+; CHECK:       for.cond.cleanup:
+; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i32* [[J]] to i8*
+; CHECK-NEXT:    call addrspace(1) void @llvm.lifetime.end.p0i8(i64 4, i8* [[TMP3]]) #[[ATTR2]]
+; CHECK-NEXT:    br label [[DO_BODY]], !llvm.loop [[LOOP6:![0-9]+]]
+; CHECK:       for.body:
+; CHECK-NEXT:    store i32 undef, i32* [[I]], align 4
+; CHECK-NEXT:    [[TMP4:%.*]] = bitcast i32* [[I]] to i8*
+; CHECK-NEXT:    call addrspace(1) void @llvm.lifetime.start.p0i8(i64 4, i8* [[TMP4]]) #[[ATTR2]]
+; CHECK-NEXT:    store i32 0, i32* [[I]], align 4, !tbaa [[TBAA2]]
+; CHECK-NEXT:    br label [[FOR_COND1:%.*]]
+; CHECK:       for.cond1:
+; CHECK-NEXT:    [[TMP5:%.*]] = load i32, i32* [[I]], align 4, !tbaa [[TBAA2]]
+; CHECK-NEXT:    [[TMP6:%.*]] = load i32, i32* @n, align 4, !tbaa [[TBAA2]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[TMP5]], [[TMP6]]
+; CHECK-NEXT:    br i1 [[CMP2]], label [[FOR_BODY4:%.*]], label [[FOR_COND_CLEANUP3:%.*]]
+; CHECK:       for.cond.cleanup3:
+; CHECK-NEXT:    [[TMP7:%.*]] = bitcast i32* [[I]] to i8*
+; CHECK-NEXT:    call addrspace(1) void @llvm.lifetime.end.p0i8(i64 4, i8* [[TMP7]]) #[[ATTR2]]
+; CHECK-NEXT:    [[TMP8:%.*]] = load i32, i32* [[J]], align 4, !tbaa [[TBAA2]]
+; CHECK-NEXT:    [[INC7:%.*]] = add nsw i32 [[TMP8]], 1
+; CHECK-NEXT:    store i32 [[INC7]], i32* [[J]], align 4, !tbaa [[TBAA2]]
+; CHECK-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP8:![0-9]+]]
+; CHECK:       for.body4:
+; CHECK-NEXT:    [[TMP9:%.*]] = load i32, i32* [[I]], align 4, !tbaa [[TBAA2]]
+; CHECK-NEXT:    store volatile i32 [[TMP9]], i32* @C, align 4, !tbaa [[TBAA2]]
+; CHECK-NEXT:    [[TMP10:%.*]] = load i32, i32* [[I]], align 4, !tbaa [[TBAA2]]
+; CHECK-NEXT:    [[INC5:%.*]] = add nsw i32 [[TMP10]], 1
+; CHECK-NEXT:    store i32 [[INC5]], i32* [[I]], align 4, !tbaa [[TBAA2]]
+; CHECK-NEXT:    br label [[FOR_COND1]], !llvm.loop [[LOOP11:![0-9]+]]
+;
+entry:
+  %j = alloca i32, align 4
+  %i = alloca i32, align 4
+  br label %do.body
+
+do.body:                                          ; preds = %do.cond, %entry
+  %0 = load i32, i32* @C, align 4, !tbaa !2
+  %inc = add nsw i32 %0, 1
+  %1 = bitcast i32* %j to i8*
+  call addrspace(1) void @llvm.lifetime.start.p0i8(i64 4, i8* %1) #2
+  store i32 0, i32* %j, align 4, !tbaa !2
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc6, %do.body
+  %2 = load i32, i32* %j, align 4, !tbaa !2
+  %cmp = icmp slt i32 %2, 3
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  %3 = bitcast i32* %j to i8*
+  call addrspace(1) void @llvm.lifetime.end.p0i8(i64 4, i8* %3) #2
+  br label %for.end8
+
+for.body:                                         ; preds = %for.cond
+  store i32 undef, i32* %i, align 4
+  %4 = bitcast i32* %i to i8*
+  call addrspace(1) void @llvm.lifetime.start.p0i8(i64 4, i8* %4) #2
+  store i32 0, i32* %i, align 4, !tbaa !2
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %5 = load i32, i32* %i, align 4, !tbaa !2
+  %6 = load i32, i32* @n, align 4, !tbaa !2
+  %cmp2 = icmp slt i32 %5, %6
+  br i1 %cmp2, label %for.body4, label %for.cond.cleanup3
+
+for.cond.cleanup3:                                ; preds = %for.cond1
+  %7 = bitcast i32* %i to i8*
+  call addrspace(1) void @llvm.lifetime.end.p0i8(i64 4, i8* %7) #2
+  br label %for.end
+
+for.body4:                                        ; preds = %for.cond1
+  %8 = load i32, i32* %i, align 4, !tbaa !2
+  store volatile i32 %8, i32* @C, align 4, !tbaa !2
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body4
+  %9 = load i32, i32* %i, align 4, !tbaa !2
+  %inc5 = add nsw i32 %9, 1
+  store i32 %inc5, i32* %i, align 4, !tbaa !2
+  br label %for.cond1, !llvm.loop !6
+
+for.end:                                          ; preds = %for.cond.cleanup3
+  br label %for.inc6
+
+for.inc6:                                         ; preds = %for.end
+  %10 = load i32, i32* %j, align 4, !tbaa !2
+  %inc7 = add nsw i32 %10, 1
+  store i32 %inc7, i32* %j, align 4, !tbaa !2
+  br label %for.cond, !llvm.loop !8
+
+for.end8:                                         ; preds = %for.cond.cleanup
+  br label %do.cond
+
+do.cond:                                          ; preds = %for.end8
+  br i1 true, label %do.body, label %do.end, !llvm.loop !10
+
+do.end:                                           ; preds = %do.cond
+  ret void
+}
+
+; Function Attrs: argmemonly nofree nosync nounwind willreturn
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) addrspace(1) #1
+
+; Function Attrs: argmemonly nofree nosync nounwind willreturn
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) addrspace(1) #1
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nofree nosync nounwind willreturn }
+attributes #2 = { nounwind }
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang)"}
+!2 = !{!3, !3, i64 0, i64 4}
+!3 = !{!4, i64 4, !"int"}
+!4 = !{!5, i64 1, !"omnipotent char"}
+!5 = !{!"Simple C++ TBAA"}
+!6 = distinct !{!6, !7}
+!7 = !{!"llvm.loop.mustprogress"}
+!8 = distinct !{!8, !7, !9}
+!9 = !{!"llvm.loop.unroll.disable"}
+!10 = distinct !{!10, !11}
+!11 = !{!"llvm.loop.unroll.count", i32 2}


        


More information about the llvm-commits mailing list