diff --git a/llvm/test/Transforms/InstCombine/icmp-fold-into-phi.ll b/llvm/test/Transforms/InstCombine/icmp-fold-into-phi.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/icmp-fold-into-phi.ll @@ -0,0 +1,203 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i1 @SimpleTest(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @SimpleTest +; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: switch i32 [[X]], label [[BB1:%.*]] [ +; CHECK-NEXT: i32 0, label [[BB2:%.*]] +; CHECK-NEXT: i32 1, label [[BB3:%.*]] +; CHECK-NEXT: ] +; CHECK: bb1: +; CHECK-NEXT: br label [[BB2]] +; CHECK: bb2: +; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[Y]], [[BB1]] ] +; CHECK-NEXT: br label [[BB3]] +; CHECK: bb3: +; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[PHI1]], [[BB2]] ], [ 0, [[ENTRY]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[PHI2]], 1 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + switch i32 %x, label %bb1 [ + i32 0, label %bb2 + i32 1, label %bb3 + ] + +bb1: + br label %bb2 + +bb2: + %phi1 = phi i32 [ 1, %entry ], [ %y, %bb1 ] + br label %bb3 + +bb3: + %phi2 = phi i32 [ %phi1, %bb2 ], [ 0, %entry ] + %cmp = icmp ugt i32 %phi2, 1 + ret i1 %cmp +} + +; Test case derived from: +; llvm-test-suite/MultiSource/Benchmarks/MiBench/consumer-typeset/z10.c +@ObjTag = external global i32, align 4 +@ObjVal = external global ptr, align 8 +@RetVal1 = external global i32, align 4 +@RetVal2 = external global i32, align 4 + +@.str = constant [2 x i8] zeroinitializer, align 1 +@.str.1 = constant [4 x i8] c"TWO\00", align 1 +@.str.2 = constant [6 x i8] c"THREE\00", align 1 +@.str.3 = constant [5 x i8] c"FOUR\00", align 1 + +define i32 @Compute() { +; CHECK-LABEL: define i32 @Compute() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @ObjTag, align 4 +; CHECK-NEXT: [[CALL:%.*]] = tail call zeroext i1 @CheckValue(i32 noundef [[TMP0]]) +; CHECK-NEXT: br i1 [[CALL]], label [[SW_EPILOG:%.*]], label [[COND_FALSE:%.*]] +; CHECK: cond.false: +; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr @ObjVal, align 8 +; CHECK-NEXT: [[CALL1:%.*]] = tail call zeroext i1 @StrCmp(ptr noundef [[TMP1]], ptr noundef nonnull @.str) +; CHECK-NEXT: br i1 [[CALL1]], label [[SW_EPILOG]], label [[COND_FALSE2:%.*]] +; CHECK: cond.false2: +; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr @ObjVal, align 8 +; CHECK-NEXT: [[CALL2:%.*]] = tail call zeroext i1 @StrCmp(ptr noundef [[TMP2]], ptr noundef nonnull @.str.1) +; CHECK-NEXT: br i1 [[CALL2]], label [[SW_EPILOG]], label [[COND_FALSE3:%.*]] +; CHECK: cond.false3: +; CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr @ObjVal, align 8 +; CHECK-NEXT: [[CALL3:%.*]] = tail call zeroext i1 @StrCmp(ptr noundef [[TMP3]], ptr noundef nonnull @.str.2) +; CHECK-NEXT: br i1 [[CALL3]], label [[SW_BB:%.*]], label [[COND_END:%.*]] +; CHECK: cond.end: +; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr @ObjVal, align 8 +; CHECK-NEXT: [[CALL4:%.*]] = tail call zeroext i1 @StrCmp(ptr noundef [[TMP4]], ptr noundef nonnull @.str.3) +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CALL4]], i32 127, i32 126 +; CHECK-NEXT: br label [[SW_BB]] +; CHECK: sw.bb: +; CHECK-NEXT: [[COND2:%.*]] = phi i32 [ [[COND]], [[COND_END]] ], [ 128, [[COND_FALSE3]] ] +; CHECK-NEXT: [[CALL5:%.*]] = tail call zeroext i1 @CheckCond() +; CHECK-NEXT: [[NOT_CALL5:%.*]] = xor i1 [[CALL5]], true +; CHECK-NEXT: br label [[SW_EPILOG]] +; CHECK: sw.epilog: +; CHECK-NEXT: [[COND3:%.*]] = phi i32 [ [[COND2]], [[SW_BB]] ], [ 134, [[COND_FALSE2]] ], [ 2, [[COND_FALSE]] ], [ 1, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[TAGERROR_0:%.*]] = phi i1 [ [[NOT_CALL5]], [[SW_BB]] ], [ false, [[COND_FALSE2]] ], [ false, [[COND_FALSE]] ], [ false, [[ENTRY]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[COND3]], 2 +; CHECK-NEXT: [[BRMERGE:%.*]] = or i1 [[CMP]], [[TAGERROR_0]] +; CHECK-NEXT: [[RETVAL2_VAL:%.*]] = load i32, ptr @RetVal2, align 4 +; CHECK-NEXT: [[RETVAL1_VAL:%.*]] = load i32, ptr @RetVal1, align 4 +; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[BRMERGE]], i32 [[RETVAL2_VAL]], i32 [[RETVAL1_VAL]] +; CHECK-NEXT: ret i32 [[RETVAL_0]] +; +entry: + %0 = load i32, ptr @ObjTag, align 4 + %call = tail call zeroext i1 @CheckValue(i32 noundef %0) + br i1 %call, label %sw.epilog, label %cond.false + +cond.false: + %1 = load ptr, ptr @ObjVal, align 8 + %call1 = tail call zeroext i1 @StrCmp(ptr noundef %1, ptr noundef nonnull @.str) + br i1 %call1, label %sw.epilog, label %cond.false2 + +cond.false2: + %2 = load ptr, ptr @ObjVal, align 8 + %call2 = tail call zeroext i1 @StrCmp(ptr noundef %2, ptr noundef nonnull @.str.1) + br i1 %call2, label %sw.epilog, label %cond.false3 + +cond.false3: + %3 = load ptr, ptr @ObjVal, align 8 + %call3 = tail call zeroext i1 @StrCmp(ptr noundef %3, ptr noundef nonnull @.str.2) + br i1 %call3, label %sw.bb, label %cond.end + +cond.end: + %4 = load ptr, ptr @ObjVal, align 8 + %call4 = tail call zeroext i1 @StrCmp(ptr noundef %4, ptr noundef nonnull @.str.3) + %cond = select i1 %call4, i32 127, i32 126 + br label %sw.bb + +sw.bb: + %cond2 = phi i32 [ %cond, %cond.end ], [ 128, %cond.false3 ] + %call5 = tail call zeroext i1 @CheckCond() + %not.call5 = xor i1 %call5, true + br label %sw.epilog + +sw.epilog: + %cond3 = phi i32 [ %cond2, %sw.bb ], [ 134, %cond.false2 ], [ 2, %cond.false ], [ 1, %entry ] + %TagError.0 = phi i1 [ %not.call5, %sw.bb ], [ false, %cond.false2 ], [ false, %cond.false ], [ false, %entry ] + %cmp = icmp ult i32 %cond3, 2 + %brmerge = or i1 %cmp, %TagError.0 + %RetVal2.val = load i32, ptr @RetVal2, align 4 + %RetVal1.val = load i32, ptr @RetVal1, align 4 + %retval.0 = select i1 %brmerge, i32 %RetVal2.val, i32 %RetVal1.val + ret i32 %retval.0 +} + +define i1 @ComputeSimplified() { +; CHECK-LABEL: define i1 @ComputeSimplified() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @ObjTag, align 4 +; CHECK-NEXT: [[CALL:%.*]] = tail call zeroext i1 @CheckValue(i32 noundef [[TMP0]]) +; CHECK-NEXT: br i1 [[CALL]], label [[SW_EPILOG:%.*]], label [[COND_FALSE:%.*]] +; CHECK: cond.false: +; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr @ObjVal, align 8 +; CHECK-NEXT: [[CALL1:%.*]] = tail call zeroext i1 @StrCmp(ptr noundef [[TMP1]], ptr noundef nonnull @.str) +; CHECK-NEXT: br i1 [[CALL1]], label [[SW_EPILOG]], label [[COND_FALSE2:%.*]] +; CHECK: cond.false2: +; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr @ObjVal, align 8 +; CHECK-NEXT: [[CALL2:%.*]] = tail call zeroext i1 @StrCmp(ptr noundef [[TMP2]], ptr noundef nonnull @.str.1) +; CHECK-NEXT: br i1 [[CALL2]], label [[SW_EPILOG]], label [[COND_FALSE3:%.*]] +; CHECK: cond.false3: +; CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr @ObjVal, align 8 +; CHECK-NEXT: [[CALL3:%.*]] = tail call zeroext i1 @StrCmp(ptr noundef [[TMP3]], ptr noundef nonnull @.str.2) +; CHECK-NEXT: br i1 [[CALL3]], label [[SW_BB:%.*]], label [[COND_END:%.*]] +; CHECK: cond.end: +; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr @ObjVal, align 8 +; CHECK-NEXT: [[CALL4:%.*]] = tail call zeroext i1 @StrCmp(ptr noundef [[TMP4]], ptr noundef nonnull @.str.3) +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CALL4]], i32 127, i32 126 +; CHECK-NEXT: br label [[SW_BB]] +; CHECK: sw.bb: +; CHECK-NEXT: [[COND2:%.*]] = phi i32 [ [[COND]], [[COND_END]] ], [ 128, [[COND_FALSE3]] ] +; CHECK-NEXT: br label [[SW_EPILOG]] +; CHECK: sw.epilog: +; CHECK-NEXT: [[COND3:%.*]] = phi i32 [ [[COND2]], [[SW_BB]] ], [ 134, [[COND_FALSE2]] ], [ 2, [[COND_FALSE]] ], [ 1, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[COND3]], 2 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %0 = load i32, ptr @ObjTag, align 4 + %call = tail call zeroext i1 @CheckValue(i32 noundef %0) + br i1 %call, label %sw.epilog, label %cond.false + +cond.false: + %1 = load ptr, ptr @ObjVal, align 8 + %call1 = tail call zeroext i1 @StrCmp(ptr noundef %1, ptr noundef nonnull @.str) + br i1 %call1, label %sw.epilog, label %cond.false2 + +cond.false2: + %2 = load ptr, ptr @ObjVal, align 8 + %call2 = tail call zeroext i1 @StrCmp(ptr noundef %2, ptr noundef nonnull @.str.1) + br i1 %call2, label %sw.epilog, label %cond.false3 + +cond.false3: + %3 = load ptr, ptr @ObjVal, align 8 + %call3 = tail call zeroext i1 @StrCmp(ptr noundef %3, ptr noundef nonnull @.str.2) + br i1 %call3, label %sw.bb, label %cond.end + +cond.end: + %4 = load ptr, ptr @ObjVal, align 8 + %call4 = tail call zeroext i1 @StrCmp(ptr noundef %4, ptr noundef nonnull @.str.3) + %cond = select i1 %call4, i32 127, i32 126 + br label %sw.bb + +sw.bb: + %cond2 = phi i32 [ %cond, %cond.end ], [ 128, %cond.false3 ] + br label %sw.epilog + +sw.epilog: + %cond3 = phi i32 [ %cond2, %sw.bb ], [ 134, %cond.false2 ], [ 2, %cond.false ], [ 1, %entry ] + %cmp = icmp ult i32 %cond3, 2 + ret i1 %cmp +} + +declare zeroext i1 @CheckValue(i32 noundef) +declare zeroext i1 @StrCmp(ptr noundef, ptr noundef) +declare zeroext i1 @CheckCond()