diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp --- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -5579,16 +5579,23 @@ << "\n"); return; } - // Bail out if we have a PHI on an EHPad that gets a value from a - // CatchSwitchInst. Because the CatchSwitchInst cannot be split, there is - // no good place to stick any instructions. + if (auto *PN = dyn_cast(U.getUser())) { auto *FirstNonPHI = PN->getParent()->getFirstNonPHI(); if (isa(FirstNonPHI) || isa(FirstNonPHI)) + // Bail out if we have a PHI on an EHPad that gets a value from a + // CatchSwitchInst. Because the CatchSwitchInst cannot be split, there + // is no good place to stick any instructions. for (BasicBlock *PredBB : PN->blocks()) if (isa(PredBB->getFirstNonPHI())) return; + + // Also bail out if we have a PHI with a value from a block ending in a + // CallBrInst, because those also can't be split for similar reasons. + for (BasicBlock *PredBB : PN->blocks()) + if (isa(PredBB->getTerminator())) + return; } } diff --git a/llvm/test/CodeGen/Generic/callbr-critical-edge-splitting.ll b/llvm/test/CodeGen/Generic/callbr-critical-edge-splitting.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Generic/callbr-critical-edge-splitting.ll @@ -0,0 +1,231 @@ +; RUN: llc < %s -o /dev/null + +; Test that we don't try to break a critical edge to a block ending in a callbr +; instruction. See https://github.com/ClangBuiltLinux/linux/issues/1252 + +source_filename = "test.c" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +$__llvm_profile_raw_version = comdat any + +$__llvm_profile_filename = comdat any + +@rdrand_int_ok = dso_local local_unnamed_addr global i32 0, align 4 +@random_ioctl_cmd = dso_local local_unnamed_addr global i32 0, align 4 +@random_ioctl_b = dso_local local_unnamed_addr global i32 0, align 4 +@random_ioctl_bytes = dso_local local_unnamed_addr global i32 0, align 4 +@write_pool_count = dso_local local_unnamed_addr global i32 0, align 4 +@__llvm_profile_raw_version = local_unnamed_addr constant i64 72057594037927941, comdat +@__profc__static_cpu_has = private global [3 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8 +@__profd__static_cpu_has = private global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 1706648762473371179, i64 1063705160746808702, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @__profc__static_cpu_has, i32 0, i32 0), i8* bitcast (i1 ()* @_static_cpu_has to i8*), i8* null, i32 3, [2 x i16] zeroinitializer }, section "__llvm_prf_data", align 8 +@__profc_rdrand_int = private global [3 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8 +@__profd_rdrand_int = private global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 -6327555252135034333, i64 1063705159444028162, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @__profc_rdrand_int, i32 0, i32 0), i8* bitcast (i32 ()* @rdrand_int to i8*), i8* null, i32 3, [2 x i16] zeroinitializer }, section "__llvm_prf_data", align 8 +@__profc_arch_get_random_int = private global [5 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8 +@__profd_arch_get_random_int = private global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 -8914602053785216465, i64 798733566790625302, i64* getelementptr inbounds ([5 x i64], [5 x i64]* @__profc_arch_get_random_int, i32 0, i32 0), i8* bitcast (i1 ()* @arch_get_random_int to i8*), i8* null, i32 5, [2 x i16] zeroinitializer }, section "__llvm_prf_data", align 8 +@__profc_random_ioctl = private global [6 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8 +@__profd_random_ioctl = private global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 -1609339618991391358, i64 694937220162189167, i64* getelementptr inbounds ([6 x i64], [6 x i64]* @__profc_random_ioctl, i32 0, i32 0), i8* bitcast (i32 ()* @random_ioctl to i8*), i8* null, i32 6, [2 x i16] zeroinitializer }, section "__llvm_prf_data", align 8 +@__llvm_prf_nm = private constant [56 x i8] c";6x\DA5\C8\C9\09\00 \0C\04@\ACt\09Q\8C\E0E\\\FB\17\05\7F\C3`QX\14:7LV\F0\E8\D2#Jg\10WCN\C4\9D\D1\DE}\0Ee=\B2\EC\17\14", section "__llvm_prf_names", align 1 +@__llvm_profile_filename = local_unnamed_addr constant [19 x i8] c"default_%m.profraw\00", comdat +@llvm.used = appending global [5 x i8*] [i8* getelementptr inbounds ([56 x i8], [56 x i8]* @__llvm_prf_nm, i32 0, i32 0), i8* bitcast ({ i64, i64, i64*, i8*, i8*, i32, [2 x i16] }* @__profd__static_cpu_has to i8*), i8* bitcast ({ i64, i64, i64*, i8*, i8*, i32, [2 x i16] }* @__profd_arch_get_random_int to i8*), i8* bitcast ({ i64, i64, i64*, i8*, i8*, i32, [2 x i16] }* @__profd_random_ioctl to i8*), i8* bitcast ({ i64, i64, i64*, i8*, i8*, i32, [2 x i16] }* @__profd_rdrand_int to i8*)], section "llvm.metadata" + +define dso_local zeroext i1 @_static_cpu_has() { +entry: + %pgocount = load i64, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @__profc__static_cpu_has, i64 0, i64 0), align 8 + %0 = add i64 %pgocount, 1 + store i64 %0, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @__profc__static_cpu_has, i64 0, i64 0), align 8 + callbr void asm sideeffect "", "X,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@_static_cpu_has, %return), i8* blockaddress(@_static_cpu_has, %t_no)) + to label %asm.fallthrough [label %return, label %t_no] + +asm.fallthrough: ; preds = %entry + %pgocount1 = load i64, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @__profc__static_cpu_has, i64 0, i64 2), align 8 + %1 = add i64 %pgocount1, 1 + store i64 %1, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @__profc__static_cpu_has, i64 0, i64 2), align 8 + br label %return + +t_no: ; preds = %entry + %pgocount2 = load i64, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @__profc__static_cpu_has, i64 0, i64 1), align 8 + %2 = add i64 %pgocount2, 1 + store i64 %2, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @__profc__static_cpu_has, i64 0, i64 1), align 8 + br label %return + +return: ; preds = %entry, %asm.fallthrough, %t_no + %retval.0 = phi i1 [ false, %t_no ], [ true, %asm.fallthrough ], [ true, %entry ] + ret i1 %retval.0 +} + +define dso_local i32 @rdrand_int() local_unnamed_addr { +entry: + %pgocount = load i64, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @__profc_rdrand_int, i64 0, i64 2), align 8 + %0 = add i64 %pgocount, 1 + store i64 %0, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @__profc_rdrand_int, i64 0, i64 2), align 8 + br label %do.body + +do.body: ; preds = %do.cond, %entry + %pgocount24 = phi i64 [ 0, %entry ], [ %2, %do.cond ] + %retry.0 = phi i32 [ 0, %entry ], [ %dec, %do.cond ] + tail call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"() + %1 = load i32, i32* @rdrand_int_ok, align 4 + %tobool.not = icmp eq i32 %1, 0 + br i1 %tobool.not, label %do.cond, label %cleanup + +do.cond: ; preds = %do.body + %2 = add nuw nsw i64 %pgocount24, 1 + %dec = add i32 %retry.0, -1 + %tobool1.not = icmp eq i32 %dec, 0 + br i1 %tobool1.not, label %do.cond.cleanup_crit_edge, label %do.body + +do.cond.cleanup_crit_edge: ; preds = %do.cond + %pgocount.promoted5 = load i64, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @__profc_rdrand_int, i64 0, i64 1), align 8 + %3 = add i64 %pgocount.promoted5, 4294967296 + store i64 %3, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @__profc_rdrand_int, i64 0, i64 1), align 8 + br label %cleanup + +cleanup: ; preds = %do.body, %do.cond.cleanup_crit_edge + %.sink = phi i64* [ getelementptr inbounds ([3 x i64], [3 x i64]* @__profc_rdrand_int, i64 0, i64 0), %do.cond.cleanup_crit_edge ], [ getelementptr inbounds ([3 x i64], [3 x i64]* @__profc_rdrand_int, i64 0, i64 1), %do.body ] + %pgocount24.sink = phi i64 [ 1, %do.cond.cleanup_crit_edge ], [ %pgocount24, %do.body ] + %retval.0 = phi i32 [ 0, %do.cond.cleanup_crit_edge ], [ 1, %do.body ] + %pgocount.promoted = load i64, i64* %.sink, align 8 + %4 = add i64 %pgocount.promoted, %pgocount24.sink + store i64 %4, i64* %.sink, align 8 + ret i32 %retval.0 +} + +define dso_local zeroext i1 @arch_get_random_int() local_unnamed_addr { +entry: + %pgocount = load i64, i64* getelementptr inbounds ([5 x i64], [5 x i64]* @__profc_arch_get_random_int, i64 0, i64 2), align 8 + %0 = add i64 %pgocount, 1 + store i64 %0, i64* getelementptr inbounds ([5 x i64], [5 x i64]* @__profc_arch_get_random_int, i64 0, i64 2), align 8 + callbr void asm sideeffect "", "X,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@arch_get_random_int, %do.body.i), i8* blockaddress(@arch_get_random_int, %cond.end)) + to label %asm.fallthrough.i [label %do.body.i, label %cond.end] + +asm.fallthrough.i: ; preds = %entry + %pgocount4 = load i64, i64* getelementptr inbounds ([5 x i64], [5 x i64]* @__profc_arch_get_random_int, i64 0, i64 4), align 8 + %1 = add i64 %pgocount4, 1 + store i64 %1, i64* getelementptr inbounds ([5 x i64], [5 x i64]* @__profc_arch_get_random_int, i64 0, i64 4), align 8 + br label %do.body.i + +do.body.i: ; preds = %entry, %asm.fallthrough.i, %do.cond.i + %pgocount58 = phi i64 [ %3, %do.cond.i ], [ 0, %asm.fallthrough.i ], [ 0, %entry ] + %retry.0.i = phi i32 [ %dec.i, %do.cond.i ], [ 0, %asm.fallthrough.i ], [ 0, %entry ] + tail call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"() + %2 = load i32, i32* @rdrand_int_ok, align 4 + %tobool.not.i = icmp eq i32 %2, 0 + br i1 %tobool.not.i, label %do.cond.i, label %rdrand_int.exit + +do.cond.i: ; preds = %do.body.i + %3 = add nuw nsw i64 %pgocount58, 1 + %dec.i = add i32 %retry.0.i, -1 + %tobool1.not.i = icmp eq i32 %dec.i, 0 + br i1 %tobool1.not.i, label %do.cond.i.rdrand_int.exit_crit_edge, label %do.body.i + +do.cond.i.rdrand_int.exit_crit_edge: ; preds = %do.cond.i + %pgocount.promoted9 = load i64, i64* getelementptr inbounds ([5 x i64], [5 x i64]* @__profc_arch_get_random_int, i64 0, i64 1), align 8 + %4 = add i64 %pgocount.promoted9, 4294967296 + store i64 %4, i64* getelementptr inbounds ([5 x i64], [5 x i64]* @__profc_arch_get_random_int, i64 0, i64 1), align 8 + br label %rdrand_int.exit + +rdrand_int.exit: ; preds = %do.body.i, %do.cond.i.rdrand_int.exit_crit_edge + %.sink = phi i64* [ getelementptr inbounds ([5 x i64], [5 x i64]* @__profc_arch_get_random_int, i64 0, i64 0), %do.cond.i.rdrand_int.exit_crit_edge ], [ getelementptr inbounds ([5 x i64], [5 x i64]* @__profc_arch_get_random_int, i64 0, i64 1), %do.body.i ] + %pgocount58.sink = phi i64 [ 1, %do.cond.i.rdrand_int.exit_crit_edge ], [ %pgocount58, %do.body.i ] + %pgocount.promoted = load i64, i64* %.sink, align 8 + %5 = add i64 %pgocount.promoted, %pgocount58.sink + store i64 %5, i64* %.sink, align 8 + %pgocount7 = load i64, i64* getelementptr inbounds ([5 x i64], [5 x i64]* @__profc_arch_get_random_int, i64 0, i64 3), align 8 + %6 = add i64 %pgocount7, 1 + store i64 %6, i64* getelementptr inbounds ([5 x i64], [5 x i64]* @__profc_arch_get_random_int, i64 0, i64 3), align 8 + %7 = xor i1 %tobool.not.i, true + br label %cond.end + +cond.end: ; preds = %entry, %rdrand_int.exit + %cond = phi i1 [ %7, %rdrand_int.exit ], [ false, %entry ] + ret i1 %cond +} + +define dso_local i32 @random_ioctl() local_unnamed_addr { +entry: + %pgocount = load i64, i64* getelementptr inbounds ([6 x i64], [6 x i64]* @__profc_random_ioctl, i64 0, i64 4), align 8 + %0 = add i64 %pgocount, 1 + store i64 %0, i64* getelementptr inbounds ([6 x i64], [6 x i64]* @__profc_random_ioctl, i64 0, i64 4), align 8 + %1 = load i32, i32* @random_ioctl_cmd, align 4 + %cond = icmp eq i32 %1, 0 + br i1 %cond, label %for.cond, label %sw.epilog + +for.cond: ; preds = %entry, %for.inc + %pgocount.promoted23 = phi i64 [ %pgocount.promoted2226, %for.inc ], [ 0, %entry ] + %pgocount919 = phi i64 [ %10, %for.inc ], [ 0, %entry ] + %pgocount816 = phi i64 [ %9, %for.inc ], [ 0, %entry ] + %pgocount613 = phi i64 [ %pgocount612, %for.inc ], [ 0, %entry ] + callbr void asm sideeffect "", "X,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@random_ioctl, %cond.true.i), i8* blockaddress(@random_ioctl, %for.end)) + to label %asm.fallthrough.i.i [label %cond.true.i, label %for.end] + +asm.fallthrough.i.i: ; preds = %for.cond + %2 = add i64 %pgocount613, 1 + br label %cond.true.i + +cond.true.i: ; preds = %asm.fallthrough.i.i, %for.cond + %pgocount612 = phi i64 [ %2, %asm.fallthrough.i.i ], [ %pgocount613, %for.cond ] + tail call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"() + %3 = load i32, i32* @rdrand_int_ok, align 4 + %tobool.not.i.i2 = icmp eq i32 %3, 0 + br i1 %tobool.not.i.i2, label %do.body.i.i.do.body.i.i_crit_edge, label %arch_get_random_int.exit + +do.body.i.i.do.body.i.i_crit_edge: ; preds = %cond.true.i, %do.body.i.i.do.body.i.i_crit_edge + %pgocount711 = phi i64 [ %4, %do.body.i.i.do.body.i.i_crit_edge ], [ 0, %cond.true.i ] + %dec.i.i5 = phi i32 [ %dec.i.i, %do.body.i.i.do.body.i.i_crit_edge ], [ -1, %cond.true.i ] + %4 = add nuw nsw i64 %pgocount711, 1 + tail call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"() + %5 = load i32, i32* @rdrand_int_ok, align 4 + %tobool.not.i.i = icmp eq i32 %5, 0 + %tobool.not.i.i.not = xor i1 %tobool.not.i.i, true + %dec.i.i = add i32 %dec.i.i5, -1 + %tobool1.not.i.i = icmp eq i32 %dec.i.i, 0 + %or.cond = or i1 %tobool1.not.i.i, %tobool.not.i.i.not + br i1 %or.cond, label %do.body.i.i.rdrand_int.exit.i_crit_edge, label %do.body.i.i.do.body.i.i_crit_edge + +do.body.i.i.rdrand_int.exit.i_crit_edge: ; preds = %do.body.i.i.do.body.i.i_crit_edge + %6 = add i64 %4, %pgocount.promoted23 + %7 = add i64 %pgocount816, 1 + br i1 %tobool.not.i.i, label %for.end, label %for.inc + +arch_get_random_int.exit: ; preds = %cond.true.i + %8 = add i64 %pgocount816, 1 + br label %for.inc + +for.inc: ; preds = %arch_get_random_int.exit, %do.body.i.i.rdrand_int.exit.i_crit_edge + %9 = phi i64 [ %7, %do.body.i.i.rdrand_int.exit.i_crit_edge ], [ %8, %arch_get_random_int.exit ] + %pgocount.promoted2226 = phi i64 [ %6, %do.body.i.i.rdrand_int.exit.i_crit_edge ], [ %pgocount.promoted23, %arch_get_random_int.exit ] + %10 = add i64 %pgocount919, 1 + %11 = load i32, i32* @random_ioctl_b, align 4 + %sub = add i32 %11, -4 + store i32 %sub, i32* @random_ioctl_b, align 4 + br label %for.cond + +for.end: ; preds = %do.body.i.i.rdrand_int.exit.i_crit_edge, %for.cond + %pgocount.promoted24 = phi i64 [ %pgocount.promoted23, %for.cond ], [ %6, %do.body.i.i.rdrand_int.exit.i_crit_edge ] + %pgocount817 = phi i64 [ %pgocount816, %for.cond ], [ %7, %do.body.i.i.rdrand_int.exit.i_crit_edge ] + %pgocount614 = phi i64 [ %pgocount613, %for.cond ], [ %pgocount612, %do.body.i.i.rdrand_int.exit.i_crit_edge ] + %pgocount.promoted15 = load i64, i64* getelementptr inbounds ([6 x i64], [6 x i64]* @__profc_random_ioctl, i64 0, i64 3), align 8 + %12 = add i64 %pgocount.promoted15, %pgocount614 + store i64 %12, i64* getelementptr inbounds ([6 x i64], [6 x i64]* @__profc_random_ioctl, i64 0, i64 3), align 8 + %pgocount.promoted18 = load i64, i64* getelementptr inbounds ([6 x i64], [6 x i64]* @__profc_random_ioctl, i64 0, i64 1), align 8 + %13 = add i64 %pgocount.promoted18, %pgocount817 + store i64 %13, i64* getelementptr inbounds ([6 x i64], [6 x i64]* @__profc_random_ioctl, i64 0, i64 1), align 8 + %pgocount.promoted21 = load i64, i64* getelementptr inbounds ([6 x i64], [6 x i64]* @__profc_random_ioctl, i64 0, i64 2), align 8 + %14 = add i64 %pgocount.promoted21, %pgocount919 + store i64 %14, i64* getelementptr inbounds ([6 x i64], [6 x i64]* @__profc_random_ioctl, i64 0, i64 2), align 8 + %pgocount.promoted25 = load i64, i64* getelementptr inbounds ([6 x i64], [6 x i64]* @__profc_random_ioctl, i64 0, i64 0), align 8 + %15 = add i64 %pgocount.promoted25, %pgocount.promoted24 + store i64 %15, i64* getelementptr inbounds ([6 x i64], [6 x i64]* @__profc_random_ioctl, i64 0, i64 0), align 8 + %pgocount10 = load i64, i64* getelementptr inbounds ([6 x i64], [6 x i64]* @__profc_random_ioctl, i64 0, i64 5), align 8 + %16 = add i64 %pgocount10, 1 + store i64 %16, i64* getelementptr inbounds ([6 x i64], [6 x i64]* @__profc_random_ioctl, i64 0, i64 5), align 8 + %17 = load i32, i32* @random_ioctl_bytes, align 4 + %18 = load i32, i32* @write_pool_count, align 4 + %sub2 = sub i32 %18, %17 + store i32 %sub2, i32* @write_pool_count, align 4 + br label %sw.epilog + +sw.epilog: ; preds = %entry, %for.end + ret i32 undef +}