diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3529,30 +3529,39 @@ // Op1.fr = Freeze(Op1) // ... = Inst(Op1.fr, NonPoisonOps...) auto* OrigOp = OrigFI.getOperand(0); - if (auto *OrigOpInst = dyn_cast(OrigOp)) { - if (OrigOpInst->hasOneUse() && !canCreateUndefOrPoison(dyn_cast(OrigOp))) { - Optional MaybePoisonOperand; - for (Use &U : OrigOpInst->operands()) { - if (isGuaranteedNotToBeUndefOrPoison(U.get())) - continue; - if (!MaybePoisonOperand) - MaybePoisonOperand = &U; - else if(MaybePoisonOperand) - return nullptr; - } + auto *OrigOpInst = dyn_cast(OrigOp); - if (!MaybePoisonOperand.hasValue()) - return nullptr; + if (!OrigOpInst) + return nullptr; - auto *MaybePoisonUse = MaybePoisonOperand.getValue(); - auto *FrozenMaybePoisonOperand = new FreezeInst(MaybePoisonUse->get(), MaybePoisonUse->getUser()->getName() + ".fr"); + if (!OrigOpInst->hasOneUse() || + canCreateUndefOrPoison(dyn_cast(OrigOp))) + return nullptr; - replaceUse(*MaybePoisonUse, FrozenMaybePoisonOperand); - FrozenMaybePoisonOperand->insertBefore(OrigOpInst); - return OrigOp; - } + // If operand is guaranteed not to be poison, there is no need to add freeze + // to the operand. So we first find the operand that is not guranteed to be + // poison. + Use *MaybePoisonOperand; + for (Use &U : OrigOpInst->operands()) { + if (isGuaranteedNotToBeUndefOrPoison(U.get())) + continue; + if (!MaybePoisonOperand) + MaybePoisonOperand = &U; + else + return nullptr; } - return nullptr; + + // If all operands are guaranteed to be non-poison, we can drop freeze. + if (!MaybePoisonOperand) + return OrigOp; + + auto *FrozenMaybePoisonOperand = + new FreezeInst(MaybePoisonOperand->get(), + MaybePoisonOperand->getUser()->getName() + ".fr"); + + replaceUse(*MaybePoisonOperand, FrozenMaybePoisonOperand); + FrozenMaybePoisonOperand->insertBefore(OrigOpInst); + return OrigOp; } Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) { diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll --- a/llvm/test/Transforms/InstCombine/freeze.ll +++ b/llvm/test/Transforms/InstCombine/freeze.ll @@ -92,10 +92,10 @@ define i32 @early_freeze_test1(i32 %x, i32 %y) { ; CHECK-LABEL: @early_freeze_test1( ; CHECK-NEXT: [[V1:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]] -; CHECK-NEXT: [[V2:%.*]] = shl i32 [[V1_FR]], 1 +; CHECK-NEXT: [[V2:%.*]] = shl i32 [[V1]], 1 ; CHECK-NEXT: [[V3:%.*]] = and i32 [[V2]], 2 -; CHECK-NEXT: ret i32 [[V3]] +; CHECK-NEXT: [[V3_FR:%.*]] = freeze i32 [[V3]] +; CHECK-NEXT: ret i32 [[V3_FR]] ; %v1 = add i32 %x, %y %v2 = shl i32 %v1, 1 @@ -107,10 +107,10 @@ define i1 @early_freeze_test2(i32* %ptr) { ; CHECK-LABEL: @early_freeze_test2( ; CHECK-NEXT: [[V1:%.*]] = load i32, i32* [[PTR:%.*]], align 4 -; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]] -; CHECK-NEXT: [[V2:%.*]] = and i32 [[V1_FR]], 1 +; CHECK-NEXT: [[V2:%.*]] = and i32 [[V1]], 1 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[V2]], 0 -; CHECK-NEXT: ret i1 [[COND]] +; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]] +; CHECK-NEXT: ret i1 [[COND_FR]] ; %v1 = load i32, i32* %ptr %v2 = and i32 %v1, 1