diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h @@ -204,6 +204,7 @@ bool isLegalICmpImmediate(int64_t Imm) const override; bool isLegalAddImmediate(int64_t Imm) const override; + bool isZExtFree(SDValue Val, EVT VT2) const override; bool hasAndNotCompare(SDValue Y) const override; diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -3255,6 +3255,21 @@ return isInt<12>(Imm); } +bool LoongArchTargetLowering::isZExtFree(SDValue Val, EVT VT2) const { + // Zexts are free if they can be combined with a load. + // Don't advertise i32->i64 zextload as being free for LA64. It interacts + // poorly with type legalization of compares preferring sext. + if (auto *LD = dyn_cast(Val)) { + EVT MemVT = LD->getMemoryVT(); + if ((MemVT == MVT::i8 || MemVT == MVT::i16) && + (LD->getExtensionType() == ISD::NON_EXTLOAD || + LD->getExtensionType() == ISD::ZEXTLOAD)) + return true; + } + + return TargetLowering::isZExtFree(Val, VT2); +} + bool LoongArchTargetLowering::hasAndNotCompare(SDValue Y) const { // TODO: Support vectors. if (Y.getValueType().isVector()) diff --git a/llvm/test/CodeGen/LoongArch/zext-with-load-is-free.ll b/llvm/test/CodeGen/LoongArch/zext-with-load-is-free.ll --- a/llvm/test/CodeGen/LoongArch/zext-with-load-is-free.ll +++ b/llvm/test/CodeGen/LoongArch/zext-with-load-is-free.ll @@ -7,14 +7,12 @@ define zeroext i8 @test_zext_i8(ptr %p) nounwind { ; LA32-LABEL: test_zext_i8: ; LA32: # %bb.0: -; LA32-NEXT: ld.b $a0, $a0, 0 -; LA32-NEXT: andi $a0, $a0, 255 +; LA32-NEXT: ld.bu $a0, $a0, 0 ; LA32-NEXT: ret ; ; LA64-LABEL: test_zext_i8: ; LA64: # %bb.0: -; LA64-NEXT: ld.b $a0, $a0, 0 -; LA64-NEXT: andi $a0, $a0, 255 +; LA64-NEXT: ld.bu $a0, $a0, 0 ; LA64-NEXT: ret %a = load i8, ptr %p, align 1 br label %exit @@ -26,16 +24,14 @@ ; LA32-LABEL: test_zext_i16: ; LA32: # %bb.0: ; LA32-NEXT: ld.bu $a1, $a0, 0 -; LA32-NEXT: ld.b $a0, $a0, 1 +; LA32-NEXT: ld.bu $a0, $a0, 1 ; LA32-NEXT: slli.w $a0, $a0, 8 ; LA32-NEXT: or $a0, $a0, $a1 -; LA32-NEXT: bstrpick.w $a0, $a0, 15, 0 ; LA32-NEXT: ret ; ; LA64-LABEL: test_zext_i16: ; LA64: # %bb.0: -; LA64-NEXT: ld.h $a0, $a0, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 15, 0 +; LA64-NEXT: ld.hu $a0, $a0, 0 ; LA64-NEXT: ret %a = load i16, ptr %p, align 1 br label %exit