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 @@ -3251,6 +3251,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 @@ -16,8 +16,7 @@ ; LA32-NEXT: ori $a2, $zero, 136 ; LA32-NEXT: bne $a1, $a2, .LBB0_3 ; LA32-NEXT: # %bb.1: # %entry -; LA32-NEXT: ld.b $a0, $a0, 1 -; LA32-NEXT: andi $a0, $a0, 255 +; LA32-NEXT: ld.bu $a0, $a0, 1 ; LA32-NEXT: ori $a1, $zero, 7 ; LA32-NEXT: bne $a0, $a1, .LBB0_3 ; LA32-NEXT: # %bb.2: # %if.end @@ -35,8 +34,7 @@ ; LA64-NEXT: ori $a2, $zero, 136 ; LA64-NEXT: bne $a1, $a2, .LBB0_3 ; LA64-NEXT: # %bb.1: # %entry -; LA64-NEXT: ld.b $a0, $a0, 1 -; LA64-NEXT: andi $a0, $a0, 255 +; LA64-NEXT: ld.bu $a0, $a0, 1 ; LA64-NEXT: ori $a1, $zero, 7 ; LA64-NEXT: bne $a0, $a1, .LBB0_3 ; LA64-NEXT: # %bb.2: # %if.end @@ -72,8 +70,7 @@ ; LA32-NEXT: ld.hu $a2, $a0, 0 ; LA32-NEXT: bne $a2, $a1, .LBB1_3 ; LA32-NEXT: # %bb.1: # %entry -; LA32-NEXT: ld.h $a0, $a0, 2 -; LA32-NEXT: bstrpick.w $a0, $a0, 15, 0 +; LA32-NEXT: ld.hu $a0, $a0, 2 ; LA32-NEXT: ori $a1, $zero, 7 ; LA32-NEXT: bne $a0, $a1, .LBB1_3 ; LA32-NEXT: # %bb.2: # %if.end @@ -92,8 +89,7 @@ ; LA64-NEXT: ld.hu $a2, $a0, 0 ; LA64-NEXT: bne $a2, $a1, .LBB1_3 ; LA64-NEXT: # %bb.1: # %entry -; LA64-NEXT: ld.h $a0, $a0, 2 -; LA64-NEXT: bstrpick.d $a0, $a0, 15, 0 +; LA64-NEXT: ld.hu $a0, $a0, 2 ; LA64-NEXT: ori $a1, $zero, 7 ; LA64-NEXT: bne $a0, $a1, .LBB1_3 ; LA64-NEXT: # %bb.2: # %if.end