[llvm] r285217 - [AArch64] Avoid materializing constant 1 when generating cneg instructions.
Chad Rosier via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 26 11:15:32 PDT 2016
Author: mcrosier
Date: Wed Oct 26 13:15:32 2016
New Revision: 285217
URL: http://llvm.org/viewvc/llvm-project?rev=285217&view=rev
Log:
[AArch64] Avoid materializing constant 1 when generating cneg instructions.
Instead of
cmp w0, #1
orr w8, wzr, #0x1
cneg w0, w8, ne
we now generate
cmp w0, #1
csinv w0, w0, wzr, eq
PR28965
Modified:
llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/trunk/test/CodeGen/AArch64/cond-sel-value-prop.ll
Modified: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp?rev=285217&r1=285216&r2=285217&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp Wed Oct 26 13:15:32 2016
@@ -4054,8 +4054,9 @@ SDValue AArch64TargetLowering::LowerSELE
// Avoid materializing a constant when possible by reusing a known value in
// a register. However, don't perform this optimization if the known value
- // is one, zero or negative one. We can always materialize these values
- // using CSINC, CSEL and CSINV with wzr/xzr as the FVal, respectively.
+ // is one, zero or negative one in the case of a CSEL. We can always
+ // materialize these values using CSINC, CSEL and CSINV with wzr/xzr as the
+ // FVal, respectively.
ConstantSDNode *RHSVal = dyn_cast<ConstantSDNode>(RHS);
if (Opcode == AArch64ISD::CSEL && RHSVal && !RHSVal->isOne() &&
!RHSVal->isNullValue() && !RHSVal->isAllOnesValue()) {
@@ -4066,6 +4067,16 @@ SDValue AArch64TargetLowering::LowerSELE
TVal = LHS;
else if (CFVal && CFVal == RHSVal && AArch64CC == AArch64CC::NE)
FVal = LHS;
+ } else if (Opcode == AArch64ISD::CSNEG && RHSVal && RHSVal->isOne()) {
+ assert (CTVal && CFVal && "Expected constant operands for CSNEG.");
+ // Use a CSINV to transform "a == C ? 1 : -1" to "a == C ? a : -1" to
+ // avoid materializing C.
+ AArch64CC::CondCode AArch64CC = changeIntCCToAArch64CC(CC);
+ if (CTVal == RHSVal && AArch64CC == AArch64CC::EQ) {
+ Opcode = AArch64ISD::CSINV;
+ TVal = LHS;
+ FVal = DAG.getConstant(0, dl, FVal.getValueType());
+ }
}
SDValue CCVal;
Modified: llvm/trunk/test/CodeGen/AArch64/cond-sel-value-prop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/cond-sel-value-prop.ll?rev=285217&r1=285216&r2=285217&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/cond-sel-value-prop.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/cond-sel-value-prop.ll Wed Oct 26 13:15:32 2016
@@ -97,3 +97,14 @@ define i64 @test9(i64 %x) {
%res = select i1 %cmp, i64 7, i64 -1
ret i64 %res
}
+
+; Rather than use a CNEG, use a CSINV to transform "a == 1 ? 1 : -1" to
+; "a == 1 ? a : -1" to avoid materializing a constant.
+; CHECK-LABEL: test10:
+; CHECK: cmp w[[REG:[0-9]]], #1
+; CHECK: cneg w0, w[[REG]], ne
+define i32 @test10(i32 %x) {
+ %cmp = icmp eq i32 %x, 1
+ %res = select i1 %cmp, i32 1, i32 -1
+ ret i32 %res
+}
More information about the llvm-commits
mailing list