riscv64 wants callees to sign extend signed and unsigned int returns. The caller can use this to avoid a sign extend if the result is used by a comparison since riscv64 only has 64-bit compares. InstCombine/SimplifyLibCalls aggressively turn memcmps that are only used by an icmp eq 0 into bcmp, but we lose the signext attribute that would have been present on the memcmp. This causes an unneeded sext.w in the generated assembly. This looks even sillier if bcmp is implemented alias to memcmp. In that case, not only did we not get any savings by using bcmp, we added an instruction. This probably applies to other functions, this just happens to be the one I noticed so far. See also the discussion here https://discourse.llvm.org/t/can-we-preserve-signext-return-attribute-when-converting-memcmp-to-bcmp/67126 Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D139901
20 lines
762 B
LLVM
20 lines
762 B
LLVM
; RUN: opt %s -passes=instcombine -mtriple=riscv64-unknown-linux-gnu -S | FileCheck %s
|
|
|
|
declare signext i32 @memcmp(ptr, ptr, i64)
|
|
|
|
; Make sure we use signext attribute for the bcmp result.
|
|
define signext i32 @test_bcmp(ptr %mem1, ptr %mem2, i64 %size) {
|
|
; CHECK-LABEL: define {{[^@]+}}@test_bcmp(
|
|
; CHECK-NEXT: [[BCMP:%.*]] = call i32 @bcmp(ptr [[MEM1:%.*]], ptr [[MEM2:%.*]], i64 [[SIZE:%.*]])
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[BCMP]], 0
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
|
|
; CHECK-NEXT: ret i32 [[ZEXT]]
|
|
;
|
|
%call = call signext i32 @memcmp(ptr %mem1, ptr %mem2, i64 %size)
|
|
%cmp = icmp eq i32 %call, 0
|
|
%zext = zext i1 %cmp to i32
|
|
ret i32 %zext
|
|
}
|
|
|
|
; CHECK: declare signext i32 @bcmp(ptr nocapture, ptr nocapture, i64)
|