diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp index 98410c2e747ea..7a8243ad7c943 100644 --- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp +++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp @@ -3838,11 +3838,6 @@ bool AArch64FastISel::selectRet(const Instruction *I) { if (!FuncInfo.CanLowerReturn) return false; - // FIXME: in principle it could. Mostly just a case of zero extending outgoing - // pointers. - if (Subtarget->isTargetILP32()) - return false; - if (F.isVarArg()) return false; @@ -3922,6 +3917,11 @@ bool AArch64FastISel::selectRet(const Instruction *I) { return false; } + // "Callee" (i.e. value producer) zero extends pointers at function + // boundary. + if (Subtarget->isTargetILP32() && RV->getType()->isPointerTy()) + SrcReg = emitAnd_ri(MVT::i64, SrcReg, false, 0xffffffff); + // Make the copy. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TargetOpcode::COPY), DestReg).addReg(SrcReg); @@ -5011,6 +5011,9 @@ std::pair AArch64FastISel::getRegForGEPIndex(const Value *Idx) { /// simple cases. This is because the standard fastEmit functions don't cover /// MUL at all and ADD is lowered very inefficientily. bool AArch64FastISel::selectGetElementPtr(const Instruction *I) { + if (Subtarget->isTargetILP32()) + return false; + unsigned N = getRegForValue(I->getOperand(0)); if (!N) return false; diff --git a/llvm/test/CodeGen/AArch64/arm64_32-fastisel.ll b/llvm/test/CodeGen/AArch64/arm64_32-fastisel.ll index 15baad215a181..0467a2cba8313 100644 --- a/llvm/test/CodeGen/AArch64/arm64_32-fastisel.ll +++ b/llvm/test/CodeGen/AArch64/arm64_32-fastisel.ll @@ -26,3 +26,24 @@ define void @test_struct_return(i32* %addr) { store i32 %res.1, i32* %addr ret void } + +define i8* @test_ret_ptr(i64 %in) { +; CHECK-LABEL: test_ret_ptr: +; CHECK: add [[TMP:x[0-9]]], x0, #1 +; CHECK: and x0, [[TMP]], #0xffffffff + + %sum = add i64 %in, 1 + %res = inttoptr i64 %sum to i8* + ret i8* %res +} + +; Handled by SDAG because the struct confuses FastISel, which is fine. +define {i8*} @test_ret_ptr_struct(i64 %in) { +; CHECK-LABEL: test_ret_ptr_struct: +; CHECK: add {{w[0-9]+}}, {{w[0-9]+}}, #1 + + %sum = add i64 %in, 1 + %res.ptr = inttoptr i64 %sum to i8* + %res = insertvalue {i8*} undef, i8* %res.ptr, 0 + ret {i8*} %res +} diff --git a/llvm/test/CodeGen/AArch64/arm64_32.ll b/llvm/test/CodeGen/AArch64/arm64_32.ll index 5fd619409a11d..ee8f4cc82957b 100644 --- a/llvm/test/CodeGen/AArch64/arm64_32.ll +++ b/llvm/test/CodeGen/AArch64/arm64_32.ll @@ -15,7 +15,9 @@ define i32* @test_global_addr() { ; CHECK-LABEL: test_global_addr: ; CHECK: adrp [[PAGE:x[0-9]+]], _var32@PAGE -; CHECK: add x0, [[PAGE]], _var32@PAGEOFF +; CHECK-OPT: add x0, [[PAGE]], _var32@PAGEOFF +; CHECK-FAST: add [[TMP:x[0-9]+]], [[PAGE]], _var32@PAGEOFF +; CHECK-FAST: and x0, [[TMP]], #0xffffffff ret i32* @var32 } @@ -156,7 +158,9 @@ define i32 @test_unsafe_negative_unscaled_add() { define i8* @test_got_addr() { ; CHECK-LABEL: test_got_addr: ; CHECK: adrp x[[PAGE:[0-9]+]], _var_got@GOTPAGE -; CHECK: ldr w0, [x[[PAGE]], _var_got@GOTPAGEOFF] +; CHECK-OPT: ldr w0, [x[[PAGE]], _var_got@GOTPAGEOFF] +; CHECK-FAST: ldr w[[TMP:[0-9]+]], [x[[PAGE]], _var_got@GOTPAGEOFF] +; CHECK-FAST: and x0, x[[TMP]], #0xffffffff ret i8* @var_got } @@ -229,7 +233,9 @@ declare i8* @llvm.frameaddress(i32) define i8* @test_frameaddr() { ; CHECK-LABEL: test_frameaddr: -; CHECK: ldr {{w0|x0}}, [x29] +; CHECK-OPT: ldr x0, [x29] +; CHECK-FAST: ldr [[TMP:x[0-9]+]], [x29] +; CHECK-FAST: and x0, [[TMP]], #0xffffffff %val = call i8* @llvm.frameaddress(i32 1) ret i8* %val } @@ -238,7 +244,8 @@ declare i8* @llvm.returnaddress(i32) define i8* @test_toplevel_returnaddr() { ; CHECK-LABEL: test_toplevel_returnaddr: -; CHECK: mov x0, x30 +; CHECK-OPT: mov x0, x30 +; CHECK-FAST: and x0, x30, #0xffffffff %val = call i8* @llvm.returnaddress(i32 0) ret i8* %val } @@ -246,7 +253,9 @@ define i8* @test_toplevel_returnaddr() { define i8* @test_deep_returnaddr() { ; CHECK-LABEL: test_deep_returnaddr: ; CHECK: ldr x[[FRAME_REC:[0-9]+]], [x29] -; CHECK: ldr x0, [x[[FRAME_REC]], #8] +; CHECK-OPT: ldr x0, [x[[FRAME_REC]], #8] +; CHECK-FAST: ldr [[TMP:x[0-9]+]], [x[[FRAME_REC]], #8] +; CHECK-FAST: and x0, [[TMP]], #0xffffffff %val = call i8* @llvm.returnaddress(i32 1) ret i8* %val } @@ -651,6 +660,7 @@ define void @test_struct_hi(i32 %hi) nounwind { ; CHECK-LABEL: test_struct_hi: ; CHECK: mov w[[IN:[0-9]+]], w0 ; CHECK: bl _get_int +; CHECK-FAST-NEXT: mov w0, w0 ; CHECK-NEXT: bfi x0, x[[IN]], #32, #32 ; CHECK-NEXT: bl _take_pair %val.64 = call i64 @get_int() @@ -691,9 +701,14 @@ false: define { [18 x i8] }* @test_gep_nonpow2({ [18 x i8] }* %a0, i32 %a1) { ; CHECK-LABEL: test_gep_nonpow2: -; CHECK: mov w[[SIZE:[0-9]+]], #18 -; CHECK-NEXT: smaddl x0, w1, w[[SIZE]], x0 -; CHECK-NEXT: ret +; CHECK-OPT: mov w[[SIZE:[0-9]+]], #18 +; CHECK-OPT-NEXT: smaddl x0, w1, w[[SIZE]], x0 +; CHECK-OPT-NEXT: ret + +; CHECK-FAST: mov w[[SIZE:[0-9]+]], #18 +; CHECK-FAST-NEXT: smaddl [[TMP:x[0-9]+]], w1, w[[SIZE]], x0 +; CHECK-FAST-NEXT: and x0, [[TMP]], #0xffffffff +; CHECK-FAST-NEXT: ret %tmp0 = getelementptr inbounds { [18 x i8] }, { [18 x i8] }* %a0, i32 %a1 ret { [18 x i8] }* %tmp0 }