diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -30,6 +30,7 @@ class MachineOperand; class GISelKnownBits; class MachineDominatorTree; +class LegalizerInfo; struct PreferredTuple { LLT Ty; // The result type of the extend. @@ -56,11 +57,13 @@ GISelChangeObserver &Observer; GISelKnownBits *KB; MachineDominatorTree *MDT; + const LegalizerInfo *LI; public: CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B, GISelKnownBits *KB = nullptr, - MachineDominatorTree *MDT = nullptr); + MachineDominatorTree *MDT = nullptr, + const LegalizerInfo *LI = nullptr); GISelKnownBits *getKnownBits() const { return KB; diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -9,6 +9,7 @@ #include "llvm/CodeGen/GlobalISel/Combiner.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" +#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/GlobalISel/Utils.h" @@ -36,9 +37,10 @@ CombinerHelper::CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B, GISelKnownBits *KB, - MachineDominatorTree *MDT) + MachineDominatorTree *MDT, + const LegalizerInfo *LI) : Builder(B), MRI(Builder.getMF().getRegInfo()), Observer(Observer), - KB(KB), MDT(MDT) { + KB(KB), MDT(MDT), LI(LI) { (void)this->KB; } @@ -405,7 +407,20 @@ for (auto &UseMI : MRI.use_nodbg_instructions(LoadValue.getReg())) { if (UseMI.getOpcode() == TargetOpcode::G_SEXT || UseMI.getOpcode() == TargetOpcode::G_ZEXT || - UseMI.getOpcode() == TargetOpcode::G_ANYEXT) { + (UseMI.getOpcode() == TargetOpcode::G_ANYEXT)) { + // Check for legality. + if (LI) { + LegalityQuery::MemDesc MMDesc; + const auto &MMO = **MI.memoperands_begin(); + MMDesc.SizeInBits = MMO.getSizeInBits(); + MMDesc.AlignInBits = MMO.getAlign().value() * 8; + MMDesc.Ordering = MMO.getOrdering(); + LLT UseTy = MRI.getType(UseMI.getOperand(0).getReg()); + LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); + if (LI->getAction({MI.getOpcode(), {UseTy, SrcTy}, {MMDesc}}).Action != + LegalizeActions::Legal) + continue; + } Preferred = ChoosePreferredUse(Preferred, MRI.getType(UseMI.getOperand(0).getReg()), UseMI.getOpcode(), &UseMI); diff --git a/llvm/lib/Target/AArch64/AArch64Combine.td b/llvm/lib/Target/AArch64/AArch64Combine.td --- a/llvm/lib/Target/AArch64/AArch64Combine.td +++ b/llvm/lib/Target/AArch64/AArch64Combine.td @@ -24,7 +24,8 @@ let DisableRuleOption = "aarch64prelegalizercombiner-disable-rule"; } -def AArch64PostLegalizerCombinerHelper: GICombinerHelper< - "AArch64GenPostLegalizerCombinerHelper", [erase_undef_store]> { +def AArch64PostLegalizerCombinerHelper + : GICombinerHelper<"AArch64GenPostLegalizerCombinerHelper", + [erase_undef_store, combines_for_extload]> { let DisableRuleOption = "aarch64postlegalizercombiner-disable-rule"; } diff --git a/llvm/lib/Target/AArch64/AArch64PostLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/AArch64PostLegalizerCombiner.cpp --- a/llvm/lib/Target/AArch64/AArch64PostLegalizerCombiner.cpp +++ b/llvm/lib/Target/AArch64/AArch64PostLegalizerCombiner.cpp @@ -61,7 +61,9 @@ bool AArch64PostLegalizerCombinerInfo::combine(GISelChangeObserver &Observer, MachineInstr &MI, MachineIRBuilder &B) const { - CombinerHelper Helper(Observer, B, KB, MDT); + const auto *LI = + MI.getParent()->getParent()->getSubtarget().getLegalizerInfo(); + CombinerHelper Helper(Observer, B, KB, MDT, LI); return Generated.tryCombineAll(Observer, MI, B, Helper); } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizercombiner-extending-loads.mir b/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizercombiner-extending-loads.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizercombiner-extending-loads.mir @@ -0,0 +1,50 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -run-pass=aarch64-postlegalizer-combiner -global-isel -verify-machineinstrs %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + define void @test_zeroext(i8* %addr) { + entry: + ret void + } + define void @test_no_anyext(i8* %addr) { + entry: + ret void + } +... + +--- +name: test_zeroext +legalized: true +body: | + bb.0.entry: + liveins: $x0 + ; CHECK-LABEL: name: test_zeroext + ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 + ; CHECK: [[ZEXTLOAD:%[0-9]+]]:_(s32) = G_ZEXTLOAD [[COPY]](p0) :: (load 1 from %ir.addr) + ; CHECK: $w0 = COPY [[ZEXTLOAD]](s32) + %0:_(p0) = COPY $x0 + %1:_(s8) = G_LOAD %0 :: (load 1 from %ir.addr) + %2:_(s32) = G_ZEXT %1 + $w0 = COPY %2 +... + +--- +name: test_no_anyext +legalized: true +body: | + bb.0.entry: + liveins: $x0 + ; Check that we don't try to do an anyext combine. We don't want to do this + ; because an anyexting load like s64 = G_LOAD %p (load 4) isn't legal. + ; CHECK-LABEL: name: test_no_anyext + ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 + ; CHECK: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[COPY]](p0) :: (load 4 from %ir.addr) + ; CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[LOAD]](s32) + ; CHECK: $x0 = COPY [[ANYEXT]](s64) + %0:_(p0) = COPY $x0 + %1:_(s32) = G_LOAD %0 :: (load 4 from %ir.addr) + %2:_(s64) = G_ANYEXT %1 + $x0 = COPY %2 +...