Index: llvm/lib/Transforms/Utils/Local.cpp =================================================================== --- llvm/lib/Transforms/Utils/Local.cpp +++ llvm/lib/Transforms/Utils/Local.cpp @@ -2604,6 +2604,13 @@ combineMetadata(ReplInst, I, KnownIDs, false); } +static bool exceptedFromValueReplacements(const User *U) { + if (const IntrinsicInst *II = dyn_cast(U)) + if (II->getIntrinsicID() == Intrinsic::is_constant) + return true; + return false; +} + template static unsigned replaceDominatedUsesWith(Value *From, Value *To, const RootType &Root, @@ -2614,7 +2621,7 @@ for (Value::use_iterator UI = From->use_begin(), UE = From->use_end(); UI != UE;) { Use &U = *UI++; - if (!Dominates(Root, U)) + if (!Dominates(Root, U) || exceptedFromValueReplacements(U.getUser())) continue; U.set(To); LLVM_DEBUG(dbgs() << "Replace dominated use of '" << From->getName() @@ -2633,7 +2640,7 @@ UI != UE;) { Use &U = *UI++; auto *I = cast(U.getUser()); - if (I->getParent() == BB) + if (I->getParent() == BB || exceptedFromValueReplacements(I)) continue; U.set(To); ++Count; Index: llvm/test/Transforms/GVN/is-constant.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/GVN/is-constant.ll @@ -0,0 +1,30 @@ +; RUN: opt -gvn -S < %s | FileCheck %s +; +; Test that @llvm.is.constant() does not get its argument replaced with a +; (runtime) constant. + +; CHECK-LABEL: define i32 @fun +; CHECK: %2 = tail call i1 @llvm.is.constant.i32(i32 %shl) + +declare i1 @llvm.is.constant.i32(i32) + +@a = global i32 0, align 4 +@b = global i32 0, align 4 + +define i32 @fun() { +entry: + %0 = load i32, i32* @a + %shl = shl i32 %0, 12 + store i32 %shl, i32* @b + %1 = icmp eq i32 %shl, 0 + br i1 %1, label %land.rhs, label %land.end + +land.rhs: ; preds = %entry + %2 = tail call i1 @llvm.is.constant.i32(i32 %shl) + %phi.cast = zext i1 %2 to i32 + br label %land.end + +land.end: ; preds = %land.rhs, %entry + %3 = phi i32 [ 0, %entry ], [ %phi.cast, %land.rhs ] + ret i32 %3 +}