diff --git a/llvm/test/Transforms/SimplifyCFG/ARM/branch-fold-threshold.ll b/llvm/test/Transforms/SimplifyCFG/ARM/branch-fold-threshold.ll new file mode 100644 index 00000000000000..370c6052fab5ed --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/ARM/branch-fold-threshold.ll @@ -0,0 +1,104 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -mtriple=thumbv8m.main %s -simplifycfg -S | FileCheck %s +; RUN: opt -mtriple=thumbv8a %s -simplifycfg -S | FileCheck %s + +define i32 @foo(i32 %a, i32 %b, i32 %c, i32 %d, i32* %input) { +; CHECK-LABEL: @foo( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[D:%.*]], 3 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]] +; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[CMP]], [[CMP1]] +; CHECK-NEXT: br i1 [[OR_COND]], label [[COND_FALSE:%.*]], label [[COND_END:%.*]] +; CHECK: cond.false: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[INPUT:%.*]], align 4 +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cond.end: +; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i32 [[COND]] +; +entry: + %cmp = icmp sgt i32 %d, 3 + br i1 %cmp, label %cond.end, label %lor.lhs.false + +lor.lhs.false: + %add = add nsw i32 %c, %a + %cmp1 = icmp slt i32 %add, %b + br i1 %cmp1, label %cond.false, label %cond.end + +cond.false: + %0 = load i32, i32* %input, align 4 + br label %cond.end + +cond.end: + %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ] + ret i32 %cond +} + +define i32 @foo_minsize(i32 %a, i32 %b, i32 %c, i32 %d, i32* %input) #0 { +; CHECK-LABEL: @foo_minsize( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[D:%.*]], 3 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]] +; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[CMP]], [[CMP1]] +; CHECK-NEXT: br i1 [[OR_COND]], label [[COND_FALSE:%.*]], label [[COND_END:%.*]] +; CHECK: cond.false: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[INPUT:%.*]], align 4 +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cond.end: +; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i32 [[COND]] +; +entry: + %cmp = icmp sgt i32 %d, 3 + br i1 %cmp, label %cond.end, label %lor.lhs.false + +lor.lhs.false: + %add = add nsw i32 %c, %a + %cmp1 = icmp slt i32 %add, %b + br i1 %cmp1, label %cond.false, label %cond.end + +cond.false: + %0 = load i32, i32* %input, align 4 + br label %cond.end + +cond.end: + %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ] + ret i32 %cond +} + +define i32 @foo_minsize_i64(i64 %a, i64 %b, i64 %c, i64 %d, i32* %input) #0 { +; CHECK-LABEL: @foo_minsize_i64( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i64 [[D:%.*]], 3 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[C:%.*]], [[A:%.*]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[ADD]], [[B:%.*]] +; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[CMP]], [[CMP1]] +; CHECK-NEXT: br i1 [[OR_COND]], label [[COND_FALSE:%.*]], label [[COND_END:%.*]] +; CHECK: cond.false: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[INPUT:%.*]], align 4 +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cond.end: +; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i32 [[COND]] +; +entry: + %cmp = icmp sgt i64 %d, 3 + br i1 %cmp, label %cond.end, label %lor.lhs.false + +lor.lhs.false: + %add = add nsw i64 %c, %a + %cmp1 = icmp slt i64 %add, %b + br i1 %cmp1, label %cond.false, label %cond.end + +cond.false: + %0 = load i32, i32* %input, align 4 + br label %cond.end + +cond.end: + %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ] + ret i32 %cond +} + +attributes #0 = { minsize optsize } diff --git a/llvm/test/Transforms/SimplifyCFG/ARM/select-costs.ll b/llvm/test/Transforms/SimplifyCFG/ARM/select-costs.ll index f2cc99f07c7717..c121061e0bea32 100644 --- a/llvm/test/Transforms/SimplifyCFG/ARM/select-costs.ll +++ b/llvm/test/Transforms/SimplifyCFG/ARM/select-costs.ll @@ -103,3 +103,101 @@ exit: ret i32 %phi.res } +define i32 @multiple_spec_select_costs_minsize(i8* %a, i32* %idx, i8 %in) #0 { +; V8M-LABEL: @multiple_spec_select_costs_minsize( +; V8M-NEXT: entry: +; V8M-NEXT: [[GEP_A_2:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i32 2 +; V8M-NEXT: [[INCDEC_PTR109_C4:%.*]] = getelementptr inbounds i8, i8* [[A]], i32 3 +; V8M-NEXT: [[ZERO:%.*]] = icmp ne i8 [[IN:%.*]], 0 +; V8M-NEXT: br i1 [[ZERO]], label [[FOR_INC_PREHEADER:%.*]], label [[SW_BB92:%.*]] +; V8M: sw.bb92: +; V8M-NEXT: [[C_OFF_I150:%.*]] = add i8 [[IN]], -48 +; V8M-NEXT: [[UGT_9:%.*]] = icmp ugt i8 [[C_OFF_I150]], 9 +; V8M-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[UGT_9]], i1 false, i1 true +; V8M-NEXT: [[SPEC_SELECT1:%.*]] = select i1 [[UGT_9]], i32 1, i32 7 +; V8M-NEXT: br label [[FOR_INC_PREHEADER]] +; V8M: for.inc.preheader: +; V8M-NEXT: [[STR_PH_0:%.*]] = phi i8* [ [[GEP_A_2]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR109_C4]], [[SW_BB92]] ] +; V8M-NEXT: [[CMP:%.*]] = phi i1 [ false, [[ENTRY]] ], [ [[SPEC_SELECT]], [[SW_BB92]] ] +; V8M-NEXT: [[PHI_RES:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[SPEC_SELECT1]], [[SW_BB92]] ] +; V8M-NEXT: br label [[FOR_INC:%.*]] +; V8M: for.inc: +; V8M-NEXT: [[STR_PH_1:%.*]] = phi i8* [ [[INCDEC_PTR109:%.*]], [[FOR_BODY:%.*]] ], [ [[STR_PH_0]], [[FOR_INC_PREHEADER]] ] +; V8M-NEXT: [[INCDEC_PTR109]] = getelementptr inbounds i8, i8* [[STR_PH_1]], i32 1 +; V8M-NEXT: [[LOAD_1:%.*]] = load i8, i8* [[INCDEC_PTR109]], align 1 +; V8M-NEXT: [[TOBOOL:%.*]] = icmp ne i8 [[LOAD_1]], 0 +; V8M-NEXT: [[AND:%.*]] = and i1 [[CMP]], [[TOBOOL]] +; V8M-NEXT: br i1 [[AND]], label [[FOR_BODY]], label [[EXIT:%.*]] +; V8M: for.body: +; V8M-NEXT: [[CMP_1:%.*]] = icmp eq i8 [[LOAD_1]], 1 +; V8M-NEXT: br i1 [[CMP_1]], label [[FOR_INC]], label [[SW_BB92]] +; V8M: exit: +; V8M-NEXT: ret i32 [[PHI_RES]] +; +; V8A-LABEL: @multiple_spec_select_costs_minsize( +; V8A-NEXT: entry: +; V8A-NEXT: [[GEP_A_2:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i32 2 +; V8A-NEXT: [[INCDEC_PTR109_C4:%.*]] = getelementptr inbounds i8, i8* [[A]], i32 3 +; V8A-NEXT: [[ZERO:%.*]] = icmp ne i8 [[IN:%.*]], 0 +; V8A-NEXT: br i1 [[ZERO]], label [[FOR_INC_PREHEADER:%.*]], label [[SW_BB92:%.*]] +; V8A: sw.bb92: +; V8A-NEXT: [[C_OFF_I150:%.*]] = add i8 [[IN]], -48 +; V8A-NEXT: [[UGT_9:%.*]] = icmp ugt i8 [[C_OFF_I150]], 9 +; V8A-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[UGT_9]], i1 false, i1 true +; V8A-NEXT: [[SPEC_SELECT1:%.*]] = select i1 [[UGT_9]], i32 1, i32 7 +; V8A-NEXT: br label [[FOR_INC_PREHEADER]] +; V8A: for.inc.preheader: +; V8A-NEXT: [[STR_PH_0:%.*]] = phi i8* [ [[GEP_A_2]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR109_C4]], [[SW_BB92]] ] +; V8A-NEXT: [[CMP:%.*]] = phi i1 [ false, [[ENTRY]] ], [ [[SPEC_SELECT]], [[SW_BB92]] ] +; V8A-NEXT: [[PHI_RES:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[SPEC_SELECT1]], [[SW_BB92]] ] +; V8A-NEXT: br label [[FOR_INC:%.*]] +; V8A: for.inc: +; V8A-NEXT: [[STR_PH_1:%.*]] = phi i8* [ [[INCDEC_PTR109:%.*]], [[FOR_BODY:%.*]] ], [ [[STR_PH_0]], [[FOR_INC_PREHEADER]] ] +; V8A-NEXT: [[INCDEC_PTR109]] = getelementptr inbounds i8, i8* [[STR_PH_1]], i32 1 +; V8A-NEXT: [[LOAD_1:%.*]] = load i8, i8* [[INCDEC_PTR109]], align 1 +; V8A-NEXT: [[TOBOOL:%.*]] = icmp ne i8 [[LOAD_1]], 0 +; V8A-NEXT: [[AND:%.*]] = and i1 [[CMP]], [[TOBOOL]] +; V8A-NEXT: br i1 [[AND]], label [[FOR_BODY]], label [[EXIT:%.*]] +; V8A: for.body: +; V8A-NEXT: [[CMP_1:%.*]] = icmp eq i8 [[LOAD_1]], 1 +; V8A-NEXT: br i1 [[CMP_1]], label [[FOR_INC]], label [[SW_BB92]] +; V8A: exit: +; V8A-NEXT: ret i32 [[PHI_RES]] +; +entry: + %gep.a.2 = getelementptr inbounds i8, i8* %a, i32 2 + %incdec.ptr109.c4 = getelementptr inbounds i8, i8* %a, i32 3 + %zero = icmp ne i8 %in, 0 + br i1 %zero , label %for.inc.preheader, label %sw.bb92 + +sw.bb92: + %c.off.i150 = add i8 %in, -48 + %ugt.9 = icmp ugt i8 %c.off.i150, 9 + br i1 %ugt.9, label %for.inc.preheader, label %select.unfold198 + +select.unfold198: + br label %for.inc.preheader + +for.inc.preheader: + %str.ph.0 = phi i8* [ %incdec.ptr109.c4, %select.unfold198 ], [ %incdec.ptr109.c4, %sw.bb92 ], [ %gep.a.2, %entry ] + %cmp = phi i1 [ true, %select.unfold198 ], [ false, %sw.bb92 ], [ false, %entry ] + %phi.res = phi i32 [ 7, %select.unfold198 ], [ 1, %sw.bb92 ], [ 1, %entry ] + br label %for.inc + +for.inc: + %str.ph.1 = phi i8* [ %incdec.ptr109, %for.body ], [ %str.ph.0, %for.inc.preheader ] + %incdec.ptr109 = getelementptr inbounds i8, i8* %str.ph.1, i32 1 + %load.1 = load i8, i8* %incdec.ptr109, align 1 + %tobool = icmp ne i8 %load.1, 0 + %and = and i1 %cmp, %tobool + br i1 %and, label %for.body, label %exit + +for.body: + %cmp.1 = icmp eq i8 %load.1, 1 + br i1 %cmp.1, label %for.inc, label %sw.bb92 + +exit: + ret i32 %phi.res +} + +attributes #0 = { minsize optsize }