-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[PowerPC][AIX] Using milicode for memcmp instead of libcall #147093
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-llvm-ir @llvm/pr-subscribers-backend-powerpc Author: zhijian lin (diggerlin) ChangesAIX has "millicode" routines, which are functions loaded at boot time into fixed addresses in kernel memory. This allows them to be customized for the processor. The __memcmp routine is a millicode implementation; we use millicode for the memcmp function instead of a library call to improve performance. Full diff: https://github.com/llvm/llvm-project/pull/147093.diff 3 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index ecd1ff87e7fbc..5bc71bdbccf43 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -9065,8 +9065,15 @@ bool SelectionDAGBuilder::visitMemCmpBCmpCall(const CallInst &I) {
// memcmp(S1,S2,2) != 0 -> (*(short*)LHS != *(short*)RHS) != 0
// memcmp(S1,S2,4) != 0 -> (*(int*)LHS != *(int*)RHS) != 0
- if (!CSize || !isOnlyUsedInZeroEqualityComparison(&I))
+ if (!CSize || !isOnlyUsedInZeroEqualityComparison(&I)) {
+ const Triple& TheTriple = TM.getTargetTriple();
+ if(TheTriple.isOSAIX()) {
+ if (Function *F = I.getCalledFunction()) {
+ F->setName(TheTriple.isArch32Bit() ? "___memcmp" : "___memcmp64");
+ }
+ }
return false;
+ }
// If the target has a fast compare for the given size, it will return a
// preferred load type for that size. Require that the load VT is legal and
diff --git a/llvm/test/CodeGen/PowerPC/memintr32.ll b/llvm/test/CodeGen/PowerPC/memintr32.ll
index c07a5af17e48a..4f0a9960a546d 100644
--- a/llvm/test/CodeGen/PowerPC/memintr32.ll
+++ b/llvm/test/CodeGen/PowerPC/memintr32.ll
@@ -11,7 +11,7 @@ define i32 @memcmp_test(ptr nocapture noundef readonly %ptr1, ptr nocapture noun
; CHECK-AIX-32-P9-NEXT: mflr r0
; CHECK-AIX-32-P9-NEXT: stwu r1, -64(r1)
; CHECK-AIX-32-P9-NEXT: stw r0, 72(r1)
-; CHECK-AIX-32-P9-NEXT: bl .memcmp[PR]
+; CHECK-AIX-32-P9-NEXT: bl .___memcmp[PR]
; CHECK-AIX-32-P9-NEXT: nop
; CHECK-AIX-32-P9-NEXT: addi r1, r1, 64
; CHECK-AIX-32-P9-NEXT: lwz r0, 8(r1)
diff --git a/llvm/test/CodeGen/PowerPC/memintr64.ll b/llvm/test/CodeGen/PowerPC/memintr64.ll
index b3a6650b8f6e6..0b0e556e89b51 100644
--- a/llvm/test/CodeGen/PowerPC/memintr64.ll
+++ b/llvm/test/CodeGen/PowerPC/memintr64.ll
@@ -39,7 +39,7 @@ define noundef i32 @_Z11memcmp_testPKvS0_m(ptr noundef readonly captures(none) %
; CHECK-AIX-64-P9-NEXT: mflr r0
; CHECK-AIX-64-P9-NEXT: stdu r1, -112(r1)
; CHECK-AIX-64-P9-NEXT: std r0, 128(r1)
-; CHECK-AIX-64-P9-NEXT: bl .memcmp[PR]
+; CHECK-AIX-64-P9-NEXT: bl .___memcmp64[PR]
; CHECK-AIX-64-P9-NEXT: nop
; CHECK-AIX-64-P9-NEXT: addi r1, r1, 112
; CHECK-AIX-64-P9-NEXT: ld r0, 16(r1)
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please apply clang-format to your changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The compiler should not directly emit string calls. This needs an entry in RuntimeLibcalls.td to emit the call. Further, this should not be based on a triple call in the DAG builder
const Triple& TheTriple = TM.getTargetTriple(); | ||
if(TheTriple.isOSAIX()) { | ||
if (Function *F = I.getCalledFunction()) { | ||
F->setName(TheTriple.isArch32Bit() ? "___memcmp" : "___memcmp64"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also mutating the IR, you cannot do that in codegen. It's also mutating the function itself, and not the call target
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also mutating the IR, you cannot do that in codegen. It's also mutating the function itself, and not the call target
do you means, we can not change the IR ?
in AIX, the function name will be used to generate an external symbol. and the AIX OS linker and loader will use the external symbol to find the correct function address in the memory , if we change the function name memcmp to function name to "___memcmp" (or ___memcmp64 for 64-bit AIX OS), it will change the call target.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You cannot change the IR, and you definitely cannot change a function name in a function pass. You either need to have this done in a separate IR pass (and change the call target to an explicit declaration of the new name), or directly change the call target that is emitted here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case you should be querying if there is an implementation of RTLIB::MEMCMP, and configuring the target to use RTLIB::___memcmp for RTLIB::MEMCMP
The
I will try not to use the triple call in the DAG builder |
Which is why they have separate entries in RuntimeLibcalls for the implementations. Every call target emitted by the compiler should be tracked in RuntimeLibcalls, and selectable through a generated enum value. No code should continue to emit functions directly by string name |
6eb1b0d
to
303de25
Compare
303de25
to
97837a2
Compare
AIX has "millicode" routines, which are functions loaded at boot time into fixed addresses in kernel memory. This allows them to be customized for the processor. The __memcmp routine is a millicode implementation; we use millicode for the memcmp function instead of a library call to improve performance.