[llvm] b64e7e0 - [SimplifyCFG] Add tests for hoisting of commutative instructions (NFC)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 19 08:13:31 PDT 2024


Author: Nikita Popov
Date: 2024-08-19T17:13:21+02:00
New Revision: b64e7e07e544d62ab132fc9f5c4153d4807a5fa3

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

LOG: [SimplifyCFG] Add tests for hoisting of commutative instructions (NFC)

Added: 
    

Modified: 
    llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll b/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll
index 991b89a486e0f5..e2705dc95ab979 100644
--- a/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll
+++ b/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll
@@ -154,3 +154,350 @@ exit:                                             ; preds = %bb2, %bb1, %bb0
   %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ]
   ret i1 %result
 }
+
+declare void @foo()
+
+define i1 @test_icmp_simple(i1 %c, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_icmp_simple(
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i1 [ [[CMP1:%.*]], [[IF]] ], [ [[CMP2:%.*]], [[ELSE]] ]
+; CHECK-NEXT:    ret i1 [[COMMON_RET_OP]]
+; CHECK:       if:
+; CHECK-NEXT:    [[CMP1]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[CMP2]] = icmp ugt i32 [[B]], [[A]]
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  br i1 %c, label %if, label %else
+
+if:
+  %cmp1 = icmp ult i32 %a, %b
+  call void @foo()
+  ret i1 %cmp1
+
+else:
+  %cmp2 = icmp ugt i32 %b, %a
+  call void @bar()
+  ret i1 %cmp2
+}
+
+define void @test_icmp_complex(i1 %c, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_icmp_complex(
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[IF2:%.*]], label [[ELSE2:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[B]], [[A]]
+; CHECK-NEXT:    br i1 [[CMP2]], label [[IF2]], label [[ELSE2]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    ret void
+; CHECK:       if2:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       else2:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  br i1 %c, label %if, label %else
+
+if:
+  %cmp1 = icmp ult i32 %a, %b
+  br i1 %cmp1, label %if2, label %else2
+
+else:
+  %cmp2 = icmp ugt i32 %b, %a
+  br i1 %cmp2, label %if2, label %else2
+
+if2:
+  call void @foo()
+  ret void
+
+else2:
+  call void @bar()
+  ret void
+}
+
+define i1 @test_icmp_wrong_operands(i1 %c, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_icmp_wrong_operands(
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i1 [ [[CMP1:%.*]], [[IF]] ], [ [[CMP2:%.*]], [[ELSE]] ]
+; CHECK-NEXT:    ret i1 [[COMMON_RET_OP]]
+; CHECK:       if:
+; CHECK-NEXT:    [[CMP1]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[CMP2]] = icmp ugt i32 [[A]], [[B]]
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  br i1 %c, label %if, label %else
+
+if:
+  %cmp1 = icmp ult i32 %a, %b
+  call void @foo()
+  ret i1 %cmp1
+
+else:
+  %cmp2 = icmp ugt i32 %a, %b
+  call void @bar()
+  ret i1 %cmp2
+}
+
+define i1 @test_icmp_wrong_pred(i1 %c, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_icmp_wrong_pred(
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i1 [ [[CMP1:%.*]], [[IF]] ], [ [[CMP2:%.*]], [[ELSE]] ]
+; CHECK-NEXT:    ret i1 [[COMMON_RET_OP]]
+; CHECK:       if:
+; CHECK-NEXT:    [[CMP1]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[CMP2]] = icmp uge i32 [[B]], [[A]]
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  br i1 %c, label %if, label %else
+
+if:
+  %cmp1 = icmp ult i32 %a, %b
+  call void @foo()
+  ret i1 %cmp1
+
+else:
+  %cmp2 = icmp uge i32 %b, %a
+  call void @bar()
+  ret i1 %cmp2
+}
+
+define i32 @test_binop(i1 %c, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_binop(
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
+; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
+; CHECK:       if:
+; CHECK-NEXT:    [[OP1]] = add i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[OP2]] = add i32 [[B]], [[A]]
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  br i1 %c, label %if, label %else
+
+if:
+  %op1 = add i32 %a, %b
+  call void @foo()
+  ret i32 %op1
+
+else:
+  %op2 = add i32 %b, %a
+  call void @bar()
+  ret i32 %op2
+}
+
+define i32 @test_binop_flags(i1 %c, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_binop_flags(
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
+; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
+; CHECK:       if:
+; CHECK-NEXT:    [[OP1]] = add nuw nsw i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[OP2]] = add nsw i32 [[B]], [[A]]
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  br i1 %c, label %if, label %else
+
+if:
+  %op1 = add nuw nsw i32 %a, %b
+  call void @foo()
+  ret i32 %op1
+
+else:
+  %op2 = add nsw i32 %b, %a
+  call void @bar()
+  ret i32 %op2
+}
+
+define i32 @test_binop_not_commutative(i1 %c, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_binop_not_commutative(
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
+; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
+; CHECK:       if:
+; CHECK-NEXT:    [[OP1]] = sub i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[OP2]] = sub i32 [[B]], [[A]]
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  br i1 %c, label %if, label %else
+
+if:
+  %op1 = sub i32 %a, %b
+  call void @foo()
+  ret i32 %op1
+
+else:
+  %op2 = sub i32 %b, %a
+  call void @bar()
+  ret i32 %op2
+}
+
+define i32 @test_binop_wrong_ops(i1 %c, i32 %a, i32 %b, i32 %d) {
+; CHECK-LABEL: @test_binop_wrong_ops(
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
+; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
+; CHECK:       if:
+; CHECK-NEXT:    [[OP1]] = add i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[OP2]] = add i32 [[B]], [[D:%.*]]
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  br i1 %c, label %if, label %else
+
+if:
+  %op1 = add i32 %a, %b
+  call void @foo()
+  ret i32 %op1
+
+else:
+  %op2 = add i32 %b, %d
+  call void @bar()
+  ret i32 %op2
+}
+
+define i32 @test_intrin(i1 %c, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_intrin(
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
+; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
+; CHECK:       if:
+; CHECK-NEXT:    [[OP1]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 [[B:%.*]])
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[OP2]] = call i32 @llvm.umin.i32(i32 [[B]], i32 [[A]])
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  br i1 %c, label %if, label %else
+
+if:
+  %op1 = call i32 @llvm.umin(i32 %a, i32 %b)
+  call void @foo()
+  ret i32 %op1
+
+else:
+  %op2 = call i32 @llvm.umin(i32 %b, i32 %a)
+  call void @bar()
+  ret i32 %op2
+}
+
+define i32 @test_intrin_not_same(i1 %c, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_intrin_not_same(
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
+; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
+; CHECK:       if:
+; CHECK-NEXT:    [[OP1]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 [[B:%.*]])
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[OP2]] = call i32 @llvm.umax.i32(i32 [[B]], i32 [[A]])
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  br i1 %c, label %if, label %else
+
+if:
+  %op1 = call i32 @llvm.umin(i32 %a, i32 %b)
+  call void @foo()
+  ret i32 %op1
+
+else:
+  %op2 = call i32 @llvm.umax(i32 %b, i32 %a)
+  call void @bar()
+  ret i32 %op2
+}
+
+define float @test_intrin_3arg(i1 %c, float %a, float %b, float %d) {
+; CHECK-LABEL: @test_intrin_3arg(
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi float [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
+; CHECK-NEXT:    ret float [[COMMON_RET_OP]]
+; CHECK:       if:
+; CHECK-NEXT:    [[OP1]] = call float @llvm.fma.f32(float [[A:%.*]], float [[B:%.*]], float [[D:%.*]])
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[OP2]] = call float @llvm.fma.f32(float [[B]], float [[A]], float [[D]])
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  br i1 %c, label %if, label %else
+
+if:
+  %op1 = call float @llvm.fma(float %a, float %b, float %d)
+  call void @foo()
+  ret float %op1
+
+else:
+  %op2 = call float @llvm.fma(float %b, float %a, float %d)
+  call void @bar()
+  ret float %op2
+}
+
+define float @test_intrin_3arg_wrong_args_commuted(i1 %c, float %a, float %b, float %d) {
+; CHECK-LABEL: @test_intrin_3arg_wrong_args_commuted(
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi float [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
+; CHECK-NEXT:    ret float [[COMMON_RET_OP]]
+; CHECK:       if:
+; CHECK-NEXT:    [[OP1]] = call float @llvm.fma.f32(float [[A:%.*]], float [[B:%.*]], float [[D:%.*]])
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[OP2]] = call float @llvm.fma.f32(float [[A]], float [[D]], float [[B]])
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  br i1 %c, label %if, label %else
+
+if:
+  %op1 = call float @llvm.fma(float %a, float %b, float %d)
+  call void @foo()
+  ret float %op1
+
+else:
+  %op2 = call float @llvm.fma(float %a, float %d, float %b)
+  call void @bar()
+  ret float %op2
+}


        


More information about the llvm-commits mailing list