diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -2368,6 +2368,14 @@ return nullptr; } + /// Given a set in interconnected phis of type 'From' that are loaded/stored + /// or bitcast to type 'To', return true if the set should be converted to + /// 'To'. + virtual bool shouldConvertPhiType(Type *From, Type *To) const { + return (From->isIntegerTy() || From->isFloatingPointTy()) && + (To->isIntegerTy() || To->isFloatingPointTy()); + } + /// Returns true if the opcode is a commutative binary operation. virtual bool isCommutativeBinOp(unsigned Opcode) const { // FIXME: This should get its info from the td file. diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -245,6 +245,10 @@ cl::desc("Enable BFI update verification for " "CodeGenPrepare.")); +static cl::opt OptimizePhiTypes( + "cgp-optimize-phi-types", cl::Hidden, cl::init(false), + cl::desc("Enable converting phi types in CodeGenPrepare")); + namespace { enum ExtType { @@ -407,6 +411,9 @@ unsigned CreatedInstsCost = 0); bool mergeSExts(Function &F); bool splitLargeGEPOffsets(); + bool optimizePhiType(PHINode *Inst, SmallPtrSetImpl &Visited, + SmallPtrSetImpl &DeletedInstrs); + bool optimizePhiTypes(Function &F); bool performAddressTypePromotion( Instruction *&Inst, bool AllowPromotionWithoutCommonHeader, @@ -515,6 +522,7 @@ MadeChange |= mergeSExts(F); if (!LargeOffsetGEPMap.empty()) MadeChange |= splitLargeGEPOffsets(); + MadeChange |= optimizePhiTypes(F); if (MadeChange) eliminateFallThrough(F); @@ -5717,6 +5725,155 @@ return Changed; } +bool CodeGenPrepare::optimizePhiType( + PHINode *I, SmallPtrSetImpl &Visited, + SmallPtrSetImpl &DeletedInstrs) { + // We are looking for a collection on interconnected phi nodes that together + // only use loads/bitcasts and are used by stores/bitcasts, and the bitcasts + // are of the same type. Convert the whole set of nodes to the type of the + // bitcast. + Type *PhiTy = I->getType(); + Type *ConvertTy = nullptr; + if (Visited.count(I) || + (!I->getType()->isIntegerTy() && !I->getType()->isFloatingPointTy())) + return false; + + SmallVector Worklist; + Worklist.push_back(cast(I)); + SmallPtrSet PhiNodes; + PhiNodes.insert(I); + Visited.insert(I); + SmallPtrSet Defs; + SmallPtrSet Uses; + + while (!Worklist.empty()) { + Instruction *II = Worklist.pop_back_val(); + + if (auto *Phi = dyn_cast(II)) { + // Handle Defs, which might also be PHI's + for (Value *V : Phi->incoming_values()) { + if (auto *OpPhi = dyn_cast(V)) { + if (!PhiNodes.count(OpPhi)) { + if (Visited.count(OpPhi)) + return false; + PhiNodes.insert(OpPhi); + Visited.insert(OpPhi); + Worklist.push_back(OpPhi); + } + } else if (auto *OpLoad = dyn_cast(V)) { + if (!Defs.count(OpLoad)) { + Defs.insert(OpLoad); + Worklist.push_back(OpLoad); + } + } else if (auto *OpEx = dyn_cast(V)) { + if (!Defs.count(OpEx)) { + Defs.insert(OpEx); + Worklist.push_back(OpEx); + } + } else if (auto *OpBC = dyn_cast(V)) { + if (!ConvertTy) + ConvertTy = OpBC->getOperand(0)->getType(); + if (OpBC->getOperand(0)->getType() != ConvertTy) + return false; + if (!Defs.count(OpBC)) { + Defs.insert(OpBC); + Worklist.push_back(OpBC); + } + } else if (!isa(V)) + return false; + } + } + + // Handle uses which might also be phi's + for (User *V : II->users()) { + if (auto *OpPhi = dyn_cast(V)) { + if (!PhiNodes.count(OpPhi)) { + if (Visited.count(OpPhi)) + return false; + PhiNodes.insert(OpPhi); + Visited.insert(OpPhi); + Worklist.push_back(OpPhi); + } + } else if (auto *OpStore = dyn_cast(V)) { + if (OpStore->getOperand(0) != II) + return false; + Uses.insert(OpStore); + } else if (auto *OpBC = dyn_cast(V)) { + if (!ConvertTy) + ConvertTy = OpBC->getType(); + if (OpBC->getType() != ConvertTy) + return false; + Uses.insert(OpBC); + } else + return false; + } + } + + if (!ConvertTy || !TLI->shouldConvertPhiType(PhiTy, ConvertTy)) + return false; + + LLVM_DEBUG(dbgs() << "Converting " << *I << "\n and connected nodes to " + << *ConvertTy << "\n"); + + // Create all the new phi nodes of the new type, and bitcast any loads to the + // correct type. + ValueToValueMap ValMap; + ValMap[UndefValue::get(PhiTy)] = UndefValue::get(ConvertTy); + for (Instruction *D : Defs) { + if (isa(D)) + ValMap[D] = D->getOperand(0); + else + ValMap[D] = + new BitCastInst(D, ConvertTy, D->getName() + ".bc", D->getNextNode()); + } + for (PHINode *Phi : PhiNodes) + ValMap[Phi] = PHINode::Create(ConvertTy, Phi->getNumIncomingValues(), + Phi->getName() + ".tc", Phi); + // Pipe together all the PhiNodes. + for (PHINode *Phi : PhiNodes) { + PHINode *NewPhi = cast(ValMap[Phi]); + for (int i = 0, e = Phi->getNumIncomingValues(); i < e; i++) + NewPhi->addIncoming(ValMap[Phi->getIncomingValue(i)], + Phi->getIncomingBlock(i)); + } + // And finally pipe up the stores and bitcasts + for (Instruction *U : Uses) { + if (isa(U)) { + DeletedInstrs.insert(U); + U->replaceAllUsesWith(ValMap[U->getOperand(0)]); + } else + U->setOperand(0, + new BitCastInst(ValMap[U->getOperand(0)], PhiTy, "bc", U)); + } + + // Save the removed phis to be deleted later. + for (PHINode *Phi : PhiNodes) + DeletedInstrs.insert(Phi); + return true; +} + +bool CodeGenPrepare::optimizePhiTypes(Function &F) { + if (!OptimizePhiTypes) + return false; + + bool Changed = false; + SmallPtrSet Visited; + SmallPtrSet DeletedInstrs; + + // Attempt to optimize all the phis in the functions to the correct type. + for (auto &BB : F) + for (auto &Phi : BB.phis()) + Changed |= optimizePhiType(&Phi, Visited, DeletedInstrs); + + // Remove any old phi's that have been converted. + for (auto *I : DeletedInstrs) { + I->replaceAllUsesWith(UndefValue::get(I->getType())); + I->eraseFromParent(); + } + + return Changed; +} + /// Return true, if an ext(load) can be formed from an extension in /// \p MovedExts. bool CodeGenPrepare::canFormExtLd( diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h --- a/llvm/lib/Target/X86/X86ISelLowering.h +++ b/llvm/lib/Target/X86/X86ISelLowering.h @@ -1187,6 +1187,7 @@ bool shouldSinkOperands(Instruction *I, SmallVectorImpl &Ops) const override; + bool shouldConvertPhiType(Type *From, Type *To) const override; /// Return true if folding a vector load into ExtVal (a sign, zero, or any /// extend node) is profitable. diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -30748,6 +30748,12 @@ return false; } +bool X86TargetLowering::shouldConvertPhiType(Type *From, Type *To) const { + if (!Subtarget.is64Bit()) + return false; + return TargetLowering::shouldConvertPhiType(From, To); +} + bool X86TargetLowering::isVectorLoadExtDesirable(SDValue ExtVal) const { if (isa(ExtVal.getOperand(0))) return false; diff --git a/llvm/test/CodeGen/AArch64/convertphitype.ll b/llvm/test/CodeGen/AArch64/convertphitype.ll --- a/llvm/test/CodeGen/AArch64/convertphitype.ll +++ b/llvm/test/CodeGen/AArch64/convertphitype.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -codegenprepare %s -S | FileCheck %s +; RUN: opt -codegenprepare -cgp-optimize-phi-types %s -S | FileCheck %s target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" target triple = "aarch64--linux-gnu" @@ -11,14 +11,15 @@ ; CHECK-NEXT: br i1 [[CMP15]], label [[THEN:%.*]], label [[ELSE:%.*]] ; CHECK: then: ; CHECK-NEXT: [[LS:%.*]] = load i32, i32* [[S:%.*]], align 4 +; CHECK-NEXT: [[LS_BC:%.*]] = bitcast i32 [[LS]] to float ; CHECK-NEXT: br label [[END:%.*]] ; CHECK: else: ; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[D:%.*]], align 4 +; CHECK-NEXT: [[LD_BC:%.*]] = bitcast i32 [[LD]] to float ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[LS]], [[THEN]] ], [ [[LD]], [[ELSE]] ] -; CHECK-NEXT: [[B:%.*]] = bitcast i32 [[PHI]] to float -; CHECK-NEXT: ret float [[B]] +; CHECK-NEXT: [[PHI_TC:%.*]] = phi float [ [[LS_BC]], [[THEN]] ], [ [[LD_BC]], [[ELSE]] ] +; CHECK-NEXT: ret float [[PHI_TC]] ; entry: %cmp15 = icmp sgt i32 %n, 0 @@ -45,11 +46,11 @@ ; CHECK-NEXT: br i1 [[CMP15]], label [[THEN:%.*]], label [[END:%.*]] ; CHECK: then: ; CHECK-NEXT: [[LS:%.*]] = load i32, i32* [[S:%.*]], align 4 +; CHECK-NEXT: [[LS_BC:%.*]] = bitcast i32 [[LS]] to float ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[LS]], [[THEN]] ], [ undef, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[B:%.*]] = bitcast i32 [[PHI]] to float -; CHECK-NEXT: ret float [[B]] +; CHECK-NEXT: [[PHI_TC:%.*]] = phi float [ [[LS_BC]], [[THEN]] ], [ undef, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret float [[PHI_TC]] ; entry: %cmp15 = icmp sgt i32 %n, 0 @@ -73,11 +74,11 @@ ; CHECK-NEXT: br i1 [[CMP15]], label [[THEN:%.*]], label [[END:%.*]] ; CHECK: then: ; CHECK-NEXT: [[LS:%.*]] = load i32, i32* [[S:%.*]], align 4 +; CHECK-NEXT: [[LS_BC:%.*]] = bitcast i32 [[LS]] to float ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[LS]], [[THEN]] ], [ [[FB]], [[ENTRY:%.*]] ] -; CHECK-NEXT: [[B:%.*]] = bitcast i32 [[PHI]] to float -; CHECK-NEXT: ret float [[B]] +; CHECK-NEXT: [[PHI_TC:%.*]] = phi float [ [[LS_BC]], [[THEN]] ], [ [[F]], [[ENTRY:%.*]] ] +; CHECK-NEXT: ret float [[PHI_TC]] ; entry: %cmp15 = icmp sgt i32 %n, 0 @@ -102,10 +103,12 @@ ; CHECK-NEXT: br i1 [[CMP15]], label [[THEN:%.*]], label [[END:%.*]] ; CHECK: then: ; CHECK-NEXT: [[LS:%.*]] = load i32, i32* [[S:%.*]], align 4 +; CHECK-NEXT: [[LS_BC:%.*]] = bitcast i32 [[LS]] to float ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[LS]], [[THEN]] ], [ [[FB]], [[ENTRY:%.*]] ] -; CHECK-NEXT: store i32 [[PHI]], i32* [[D:%.*]], align 4 +; CHECK-NEXT: [[PHI_TC:%.*]] = phi float [ [[LS_BC]], [[THEN]] ], [ [[F]], [[ENTRY:%.*]] ] +; CHECK-NEXT: [[BC:%.*]] = bitcast float [[PHI_TC]] to i32 +; CHECK-NEXT: store i32 [[BC]], i32* [[D:%.*]], align 4 ; CHECK-NEXT: ret void ; entry: @@ -130,14 +133,15 @@ ; CHECK-NEXT: br i1 [[CMP15]], label [[THEN:%.*]], label [[ELSE:%.*]] ; CHECK: then: ; CHECK-NEXT: [[LS:%.*]] = load double, double* [[S:%.*]], align 4 +; CHECK-NEXT: [[LS_BC:%.*]] = bitcast double [[LS]] to i64 ; CHECK-NEXT: br label [[END:%.*]] ; CHECK: else: ; CHECK-NEXT: [[LD:%.*]] = load double, double* [[D:%.*]], align 4 +; CHECK-NEXT: [[LD_BC:%.*]] = bitcast double [[LD]] to i64 ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[PHI:%.*]] = phi double [ [[LS]], [[THEN]] ], [ [[LD]], [[ELSE]] ] -; CHECK-NEXT: [[B:%.*]] = bitcast double [[PHI]] to i64 -; CHECK-NEXT: ret i64 [[B]] +; CHECK-NEXT: [[PHI_TC:%.*]] = phi i64 [ [[LS_BC]], [[THEN]] ], [ [[LD_BC]], [[ELSE]] ] +; CHECK-NEXT: ret i64 [[PHI_TC]] ; entry: %cmp15 = icmp sgt i32 %n, 0 @@ -164,14 +168,15 @@ ; CHECK-NEXT: br i1 [[CMP15]], label [[THEN:%.*]], label [[ELSE:%.*]] ; CHECK: then: ; CHECK-NEXT: [[LS:%.*]] = load float, float* [[S:%.*]], align 4 +; CHECK-NEXT: [[LS_BC:%.*]] = bitcast float [[LS]] to i32 ; CHECK-NEXT: br label [[END:%.*]] ; CHECK: else: ; CHECK-NEXT: [[LD:%.*]] = load float, float* [[D:%.*]], align 4 +; CHECK-NEXT: [[LD_BC:%.*]] = bitcast float [[LD]] to i32 ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[PHI:%.*]] = phi float [ [[LS]], [[THEN]] ], [ [[LD]], [[ELSE]] ] -; CHECK-NEXT: [[B:%.*]] = bitcast float [[PHI]] to i32 -; CHECK-NEXT: ret i32 [[B]] +; CHECK-NEXT: [[PHI_TC:%.*]] = phi i32 [ [[LS_BC]], [[THEN]] ], [ [[LD_BC]], [[ELSE]] ] +; CHECK-NEXT: ret i32 [[PHI_TC]] ; entry: %cmp15 = icmp sgt i32 %n, 0 @@ -198,14 +203,15 @@ ; CHECK-NEXT: br i1 [[CMP15]], label [[THEN:%.*]], label [[ELSE:%.*]] ; CHECK: then: ; CHECK-NEXT: [[LS:%.*]] = load half, half* [[S:%.*]], align 4 +; CHECK-NEXT: [[LS_BC:%.*]] = bitcast half [[LS]] to i16 ; CHECK-NEXT: br label [[END:%.*]] ; CHECK: else: ; CHECK-NEXT: [[LD:%.*]] = load half, half* [[D:%.*]], align 4 +; CHECK-NEXT: [[LD_BC:%.*]] = bitcast half [[LD]] to i16 ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[LS]], [[THEN]] ], [ [[LD]], [[ELSE]] ] -; CHECK-NEXT: [[B:%.*]] = bitcast half [[PHI]] to i16 -; CHECK-NEXT: ret i16 [[B]] +; CHECK-NEXT: [[PHI_TC:%.*]] = phi i16 [ [[LS_BC]], [[THEN]] ], [ [[LD_BC]], [[ELSE]] ] +; CHECK-NEXT: ret i16 [[PHI_TC]] ; entry: %cmp15 = icmp sgt i32 %n, 0 @@ -232,14 +238,15 @@ ; CHECK-NEXT: br i1 [[CMP15]], label [[THEN:%.*]], label [[ELSE:%.*]] ; CHECK: then: ; CHECK-NEXT: [[LS:%.*]] = load fp128, fp128* [[S:%.*]], align 4 +; CHECK-NEXT: [[LS_BC:%.*]] = bitcast fp128 [[LS]] to i128 ; CHECK-NEXT: br label [[END:%.*]] ; CHECK: else: ; CHECK-NEXT: [[LD:%.*]] = load fp128, fp128* [[D:%.*]], align 4 +; CHECK-NEXT: [[LD_BC:%.*]] = bitcast fp128 [[LD]] to i128 ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[PHI:%.*]] = phi fp128 [ [[LS]], [[THEN]] ], [ [[LD]], [[ELSE]] ] -; CHECK-NEXT: [[B:%.*]] = bitcast fp128 [[PHI]] to i128 -; CHECK-NEXT: ret i128 [[B]] +; CHECK-NEXT: [[PHI_TC:%.*]] = phi i128 [ [[LS_BC]], [[THEN]] ], [ [[LD_BC]], [[ELSE]] ] +; CHECK-NEXT: ret i128 [[PHI_TC]] ; entry: %cmp15 = icmp sgt i32 %n, 0 @@ -298,18 +305,19 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP15:%.*]] = icmp sgt i64 [[N:%.*]], 0 ; CHECK-NEXT: [[LS:%.*]] = load i32, i32* [[S:%.*]], align 4 +; CHECK-NEXT: [[LS_BC:%.*]] = bitcast i32 [[LS]] to float ; CHECK-NEXT: br i1 [[CMP15]], label [[LOOP:%.*]], label [[END:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[LPHI:%.*]] = phi i32 [ [[LS]], [[ENTRY]] ], [ [[LD:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[LD]] = load i32, i32* [[D:%.*]], align 4 +; CHECK-NEXT: [[LPHI_TC:%.*]] = phi float [ [[LS_BC]], [[ENTRY]] ], [ [[LD_BC:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[D:%.*]], align 4 +; CHECK-NEXT: [[LD_BC]] = bitcast i32 [[LD]] to float ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[END]], label [[LOOP]] ; CHECK: end: -; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ undef, [[ENTRY]] ], [ [[LPHI]], [[LOOP]] ] -; CHECK-NEXT: [[B:%.*]] = bitcast i32 [[PHI]] to float -; CHECK-NEXT: ret float [[B]] +; CHECK-NEXT: [[PHI_TC:%.*]] = phi float [ undef, [[ENTRY]] ], [ [[LPHI_TC]], [[LOOP]] ] +; CHECK-NEXT: ret float [[PHI_TC]] ; entry: %cmp15 = icmp sgt i64 %n, 0 @@ -370,19 +378,20 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP15:%.*]] = icmp sgt i64 [[N:%.*]], 0 ; CHECK-NEXT: [[LS:%.*]] = load i32, i32* [[S:%.*]], align 4 +; CHECK-NEXT: [[LS_BC:%.*]] = bitcast i32 [[LS]] to float ; CHECK-NEXT: br i1 [[CMP15]], label [[LOOP:%.*]], label [[END:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[LPHI:%.*]] = phi i32 [ [[LS]], [[ENTRY]] ], [ [[LD:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[LPHI2:%.*]] = phi i32 [ undef, [[ENTRY]] ], [ [[LPHI]], [[LOOP]] ] -; CHECK-NEXT: [[LD]] = load i32, i32* [[D:%.*]], align 4 +; CHECK-NEXT: [[LPHI_TC:%.*]] = phi float [ [[LS_BC]], [[ENTRY]] ], [ [[LD_BC:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[LPHI2_TC:%.*]] = phi float [ undef, [[ENTRY]] ], [ [[LPHI_TC]], [[LOOP]] ] +; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[D:%.*]], align 4 +; CHECK-NEXT: [[LD_BC]] = bitcast i32 [[LD]] to float ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[END]], label [[LOOP]] ; CHECK: end: -; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ undef, [[ENTRY]] ], [ [[LPHI2]], [[LOOP]] ] -; CHECK-NEXT: [[B:%.*]] = bitcast i32 [[PHI]] to float -; CHECK-NEXT: ret float [[B]] +; CHECK-NEXT: [[PHI_TC:%.*]] = phi float [ undef, [[ENTRY]] ], [ [[LPHI2_TC]], [[LOOP]] ] +; CHECK-NEXT: ret float [[PHI_TC]] ; entry: %cmp15 = icmp sgt i64 %n, 0 @@ -409,31 +418,33 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[N:%.*]], 1 ; CHECK-NEXT: [[LS:%.*]] = load i32, i32* [[S:%.*]], align 4 +; CHECK-NEXT: [[LS_BC:%.*]] = bitcast i32 [[LS]] to float ; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[IFEND:%.*]] ; CHECK: then: ; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[D:%.*]], align 4 +; CHECK-NEXT: [[LD_BC:%.*]] = bitcast i32 [[LD]] to float ; CHECK-NEXT: br label [[IFEND]] ; CHECK: ifend: -; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ [[LD]], [[THEN]] ], [ [[LS]], [[ENTRY:%.*]] ] +; CHECK-NEXT: [[PHI1_TC:%.*]] = phi float [ [[LD_BC]], [[THEN]] ], [ [[LS_BC]], [[ENTRY:%.*]] ] ; CHECK-NEXT: [[CMP15:%.*]] = icmp sgt i64 [[N]], 0 ; CHECK-NEXT: br i1 [[CMP15]], label [[LOOP:%.*]], label [[END:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[IFEND]] ], [ [[IV_NEXT:%.*]], [[LOOPEND:%.*]] ] -; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[PHI1]], [[IFEND]] ], [ [[PHI3:%.*]], [[LOOPEND]] ] +; CHECK-NEXT: [[PHI2_TC:%.*]] = phi float [ [[PHI1_TC]], [[IFEND]] ], [ [[PHI3_TC:%.*]], [[LOOPEND]] ] ; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[N]], 1 ; CHECK-NEXT: br i1 [[TMP0]], label [[LOOPTHEN:%.*]], label [[LOOPEND]] ; CHECK: loopthen: ; CHECK-NEXT: [[LL:%.*]] = load i32, i32* [[D]], align 4 +; CHECK-NEXT: [[LL_BC:%.*]] = bitcast i32 [[LL]] to float ; CHECK-NEXT: br label [[LOOPEND]] ; CHECK: loopend: -; CHECK-NEXT: [[PHI3]] = phi i32 [ [[LL]], [[LOOPTHEN]] ], [ [[PHI2]], [[LOOP]] ] +; CHECK-NEXT: [[PHI3_TC]] = phi float [ [[LL_BC]], [[LOOPTHEN]] ], [ [[PHI2_TC]], [[LOOP]] ] ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[END]], label [[LOOP]] ; CHECK: end: -; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[PHI1]], [[IFEND]] ], [ [[PHI3]], [[LOOPEND]] ] -; CHECK-NEXT: [[B:%.*]] = bitcast i32 [[PHI]] to float -; CHECK-NEXT: ret float [[B]] +; CHECK-NEXT: [[PHI_TC:%.*]] = phi float [ [[PHI1_TC]], [[IFEND]] ], [ [[PHI3_TC]], [[LOOPEND]] ] +; CHECK-NEXT: ret float [[PHI_TC]] ; entry: %cmp = icmp eq i64 %n, 1 diff --git a/llvm/test/CodeGen/X86/convertphitype.ll b/llvm/test/CodeGen/X86/convertphitype.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/convertphitype.ll @@ -0,0 +1,39 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -codegenprepare -cgp-optimize-phi-types=true %s -S | FileCheck %s + +target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128" +target triple = "i386-unknown-linux-gnu" + +define float @convphi1(i32 *%s, i32 *%d, i32 %n) { +; CHECK-LABEL: @convphi1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP15:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP15]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[LS:%.*]] = load i32, i32* [[S:%.*]], align 4 +; CHECK-NEXT: br label [[END:%.*]] +; CHECK: else: +; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[D:%.*]], align 4 +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[LS]], [[THEN]] ], [ [[LD]], [[ELSE]] ] +; CHECK-NEXT: [[B:%.*]] = bitcast i32 [[PHI]] to float +; CHECK-NEXT: ret float [[B]] +; +entry: + %cmp15 = icmp sgt i32 %n, 0 + br i1 %cmp15, label %then, label %else + +then: + %ls = load i32, i32* %s, align 4 + br label %end + +else: + %ld = load i32, i32* %d, align 4 + br label %end + +end: + %phi = phi i32 [ %ls, %then ], [ %ld, %else ] + %b = bitcast i32 %phi to float + ret float %b +}