ARM FastISel fix sext/zext fold

Sign- and zero-extension folding was slightly incorrect because it wasn't checking that the shift on extensions was zero. Further, I recently added AND rd, rn, #255 as a form of 8-bit zero extension, and failed to add the folding code for it.

This patch fixes both issues.

This patch fixes both, and the test should remain the same:
  test/CodeGen/ARM/fast-isel-fold.ll

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183794 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
JF Bastien 2013-06-11 22:13:46 +00:00
parent a85644459c
commit 5ab770417b

View File

@ -20,6 +20,7 @@
#include "ARMSubtarget.h"
#include "ARMTargetMachine.h"
#include "MCTargetDesc/ARMAddressingModes.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/FastISel.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
@ -2863,6 +2864,25 @@ bool ARMFastISel::TargetSelectInstruction(const Instruction *I) {
return false;
}
namespace {
// This table describes sign- and zero-extend instructions which can be
// folded into a preceding load. All of these extends have an immediate
// (sometimes a mask and sometimes a shift) that's applied after
// extension.
const struct FoldableLoadExtendsStruct {
uint16_t Opc[2]; // ARM, Thumb.
uint8_t ExpectedImm;
uint8_t isZExt : 1;
uint8_t ExpectedVT : 7;
} FoldableLoadExtends[] = {
{ { ARM::SXTH, ARM::t2SXTH }, 0, 0, MVT::i16 },
{ { ARM::UXTH, ARM::t2UXTH }, 0, 1, MVT::i16 },
{ { ARM::ANDri, ARM::t2ANDri }, 255, 1, MVT::i8 },
{ { ARM::SXTB, ARM::t2SXTB }, 0, 0, MVT::i8 },
{ { ARM::UXTB, ARM::t2UXTB }, 0, 1, MVT::i8 }
};
}
/// \brief The specified machine instr operand is a vreg, and that
/// vreg is being provided by the specified load instruction. If possible,
/// try to fold the load as an operand to the instruction, returning true if
@ -2878,26 +2898,23 @@ bool ARMFastISel::tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
// ldrb r1, [r0] ldrb r1, [r0]
// uxtb r2, r1 =>
// mov r3, r2 mov r3, r1
bool isZExt = true;
switch(MI->getOpcode()) {
default: return false;
case ARM::SXTH:
case ARM::t2SXTH:
isZExt = false;
case ARM::UXTH:
case ARM::t2UXTH:
if (VT != MVT::i16)
return false;
break;
case ARM::SXTB:
case ARM::t2SXTB:
isZExt = false;
case ARM::UXTB:
case ARM::t2UXTB:
if (VT != MVT::i8)
return false;
break;
if (MI->getNumOperands() < 3 || !MI->getOperand(2).isImm())
return false;
const uint64_t Imm = MI->getOperand(2).getImm();
bool Found = false;
bool isZExt;
for (unsigned i = 0, e = array_lengthof(FoldableLoadExtends);
i != e; ++i) {
if (FoldableLoadExtends[i].Opc[isThumb2] == MI->getOpcode() &&
(uint64_t)FoldableLoadExtends[i].ExpectedImm == Imm &&
MVT((MVT::SimpleValueType)FoldableLoadExtends[i].ExpectedVT) == VT) {
Found = true;
isZExt = FoldableLoadExtends[i].isZExt;
}
}
if (!Found) return false;
// See if we can handle this address.
Address Addr;
if (!ARMComputeAddress(LI->getOperand(0), Addr)) return false;