[MergeICmp] Make instruction move robust against empty block (NFCI)
authorNikita Popov <npopov@redhat.com>
Fri, 4 Mar 2022 10:13:40 +0000 (11:13 +0100)
committerNikita Popov <npopov@redhat.com>
Fri, 4 Mar 2022 10:15:08 +0000 (11:15 +0100)
Use the overload that support moving into an empty block. I don't
think that this situation can occur right now, but it can happen
with the change from e7fb1c15cb85d748c1c4fdd5a2eb5613ec7bef1d,
and the test is derived from the issue reported there.

llvm/lib/Transforms/Scalar/MergeICmps.cpp
llvm/test/Transforms/MergeICmps/X86/no-gep-other-work.ll [new file with mode: 0644]

index d38e362..1c1026b 100644 (file)
@@ -270,9 +270,8 @@ void BCECmpBlock::split(BasicBlock *NewParent, AliasAnalysis &AA) const {
   }
 
   // Do the actual spliting.
-  for (Instruction *Inst : reverse(OtherInsts)) {
-    Inst->moveBefore(&*NewParent->begin());
-  }
+  for (Instruction *Inst : reverse(OtherInsts))
+    Inst->moveBefore(*NewParent, NewParent->begin());
 }
 
 bool BCECmpBlock::canSplit(AliasAnalysis &AA) const {
diff --git a/llvm/test/Transforms/MergeICmps/X86/no-gep-other-work.ll b/llvm/test/Transforms/MergeICmps/X86/no-gep-other-work.ll
new file mode 100644 (file)
index 0000000..3ffbd93
--- /dev/null
@@ -0,0 +1,48 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -mergeicmps < %s | FileCheck %s
+
+; This does not use a GEP for the zero-offset comparison and requires a
+; split for other work.
+
+target triple = "x86_64-grtev4-linux-gnu"
+
+declare void @other_work()
+
+define i1 @test(i8* dereferenceable(2) %arg, i8* dereferenceable(2) %arg1) {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    call void @other_work()
+; CHECK-NEXT:    [[ARG_OFF:%.*]] = getelementptr inbounds i8, i8* [[ARG:%.*]], i64 1
+; CHECK-NEXT:    [[ARG1_OFF:%.*]] = getelementptr inbounds i8, i8* [[ARG1:%.*]], i64 1
+; CHECK-NEXT:    [[ARG_OFF_VAL:%.*]] = load i8, i8* [[ARG_OFF]], align 1
+; CHECK-NEXT:    [[ARG1_OFF_VAL:%.*]] = load i8, i8* [[ARG1_OFF]], align 1
+; CHECK-NEXT:    [[CMP_OFF:%.*]] = icmp eq i8 [[ARG_OFF_VAL]], [[ARG1_OFF_VAL]]
+; CHECK-NEXT:    br i1 [[CMP_OFF]], label [[IF:%.*]], label [[JOIN:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[ARG_VAL:%.*]] = load i8, i8* [[ARG]], align 1
+; CHECK-NEXT:    [[ARG1_VAL:%.*]] = load i8, i8* [[ARG1]], align 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[ARG_VAL]], [[ARG1_VAL]]
+; CHECK-NEXT:    br label [[JOIN]]
+; CHECK:       join:
+; CHECK-NEXT:    [[PHI:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP]], [[IF]] ]
+; CHECK-NEXT:    ret i1 [[PHI]]
+;
+entry:
+  call void @other_work()
+  %arg.off = getelementptr inbounds i8, i8* %arg, i64 1
+  %arg1.off = getelementptr inbounds i8, i8* %arg1, i64 1
+  %arg.off.val = load i8, i8* %arg.off
+  %arg1.off.val = load i8, i8* %arg1.off
+  %cmp.off = icmp eq i8 %arg.off.val, %arg1.off.val
+  br i1 %cmp.off, label %if, label %join
+
+if:
+  %arg.val = load i8, i8* %arg
+  %arg1.val = load i8, i8* %arg1
+  %cmp = icmp eq i8 %arg.val, %arg1.val
+  br label %join
+
+join:
+  %phi = phi i1 [ false, %entry ], [ %cmp, %if ]
+  ret i1 %phi
+}