From 92e8978e4031cda35d282013919a81bdc3b2d79d Mon Sep 17 00:00:00 2001 From: Juergen Ributzka Date: Fri, 19 Sep 2014 22:23:46 +0000 Subject: [PATCH] [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 --- llvm/lib/Target/AArch64/AArch64FastISel.cpp | 47 +++++++++++-------- .../AArch64/fast-isel-addressing-modes.ll | 39 +++++++++++++++ 2 files changed, 66 insertions(+), 20 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp index 1ba5ba5de70b..f09f60032894 100644 --- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp +++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp @@ -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(U->getOperand(0))) + const Value *Src = U->getOperand(0); + if (const auto *I = dyn_cast(Src)) if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) - U = I; + Src = I; - if (const auto *ZE = dyn_cast(U)) - if (ZE->getOperand(0)->getType()->isIntegerTy(32)) + if (const auto *ZE = dyn_cast(Src)) { + if (ZE->getOperand(0)->getType()->isIntegerTy(32)) { Addr.setExtendType(AArch64_AM::UXTW); - - if (const auto *SE = dyn_cast(U)) - if (SE->getOperand(0)->getType()->isIntegerTy(32)) + Src = ZE->getOperand(0); + } + } else if (const auto *SE = dyn_cast(Src)) { + if (SE->getOperand(0)->getType()->isIntegerTy(32)) { Addr.setExtendType(AArch64_AM::SXTW); + Src = SE->getOperand(0); + } + } - if (const auto *AI = dyn_cast(U)) + if (const auto *AI = dyn_cast(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(RHS)) + if (const auto *C = dyn_cast(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(LHS)) + const Value *Src = LHS; + if (const auto *I = dyn_cast(Src)) if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) - U = I; + Src = I; - if (const auto *ZE = dyn_cast(U)) + if (const auto *ZE = dyn_cast(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(U)) + } else if (const auto *SE = dyn_cast(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(RHS)) + if (const auto *C = dyn_cast(RHS)) if (C->getValue() == 0xffffffff) { Addr.setShift(0); Addr.setExtendType(AArch64_AM::LSL); diff --git a/llvm/test/CodeGen/AArch64/fast-isel-addressing-modes.ll b/llvm/test/CodeGen/AArch64/fast-isel-addressing-modes.ll index e562a5dba05e..be2dc317a476 100644 --- a/llvm/test/CodeGen/AArch64/fast-isel-addressing-modes.ll +++ b/llvm/test/CodeGen/AArch64/fast-isel-addressing-modes.ll @@ -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]