[FastIsel][AArch64] Fix a think-o in address computation.

When looking through sign/zero-extensions the code would always assume there is
such an extension instruction and use the wrong operand for the address.

There was also a minor issue in the handling of 'AND' instructions. I
accidentially used a 'cast' instead of a 'dyn_cast'.

llvm-svn: 218161
This commit is contained in:
Juergen Ributzka 2014-09-19 22:23:46 +00:00
parent 684981e454
commit 92e8978e40
2 changed files with 66 additions and 20 deletions

View File

@ -561,7 +561,7 @@ bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty)
break;
}
case Instruction::Shl:
case Instruction::Shl: {
if (Addr.getOffsetReg())
break;
@ -584,19 +584,24 @@ bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty)
Addr.setShift(Val);
Addr.setExtendType(AArch64_AM::LSL);
if (const auto *I = dyn_cast<Instruction>(U->getOperand(0)))
const Value *Src = U->getOperand(0);
if (const auto *I = dyn_cast<Instruction>(Src))
if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB)
U = I;
Src = I;
if (const auto *ZE = dyn_cast<ZExtInst>(U))
if (ZE->getOperand(0)->getType()->isIntegerTy(32))
if (const auto *ZE = dyn_cast<ZExtInst>(Src)) {
if (ZE->getOperand(0)->getType()->isIntegerTy(32)) {
Addr.setExtendType(AArch64_AM::UXTW);
if (const auto *SE = dyn_cast<SExtInst>(U))
if (SE->getOperand(0)->getType()->isIntegerTy(32))
Src = ZE->getOperand(0);
}
} else if (const auto *SE = dyn_cast<SExtInst>(Src)) {
if (SE->getOperand(0)->getType()->isIntegerTy(32)) {
Addr.setExtendType(AArch64_AM::SXTW);
Src = SE->getOperand(0);
}
}
if (const auto *AI = dyn_cast<BinaryOperator>(U))
if (const auto *AI = dyn_cast<BinaryOperator>(Src))
if (AI->getOpcode() == Instruction::And) {
const Value *LHS = AI->getOperand(0);
const Value *RHS = AI->getOperand(1);
@ -605,7 +610,7 @@ bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty)
if (C->getValue() == 0xffffffff)
std::swap(LHS, RHS);
if (const auto *C = cast<ConstantInt>(RHS))
if (const auto *C = dyn_cast<ConstantInt>(RHS))
if (C->getValue() == 0xffffffff) {
Addr.setExtendType(AArch64_AM::UXTW);
unsigned Reg = getRegForValue(LHS);
@ -619,13 +624,14 @@ bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty)
}
}
unsigned Reg = getRegForValue(U->getOperand(0));
unsigned Reg = getRegForValue(Src);
if (!Reg)
return false;
Addr.setOffsetReg(Reg);
return true;
}
break;
}
case Instruction::Mul: {
if (Addr.getOffsetReg())
break;
@ -661,23 +667,24 @@ bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty)
Addr.setShift(Val);
Addr.setExtendType(AArch64_AM::LSL);
if (const auto *I = dyn_cast<Instruction>(LHS))
const Value *Src = LHS;
if (const auto *I = dyn_cast<Instruction>(Src))
if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB)
U = I;
Src = I;
if (const auto *ZE = dyn_cast<ZExtInst>(U))
if (const auto *ZE = dyn_cast<ZExtInst>(Src)) {
if (ZE->getOperand(0)->getType()->isIntegerTy(32)) {
Addr.setExtendType(AArch64_AM::UXTW);
LHS = U->getOperand(0);
Src = ZE->getOperand(0);
}
if (const auto *SE = dyn_cast<SExtInst>(U))
} else if (const auto *SE = dyn_cast<SExtInst>(Src)) {
if (SE->getOperand(0)->getType()->isIntegerTy(32)) {
Addr.setExtendType(AArch64_AM::SXTW);
LHS = U->getOperand(0);
Src = SE->getOperand(0);
}
}
unsigned Reg = getRegForValue(LHS);
unsigned Reg = getRegForValue(Src);
if (!Reg)
return false;
Addr.setOffsetReg(Reg);
@ -697,7 +704,7 @@ bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty)
if (C->getValue() == 0xffffffff)
std::swap(LHS, RHS);
if (const auto *C = cast<ConstantInt>(RHS))
if (const auto *C = dyn_cast<ConstantInt>(RHS))
if (C->getValue() == 0xffffffff) {
Addr.setShift(0);
Addr.setExtendType(AArch64_AM::LSL);

View File

@ -450,6 +450,30 @@ define i64 @load_breg_and_offreg_4(i64 %a, i64 %b) {
ret i64 %5
}
; Not all 'and' instructions have immediates.
define i64 @load_breg_and_offreg_5(i64 %a, i64 %b, i64 %c) {
; CHECK-LABEL: load_breg_and_offreg_5
; CHECK: and [[REG:x[0-9]+]], x0, x2
; CHECK-NEXT: ldr {{x[0-9]+}}, {{\[}}[[REG]], x1{{\]}}
%1 = and i64 %a, %c
%2 = add i64 %1, %b
%3 = inttoptr i64 %2 to i64*
%4 = load i64* %3
ret i64 %4
}
define i64 @load_breg_and_offreg_6(i64 %a, i64 %b, i64 %c) {
; CHECK-LABEL: load_breg_and_offreg_6
; CHECK: and [[REG:x[0-9]+]], x0, x2
; CHECK-NEXT: ldr {{x[0-9]+}}, {{\[}}x1, [[REG]], lsl #3{{\]}}
%1 = and i64 %a, %c
%2 = shl i64 %1, 3
%3 = add i64 %2, %b
%4 = inttoptr i64 %3 to i64*
%5 = load i64* %4
ret i64 %5
}
; Load Base Register + Scaled Register Offset + Sign/Zero extension
define i32 @load_breg_zext_shift_offreg_1(i32 %a, i64 %b) {
; CHECK-LABEL: load_breg_zext_shift_offreg_1
@ -506,6 +530,21 @@ define i32 @load_breg_sext_shift_offreg_2(i32 %a, i64 %b) {
ret i32 %5
}
; Make sure that we don't drop the first 'add' instruction.
define i32 @load_breg_sext_shift_offreg_3(i32 %a, i64 %b) {
; CHECK-LABEL: load_breg_sext_shift_offreg_3
; CHECK: add [[REG:w[0-9]+]], w0, #4
; CHECK: ldr {{w[0-9]+}}, {{\[}}x1, [[REG]], sxtw #2{{\]}}
%1 = add i32 %a, 4
%2 = sext i32 %1 to i64
%3 = shl i64 %2, 2
%4 = add i64 %b, %3
%5 = inttoptr i64 %4 to i32*
%6 = load i32* %5
ret i32 %6
}
define i32 @load_breg_sext_mul_offreg_1(i32 %a, i64 %b) {
; CHECK-LABEL: load_breg_sext_mul_offreg_1
; CHECK: ldr {{w[0-9]+}}, [x1, w0, sxtw #2]