Index: llvm/lib/CodeGen/TypePromotion.cpp =================================================================== --- llvm/lib/CodeGen/TypePromotion.cpp +++ llvm/lib/CodeGen/TypePromotion.cpp @@ -897,41 +897,54 @@ TII.getRegisterBitWidth(TargetTransformInfo::RGK_Scalar).getFixedSize(); Ctx = &F.getParent()->getContext(); - // Search up from icmps to try to promote their operands. + // Return the preferred integer width of the instruction, or zero if we + // shouldn't try. + auto GetPromoteWidth = [&](Instruction *I) -> uint32_t { + if (!isa(I->getType())) + return 0; + + EVT SrcVT = TLI->getValueType(DL, I->getType()); + if (SrcVT.isSimple() && TLI->isTypeLegal(SrcVT.getSimpleVT())) + return 0; + + if (TLI->getTypeAction(*Ctx, SrcVT) != TargetLowering::TypePromoteInteger) + return 0; + + EVT PromotedVT = TLI->getTypeToTransformTo(*Ctx, SrcVT); + if (RegisterBitWidth < PromotedVT.getFixedSizeInBits()) { + LLVM_DEBUG(dbgs() << "IR Promotion: Couldn't find target register " + << "for promoted type\n"); + return 0; + } + + // TODO: Should we prefer to use RegisterBitWidth instead? + return PromotedVT.getFixedSizeInBits(); + }; + + // Search up from icmps and phis to try to promote their operands. for (BasicBlock &BB : F) { for (auto &I : BB) { if (AllVisited.count(&I)) continue; - if (!isa(&I)) - continue; - - auto *ICmp = cast(&I); - // Skip signed or pointer compares - if (ICmp->isSigned() || - !isa(ICmp->getOperand(0)->getType())) - continue; - - LLVM_DEBUG(dbgs() << "IR Promotion: Searching from: " << *ICmp << "\n"); - - for (auto &Op : ICmp->operands()) { - if (auto *I = dyn_cast(Op)) { - EVT SrcVT = TLI->getValueType(DL, I->getType()); - if (SrcVT.isSimple() && TLI->isTypeLegal(SrcVT.getSimpleVT())) - break; - - if (TLI->getTypeAction(ICmp->getContext(), SrcVT) != - TargetLowering::TypePromoteInteger) - break; - EVT PromotedVT = TLI->getTypeToTransformTo(ICmp->getContext(), SrcVT); - if (RegisterBitWidth < PromotedVT.getFixedSizeInBits()) { - LLVM_DEBUG(dbgs() << "IR Promotion: Couldn't find target register " - << "for promoted type\n"); - break; + if (isa(&I)) { + LLVM_DEBUG(dbgs() << "IR Promotion: Searching from: " << I << "\n"); + if (auto PromotedWidth = GetPromoteWidth(&I)) + MadeChange |= TryToPromote(&I, PromotedWidth); + } else if (auto *ICmp = dyn_cast(&I)) { + // Skip signed compares + if (ICmp->isSigned()) + continue; + + LLVM_DEBUG(dbgs() << "IR Promotion: Searching from: " << *ICmp << "\n"); + + for (auto &Op : ICmp->operands()) { + if (auto *OpI = dyn_cast(Op)) { + if (auto PromotedWidth = GetPromoteWidth(OpI)) { + MadeChange |= TryToPromote(OpI, PromotedWidth); + break; + } } - - MadeChange |= TryToPromote(I, PromotedVT.getFixedSizeInBits()); - break; } } } Index: llvm/test/Transforms/TypePromotion/ARM/calls.ll =================================================================== --- llvm/test/Transforms/TypePromotion/ARM/calls.ll +++ llvm/test/Transforms/TypePromotion/ARM/calls.ll @@ -129,12 +129,15 @@ ; CHECK-LABEL: @call_zext_i8_i32( ; CHECK-NEXT: for.cond8.preheader: ; CHECK-NEXT: [[CALL217:%.*]] = call fastcc zeroext i8 @safe_mul_func_uint8_t_u_u(i8 zeroext undef) -; CHECK-NEXT: [[TOBOOL219:%.*]] = icmp eq i8 [[CALL217]], 0 +; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[CALL217]] to i32 +; CHECK-NEXT: [[TOBOOL219:%.*]] = icmp eq i32 [[TMP0]], 0 ; CHECK-NEXT: br i1 [[TOBOOL219]], label [[FOR_END411:%.*]], label [[FOR_COND273_PREHEADER:%.*]] ; CHECK: for.cond273.preheader: -; CHECK-NEXT: [[CALL217_LCSSA:%.*]] = phi i8 [ [[CALL217]], [[FOR_COND8_PREHEADER:%.*]] ] -; CHECK-NEXT: [[CONV218_LE:%.*]] = zext i8 [[CALL217_LCSSA]] to i32 -; CHECK-NEXT: [[CALL346:%.*]] = call fastcc zeroext i8 @safe_lshift_func(i8 zeroext [[CALL217_LCSSA]], i32 [[CONV218_LE]]) +; CHECK-NEXT: [[CALL217_LCSSA:%.*]] = phi i32 [ [[TMP0]], [[FOR_COND8_PREHEADER:%.*]] ] +; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[CALL217_LCSSA]] to i8 +; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[CALL217_LCSSA]] to i8 +; CHECK-NEXT: [[CALL346:%.*]] = call fastcc zeroext i8 @safe_lshift_func(i8 zeroext [[TMP2]], i32 [[CALL217_LCSSA]]) +; CHECK-NEXT: [[TMP3:%.*]] = zext i8 [[CALL346]] to i32 ; CHECK-NEXT: unreachable ; CHECK: for.end411: ; CHECK-NEXT: [[CALL452:%.*]] = call fastcc i64 @safe_sub_func_int64_t_s_s(i64 undef, i64 4) Index: llvm/test/Transforms/TypePromotion/ARM/casts.ll =================================================================== --- llvm/test/Transforms/TypePromotion/ARM/casts.ll +++ llvm/test/Transforms/TypePromotion/ARM/casts.ll @@ -50,31 +50,32 @@ ret i8 %4 } -; The pass perform the transform, but a uxtb will still be inserted to handle -; the zext to the icmp. define i8 @icmp_i32_zext_i8(i8* %ptr) { ; CHECK-LABEL: @icmp_i32_zext_i8( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i32 0 ; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[GEP]], align 1 -; CHECK-NEXT: [[TMP1:%.*]] = sub nuw nsw i8 [[TMP0]], 1 +; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i32 +; CHECK-NEXT: [[TMP2:%.*]] = sub nuw nsw i32 [[TMP1]], 1 ; CHECK-NEXT: [[CONV44:%.*]] = zext i8 [[TMP0]] to i32 ; CHECK-NEXT: br label [[PREHEADER:%.*]] ; CHECK: preheader: ; CHECK-NEXT: br label [[BODY:%.*]] ; CHECK: body: -; CHECK-NEXT: [[TMP2:%.*]] = phi i8 [ [[TMP1]], [[PREHEADER]] ], [ [[TMP3:%.*]], [[IF_END:%.*]] ] +; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ [[TMP2]], [[PREHEADER]] ], [ [[TMP6:%.*]], [[IF_END:%.*]] ] ; CHECK-NEXT: [[SI_0274:%.*]] = phi i32 [ [[CONV44]], [[PREHEADER]] ], [ [[INC:%.*]], [[IF_END]] ] -; CHECK-NEXT: [[CONV51266:%.*]] = zext i8 [[TMP2]] to i32 -; CHECK-NEXT: [[CMP52267:%.*]] = icmp eq i32 [[SI_0274]], [[CONV51266]] +; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i8 +; CHECK-NEXT: [[CMP52267:%.*]] = icmp eq i32 [[SI_0274]], [[TMP3]] ; CHECK-NEXT: br i1 [[CMP52267]], label [[IF_END]], label [[EXIT:%.*]] ; CHECK: if.end: ; CHECK-NEXT: [[INC]] = add i32 [[SI_0274]], 1 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i32 [[INC]] -; CHECK-NEXT: [[TMP3]] = load i8, i8* [[GEP1]], align 1 +; CHECK-NEXT: [[TMP5:%.*]] = load i8, i8* [[GEP1]], align 1 +; CHECK-NEXT: [[TMP6]] = zext i8 [[TMP5]] to i32 ; CHECK-NEXT: br label [[BODY]] ; CHECK: exit: -; CHECK-NEXT: ret i8 [[TMP2]] +; CHECK-NEXT: [[TMP7:%.*]] = trunc i32 [[TMP3]] to i8 +; CHECK-NEXT: ret i8 [[TMP7]] ; entry: %gep = getelementptr inbounds i8, i8* %ptr, i32 0 @@ -108,21 +109,25 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i32 0 ; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[GEP]], align 1 -; CHECK-NEXT: [[TMP1:%.*]] = sub nuw nsw i8 [[TMP0]], 1 -; CHECK-NEXT: [[CONV44:%.*]] = zext i8 [[TMP0]] to i16 +; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i32 +; CHECK-NEXT: [[TMP2:%.*]] = sub nuw nsw i32 [[TMP1]], 1 +; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP1]] to i8 +; CHECK-NEXT: [[CONV44:%.*]] = zext i8 [[TMP3]] to i16 ; CHECK-NEXT: br label [[PREHEADER:%.*]] ; CHECK: preheader: ; CHECK-NEXT: br label [[BODY:%.*]] ; CHECK: body: -; CHECK-NEXT: [[TMP2:%.*]] = phi i8 [ [[TMP1]], [[PREHEADER]] ], [ [[TMP3:%.*]], [[IF_END:%.*]] ] +; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ [[TMP2]], [[PREHEADER]] ], [ [[TMP7:%.*]], [[IF_END:%.*]] ] ; CHECK-NEXT: [[SI_0274:%.*]] = phi i16 [ [[CONV44]], [[PREHEADER]] ], [ [[INC:%.*]], [[IF_END]] ] -; CHECK-NEXT: [[CONV51266:%.*]] = zext i8 [[TMP2]] to i16 +; CHECK-NEXT: [[TMP5:%.*]] = trunc i32 [[TMP4]] to i8 +; CHECK-NEXT: [[CONV51266:%.*]] = zext i8 [[TMP5]] to i16 ; CHECK-NEXT: [[CMP52267:%.*]] = icmp eq i16 [[SI_0274]], [[CONV51266]] ; CHECK-NEXT: br i1 [[CMP52267]], label [[IF_END]], label [[EXIT:%.*]] ; CHECK: if.end: ; CHECK-NEXT: [[INC]] = add i16 [[SI_0274]], 1 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[INC]] -; CHECK-NEXT: [[TMP3]] = load i8, i8* [[GEP1]], align 1 +; CHECK-NEXT: [[TMP6:%.*]] = load i8, i8* [[GEP1]], align 1 +; CHECK-NEXT: [[TMP7]] = zext i8 [[TMP6]] to i32 ; CHECK-NEXT: br label [[BODY]] ; CHECK: exit: ; CHECK-NEXT: [[RET:%.*]] = zext i16 [[CONV51266]] to i32