#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/IR/AssemblyAnnotationWriter.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/InstIterator.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
renameUses(OpsToRename);
}
-// Create a ssa_copy declaration with custom mangling, because
-// Intrinsic::getDeclaration does not handle overloaded unnamed types properly:
-// all unnamed types get mangled to the same string. We use the pointer
-// to the type as name here, as it guarantees unique names for different
-// types and we remove the declarations when destroying PredicateInfo.
-// It is a workaround for PR38117, because solving it in a fully general way is
-// tricky (FIXME).
-static Function *getCopyDeclaration(Module *M, Type *Ty) {
- std::string Name = "llvm.ssa.copy." + utostr((uintptr_t) Ty);
- return cast<Function>(
- M->getOrInsertFunction(Name,
- getType(M->getContext(), Intrinsic::ssa_copy, Ty))
- .getCallee());
-}
-
// Given the renaming stack, make all the operands currently on the stack real
// by inserting them into the IR. Return the last operation's value.
Value *PredicateInfoBuilder::materializeStack(unsigned int &Counter,
// order in the case of multiple predicateinfo in the same block.
if (isa<PredicateWithEdge>(ValInfo)) {
IRBuilder<> B(getBranchTerminator(ValInfo));
- Function *IF = getCopyDeclaration(F.getParent(), Op->getType());
- if (IF->users().empty())
- PI.CreatedDeclarations.insert(IF);
+ Function *IF = Intrinsic::getDeclaration(
+ F.getParent(), Intrinsic::ssa_copy, Op->getType());
CallInst *PIC =
B.CreateCall(IF, Op, Op->getName() + "." + Twine(Counter++));
PI.PredicateMap.insert({PIC, ValInfo});
// Insert the predicate directly after the assume. While it also holds
// directly before it, assume(i1 true) is not a useful fact.
IRBuilder<> B(PAssume->AssumeInst->getNextNode());
- Function *IF = getCopyDeclaration(F.getParent(), Op->getType());
- if (IF->users().empty())
- PI.CreatedDeclarations.insert(IF);
+ Function *IF = Intrinsic::getDeclaration(
+ F.getParent(), Intrinsic::ssa_copy, Op->getType());
CallInst *PIC = B.CreateCall(IF, Op);
PI.PredicateMap.insert({PIC, ValInfo});
Result.Def = PIC;
Builder.buildPredicateInfo();
}
-// Remove all declarations we created . The PredicateInfo consumers are
-// responsible for remove the ssa_copy calls created.
-PredicateInfo::~PredicateInfo() {
- // Collect function pointers in set first, as SmallSet uses a SmallVector
- // internally and we have to remove the asserting value handles first.
- SmallPtrSet<Function *, 20> FunctionPtrs;
- for (auto &F : CreatedDeclarations)
- FunctionPtrs.insert(&*F);
- CreatedDeclarations.clear();
-
- for (Function *F : FunctionPtrs) {
- assert(F->user_begin() == F->user_end() &&
- "PredicateInfo consumer did not remove all SSA copies.");
- F->eraseFromParent();
- }
-}
-
Optional<PredicateConstraint> PredicateBase::getConstraint() const {
switch (Type) {
case PT_Assume:
AU.addRequired<AssumptionCacheTracker>();
}
-// Replace ssa_copy calls created by PredicateInfo with their operand.
-static void replaceCreatedSSACopys(PredicateInfo &PredInfo, Function &F) {
- for (Instruction &Inst : llvm::make_early_inc_range(instructions(F))) {
- const auto *PI = PredInfo.getPredicateInfoFor(&Inst);
- auto *II = dyn_cast<IntrinsicInst>(&Inst);
- if (!PI || !II || II->getIntrinsicID() != Intrinsic::ssa_copy)
- continue;
-
- Inst.replaceAllUsesWith(II->getOperand(0));
- Inst.eraseFromParent();
- }
-}
-
bool PredicateInfoPrinterLegacyPass::runOnFunction(Function &F) {
auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
PredInfo->print(dbgs());
if (VerifyPredicateInfo)
PredInfo->verifyPredicateInfo();
-
- replaceCreatedSSACopys(*PredInfo, F);
return false;
}
auto PredInfo = std::make_unique<PredicateInfo>(F, DT, AC);
PredInfo->print(OS);
- replaceCreatedSSACopys(*PredInfo, F);
return PreservedAnalyses::all();
}
define i1 @test5(i32 %x, i32 %y) {
; CHECK-LABEL: @test5(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
-; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
-; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
-; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
-; CHECK: [[Y_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
+; CHECK: [[Y_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
; CHECK: same:
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[X_0]], [[Y_0]]
define i1 @test7(i32 %x, i32 %y) {
; CHECK-LABEL: @test7(
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
-; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
-; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
-; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
-; CHECK: [[Y_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
+; CHECK: [[Y_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
; CHECK: same:
; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X_0]], [[Y_0]]
define i1 @test7_fp(float %x, float %y) {
; CHECK-LABEL: @test7_fp(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]]
-; CHECK: [[X_0:%.*]] = call float @llvm.ssa.copy.{{.+}}(float [[X]])
-; CHECK: [[X_1:%.*]] = call float @llvm.ssa.copy.{{.+}}(float [[X]])
-; CHECK: [[Y_0:%.*]] = call float @llvm.ssa.copy.{{.+}}(float [[Y]])
-; CHECK: [[Y_1:%.*]] = call float @llvm.ssa.copy.{{.+}}(float [[Y]])
+; CHECK: [[X_0:%.*]] = call float @llvm.ssa.copy.f32(float [[X]])
+; CHECK: [[X_1:%.*]] = call float @llvm.ssa.copy.f32(float [[X]])
+; CHECK: [[Y_0:%.*]] = call float @llvm.ssa.copy.f32(float [[Y]])
+; CHECK: [[Y_1:%.*]] = call float @llvm.ssa.copy.f32(float [[Y]])
; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
; CHECK: same:
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ule float [[X_0]], [[Y_0]]
define i32 @test9(i32 %i, i32 %j) {
; CHECK-LABEL: @test9(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
-; CHECK: [[I_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[I]])
-; CHECK: [[J_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[J]])
+; CHECK: [[I_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[I]])
+; CHECK: [[J_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[J]])
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
; CHECK: cond_true:
; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[I_0]], [[J_0]]
define i32 @test10(i32 %j, i32 %i) {
; CHECK-LABEL: @test10(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
-; CHECK: [[I_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[I]])
-; CHECK: [[J_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[J]])
+; CHECK: [[I_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[I]])
+; CHECK: [[J_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[J]])
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
; CHECK: cond_true:
; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[I_0]], [[J_0]]
; CHECK-NEXT: [[V0:%.*]] = call i32 @yogibar()
; CHECK-NEXT: [[V1:%.*]] = call i32 @yogibar()
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[V0]], [[V1]]
-; CHECK: [[V0_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[V0]])
-; CHECK: [[V1_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[V1]])
+; CHECK: [[V0_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[V0]])
+; CHECK: [[V1_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[V1]])
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[NEXT:%.*]]
; CHECK: cond_true:
; CHECK-NEXT: ret i32 [[V1_0]]
; CHECK: next:
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[X:%.*]], [[V0_0]]
-; CHECK: [[V0_0_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[V0_0]])
+; CHECK: [[V0_0_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[V0_0]])
; CHECK-NEXT: br i1 [[CMP2]], label [[COND_TRUE2:%.*]], label [[NEXT2:%.*]]
; CHECK: cond_true2:
; CHECK-NEXT: ret i32 [[V0_0_1]]
define i32 @test12(i32 %x) {
; CHECK-LABEL: @test12(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
-; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
-; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
; CHECK: cond_true:
; CHECK-NEXT: br label [[RET:%.*]]
; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]]
-; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
-; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
-; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
-; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
-; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
+; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
+; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
; CHECK-NEXT: br i1 [[Z]], label [[ONEOF:%.*]], label [[NEITHER:%.*]]
; CHECK: oneof:
; CHECK-NEXT: call void @foo(i1 [[XZ]])
; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
; CHECK-NEXT: [[Z:%.*]] = select i1 [[XZ]], i1 true, i1 [[YZ]]
-; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
-; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
-; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
-; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
-; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
+; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
+; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
; CHECK-NEXT: br i1 [[Z]], label [[ONEOF:%.*]], label [[NEITHER:%.*]]
; CHECK: oneof:
; CHECK-NEXT: call void @foo(i1 [[XZ]])
; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
-; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
-; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
-; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
-; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
-; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
+; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
+; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
; CHECK: both:
; CHECK-NEXT: call void @foo(i1 [[XZ_0]])
; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
; CHECK-NEXT: [[Z:%.*]] = select i1 [[XZ]], i1 [[YZ]], i1 false
-; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
-; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
-; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
-; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
-; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
+; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
+; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
; CHECK: both:
; CHECK-NEXT: call void @foo(i1 [[XZ_0]])
; CHECK-NEXT: [[XGT:%.*]] = icmp sgt i32 [[X:%.*]], 0
; CHECK-NEXT: [[XLT:%.*]] = icmp slt i32 [[X]], 100
; CHECK-NEXT: [[Z:%.*]] = and i1 [[XGT]], [[XLT]]
-; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
-; CHECK: [[XGT_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XGT]])
-; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
-; CHECK: [[X_0_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X_0]])
-; CHECK: [[XLT_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XLT]])
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
+; CHECK: [[XGT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XGT]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[X_0_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X_0]])
+; CHECK: [[XLT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XLT]])
; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
; CHECK: both:
; CHECK-NEXT: call void @foo(i1 [[XGT_0]])
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
; CHECK-NEXT: call void @llvm.assume(i1 [[Z]])
-; CHECK: [[TMP1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
-; CHECK: [[TMP2:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
-; CHECK: [[TMP3:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
-; CHECK: [[TMP4:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
-; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
-; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP5]])
-; CHECK: [[DOT01:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP4]])
-; CHECK: [[DOT02:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP3]])
-; CHECK: [[DOT03:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP2]])
-; CHECK: [[DOT04:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP1]])
+; CHECK: [[TMP1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
+; CHECK: [[TMP2:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
+; CHECK: [[TMP3:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
+; CHECK: [[TMP4:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
+; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
+; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP5]])
+; CHECK: [[DOT01:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP4]])
+; CHECK: [[DOT02:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP3]])
+; CHECK: [[DOT03:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP2]])
+; CHECK: [[DOT04:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP1]])
; CHECK-NEXT: br i1 [[TMP5]], label [[BOTH:%.*]], label [[NOPE:%.*]]
; CHECK: both:
; CHECK-NEXT: call void @foo(i1 [[DOT01]])
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]]
; CHECK-NEXT: call void @llvm.assume(i1 [[Z]])
-; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
-; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP1]])
+; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
+; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP1]])
; CHECK-NEXT: br i1 [[TMP1]], label [[BOTH:%.*]], label [[NOPE:%.*]]
; CHECK: both:
; CHECK-NEXT: call void @foo(i1 [[XZ]])
; CHECK-LABEL: @test_and_one_unknown_cond(
; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[A:%.*]] = and i1 [[C1:%.*]], [[C2]]
-; CHECK: [[A_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
-; CHECK: [[A_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
-; CHECK: [[C1_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C1]])
-; CHECK: [[C2_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C2]])
-; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK: [[A_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
+; CHECK: [[A_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
+; CHECK: [[C1_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C1]])
+; CHECK: [[C2_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C2]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
; CHECK-NEXT: br i1 [[A]], label [[BOTH:%.*]], label [[NOPE:%.*]]
; CHECK: both:
; CHECK-NEXT: call void @bar(i32 [[X_0]])
; CHECK-LABEL: @test_or_one_unknown_cond(
; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[A:%.*]] = or i1 [[C1:%.*]], [[C2]]
-; CHECK: [[A_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
-; CHECK: [[A_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
-; CHECK: [[C1_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C1]])
-; CHECK: [[C2_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C2]])
-; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK: [[A_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
+; CHECK: [[A_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
+; CHECK: [[C1_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C1]])
+; CHECK: [[C2_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C2]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
; CHECK-NEXT: br i1 [[A]], label [[NOPE:%.*]], label [[BOTH_INVERTED:%.*]]
; CHECK: both_inverted:
; CHECK-NEXT: call void @bar(i32 [[X_0]])
; CHECK-LABEL: @test_and_chain(
; CHECK-NEXT: [[AND1:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[AND2:%.*]] = and i1 [[AND1]], [[C:%.*]]
-; CHECK: [[AND2_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND2]])
-; CHECK: [[AND2_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND2]])
-; CHECK: [[AND1_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND1]])
-; CHECK: [[A_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
-; CHECK: [[B_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[B]])
-; CHECK: [[C_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C]])
+; CHECK: [[AND2_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND2]])
+; CHECK: [[AND2_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND2]])
+; CHECK: [[AND1_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND1]])
+; CHECK: [[A_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
+; CHECK: [[B_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[B]])
+; CHECK: [[C_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C]])
; CHECK-NEXT: br i1 [[AND2]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @foo(i1 [[A_0]])
; CHECK-LABEL: @test_or_chain(
; CHECK-NEXT: [[OR1:%.*]] = or i1 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[OR2:%.*]] = or i1 [[OR1]], [[C:%.*]]
-; CHECK: [[OR2_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[OR2]])
-; CHECK: [[OR2_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[OR2]])
-; CHECK: [[OR1_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[OR1]])
-; CHECK: [[A_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
-; CHECK: [[B_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[B]])
-; CHECK: [[C_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C]])
+; CHECK: [[OR2_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[OR2]])
+; CHECK: [[OR2_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[OR2]])
+; CHECK: [[OR1_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[OR1]])
+; CHECK: [[A_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
+; CHECK: [[B_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[B]])
+; CHECK: [[C_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C]])
; CHECK-NEXT: br i1 [[OR2]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @foo(i1 [[A]])
; CHECK-LABEL: @test_and_or_mixed(
; CHECK-NEXT: [[OR:%.*]] = or i1 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[AND:%.*]] = and i1 [[OR]], [[C:%.*]]
-; CHECK: [[AND_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND]])
-; CHECK: [[AND_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND]])
-; CHECK: [[OR_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[OR]])
-; CHECK: [[C_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C]])
+; CHECK: [[AND_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND]])
+; CHECK: [[AND_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND]])
+; CHECK: [[OR_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[OR]])
+; CHECK: [[C_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C]])
; CHECK-NEXT: br i1 [[AND]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @foo(i1 [[A]])
; CHECK-NEXT: [[A13:%.*]] = and i1 [[A12]], true
; CHECK-NEXT: [[A14:%.*]] = and i1 [[A13]], true
; CHECK-NEXT: [[A15:%.*]] = and i1 [[A14]], true
-; CHECK: [[A15_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
-; CHECK: [[A15_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
-; CHECK: [[A14_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A14]])
-; CHECK: [[A13_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A13]])
-; CHECK: [[A12_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A12]])
-; CHECK: [[A11_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A11]])
-; CHECK: [[A10_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A10]])
-; CHECK: [[A9_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A9]])
-; CHECK: [[A8_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A8]])
+; CHECK: [[A15_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
+; CHECK: [[A15_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
+; CHECK: [[A14_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A14]])
+; CHECK: [[A13_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A13]])
+; CHECK: [[A12_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A12]])
+; CHECK: [[A11_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A11]])
+; CHECK: [[A10_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A10]])
+; CHECK: [[A9_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A9]])
+; CHECK: [[A8_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A8]])
; CHECK-NEXT: br i1 [[A15]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @foo(i1 [[A1]])
; CHECK-NEXT: [[A13:%.*]] = and i1 [[A12]], [[A12]]
; CHECK-NEXT: [[A14:%.*]] = and i1 [[A13]], [[A13]]
; CHECK-NEXT: [[A15:%.*]] = and i1 [[A14]], [[A14]]
-; CHECK: [[A15_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
-; CHECK: [[A15_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
-; CHECK: [[A14_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A14]])
-; CHECK: [[A13_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A13]])
-; CHECK: [[A12_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A12]])
-; CHECK: [[A11_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A11]])
-; CHECK: [[A10_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A10]])
-; CHECK: [[A9_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A9]])
-; CHECK: [[A8_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A8]])
+; CHECK: [[A15_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
+; CHECK: [[A15_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
+; CHECK: [[A14_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A14]])
+; CHECK: [[A13_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A13]])
+; CHECK: [[A12_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A12]])
+; CHECK: [[A11_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A11]])
+; CHECK: [[A10_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A10]])
+; CHECK: [[A9_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A9]])
+; CHECK: [[A8_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A8]])
; CHECK-NEXT: br i1 [[A15]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @foo(i1 [[A1]])
; CHECK-NEXT: [[A13:%.*]] = or i1 [[A12]], [[A12]]
; CHECK-NEXT: [[A14:%.*]] = or i1 [[A13]], [[A13]]
; CHECK-NEXT: [[A15:%.*]] = or i1 [[A14]], [[A14]]
-; CHECK: [[A15_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
-; CHECK: [[A15_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
-; CHECK: [[A14_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A14]])
-; CHECK: [[A13_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A13]])
-; CHECK: [[A12_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A12]])
-; CHECK: [[A11_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A11]])
-; CHECK: [[A10_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A10]])
-; CHECK: [[A9_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A9]])
-; CHECK: [[A8_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A8]])
+; CHECK: [[A15_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
+; CHECK: [[A15_1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
+; CHECK: [[A14_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A14]])
+; CHECK: [[A13_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A13]])
+; CHECK: [[A12_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A12]])
+; CHECK: [[A11_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A11]])
+; CHECK: [[A10_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A10]])
+; CHECK: [[A9_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A9]])
+; CHECK: [[A8_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A8]])
; CHECK-NEXT: br i1 [[A15]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @foo(i1 [[A1]])
; CHECK-NEXT: [[AND1:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[AND2:%.*]] = and i1 [[AND1]], [[C:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[AND2]])
-; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C]])
-; CHECK: [[TMP2:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[B]])
-; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
-; CHECK: [[TMP4:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND1]])
-; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND2]])
+; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[C]])
+; CHECK: [[TMP2:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[B]])
+; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A]])
+; CHECK: [[TMP4:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND1]])
+; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[AND2]])
; CHECK-NEXT: call void @foo(i1 [[TMP3]])
; CHECK-NEXT: call void @foo(i1 [[TMP2]])
; CHECK-NEXT: call void @foo(i1 [[TMP1]])
; CHECK-NEXT: [[OR1:%.*]] = or i1 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[OR2:%.*]] = or i1 [[OR1]], [[C:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[OR2]])
-; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[OR2]])
+; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[OR2]])
; CHECK-NEXT: call void @foo(i1 [[A]])
; CHECK-NEXT: call void @foo(i1 [[B]])
; CHECK-NEXT: call void @foo(i1 [[C]])
; CHECK-NEXT: [[A14:%.*]] = and i1 [[A13]], [[A13]]
; CHECK-NEXT: [[A15:%.*]] = and i1 [[A14]], [[A14]]
; CHECK-NEXT: call void @llvm.assume(i1 [[A15]])
-; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A8]])
-; CHECK: [[TMP2:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A9]])
-; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A10]])
-; CHECK: [[TMP4:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A11]])
-; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A12]])
-; CHECK: [[TMP6:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A13]])
-; CHECK: [[TMP7:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A14]])
-; CHECK: [[TMP8:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
+; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A8]])
+; CHECK: [[TMP2:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A9]])
+; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A10]])
+; CHECK: [[TMP4:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A11]])
+; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A12]])
+; CHECK: [[TMP6:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A13]])
+; CHECK: [[TMP7:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A14]])
+; CHECK: [[TMP8:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[A15]])
; CHECK-NEXT: call void @foo(i1 [[A1]])
; CHECK-NEXT: call void @foo(i1 [[A2]])
; CHECK-NEXT: call void @foo(i1 [[A3]])