diff --git a/lib/Target/AArch64/AArch64FastISel.cpp b/lib/Target/AArch64/AArch64FastISel.cpp index 504049bbafd..559a6bdf8ea 100644 --- a/lib/Target/AArch64/AArch64FastISel.cpp +++ b/lib/Target/AArch64/AArch64FastISel.cpp @@ -590,7 +590,7 @@ bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty) std::swap(LHS, RHS); if (const ConstantInt *CI = dyn_cast(RHS)) { - Addr.setOffset(Addr.getOffset() + (uint64_t)CI->getSExtValue()); + Addr.setOffset(Addr.getOffset() + CI->getSExtValue()); return computeAddress(LHS, Addr, Ty); } @@ -601,6 +601,17 @@ bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty) break; } + case Instruction::Sub: { + // Subs of constants are common and easy enough. + const Value *LHS = U->getOperand(0); + const Value *RHS = U->getOperand(1); + + if (const ConstantInt *CI = dyn_cast(RHS)) { + Addr.setOffset(Addr.getOffset() - CI->getSExtValue()); + return computeAddress(LHS, Addr, Ty); + } + break; + } case Instruction::Shl: { if (Addr.getOffsetReg()) break; diff --git a/test/CodeGen/AArch64/fast-isel-int-ext.ll b/test/CodeGen/AArch64/fast-isel-int-ext.ll index 31372ee35bd..4a783a87a70 100644 --- a/test/CodeGen/AArch64/fast-isel-int-ext.ll +++ b/test/CodeGen/AArch64/fast-isel-int-ext.ll @@ -151,7 +151,7 @@ define i32 @load_unscaled_zext_i8_to_i32(i64 %a) { ; CHECK-LABEL: load_unscaled_zext_i8_to_i32 ; CHECK: ldurb w0, [x0, #-8] ; CHECK-NOT: uxtb - %1 = add i64 %a, -8 + %1 = sub i64 %a, 8 %2 = inttoptr i64 %1 to i8* %3 = load i8* %2 %4 = zext i8 %3 to i32 @@ -162,7 +162,7 @@ define i32 @load_unscaled_zext_i16_to_i32(i64 %a) { ; CHECK-LABEL: load_unscaled_zext_i16_to_i32 ; CHECK: ldurh w0, [x0, #-8] ; CHECK-NOT: uxth - %1 = add i64 %a, -8 + %1 = sub i64 %a, 8 %2 = inttoptr i64 %1 to i16* %3 = load i16* %2 %4 = zext i16 %3 to i32 @@ -173,7 +173,7 @@ define i64 @load_unscaled_zext_i8_to_i64(i64 %a) { ; CHECK-LABEL: load_unscaled_zext_i8_to_i64 ; CHECK: ldurb w0, [x0, #-8] ; CHECK-NOT: uxtb - %1 = add i64 %a, -8 + %1 = sub i64 %a, 8 %2 = inttoptr i64 %1 to i8* %3 = load i8* %2 %4 = zext i8 %3 to i64 @@ -184,7 +184,7 @@ define i64 @load_unscaled_zext_i16_to_i64(i64 %a) { ; CHECK-LABEL: load_unscaled_zext_i16_to_i64 ; CHECK: ldurh w0, [x0, #-8] ; CHECK-NOT: uxth - %1 = add i64 %a, -8 + %1 = sub i64 %a, 8 %2 = inttoptr i64 %1 to i16* %3 = load i16* %2 %4 = zext i16 %3 to i64 @@ -195,7 +195,7 @@ define i64 @load_unscaled_zext_i32_to_i64(i64 %a) { ; CHECK-LABEL: load_unscaled_zext_i32_to_i64 ; CHECK: ldur w0, [x0, #-8] ; CHECK-NOT: uxtw - %1 = add i64 %a, -8 + %1 = sub i64 %a, 8 %2 = inttoptr i64 %1 to i32* %3 = load i32* %2 %4 = zext i32 %3 to i64 @@ -206,7 +206,7 @@ define i32 @load_unscaled_sext_i8_to_i32(i64 %a) { ; CHECK-LABEL: load_unscaled_sext_i8_to_i32 ; CHECK: ldursb w0, [x0, #-8] ; CHECK-NOT: sxtb - %1 = add i64 %a, -8 + %1 = sub i64 %a, 8 %2 = inttoptr i64 %1 to i8* %3 = load i8* %2 %4 = sext i8 %3 to i32 @@ -217,7 +217,7 @@ define i32 @load_unscaled_sext_i16_to_i32(i64 %a) { ; CHECK-LABEL: load_unscaled_sext_i16_to_i32 ; CHECK: ldursh w0, [x0, #-8] ; CHECK-NOT: sxth - %1 = add i64 %a, -8 + %1 = sub i64 %a, 8 %2 = inttoptr i64 %1 to i16* %3 = load i16* %2 %4 = sext i16 %3 to i32 @@ -228,7 +228,7 @@ define i64 @load_unscaled_sext_i8_to_i64(i64 %a) { ; CHECK-LABEL: load_unscaled_sext_i8_to_i64 ; CHECK: ldursb x0, [x0, #-8] ; CHECK-NOT: sxtb - %1 = add i64 %a, -8 + %1 = sub i64 %a, 8 %2 = inttoptr i64 %1 to i8* %3 = load i8* %2 %4 = sext i8 %3 to i64 @@ -239,7 +239,7 @@ define i64 @load_unscaled_sext_i16_to_i64(i64 %a) { ; CHECK-LABEL: load_unscaled_sext_i16_to_i64 ; CHECK: ldursh x0, [x0, #-8] ; CHECK-NOT: sxth - %1 = add i64 %a, -8 + %1 = sub i64 %a, 8 %2 = inttoptr i64 %1 to i16* %3 = load i16* %2 %4 = sext i16 %3 to i64 @@ -250,7 +250,7 @@ define i64 @load_unscaled_sext_i32_to_i64(i64 %a) { ; CHECK-LABEL: load_unscaled_sext_i32_to_i64 ; CHECK: ldursw x0, [x0, #-8] ; CHECK-NOT: sxtw - %1 = add i64 %a, -8 + %1 = sub i64 %a, 8 %2 = inttoptr i64 %1 to i32* %3 = load i32* %2 %4 = sext i32 %3 to i64