[llvm] decf385 - [RISCV] Teach targetShrinkDemandedConstant to handle OR and XOR.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 17 12:39:57 PDT 2022


Author: Craig Topper
Date: 2022-07-17T12:36:33-07:00
New Revision: decf385c270ed814ac00331410b34fdea4e0b2b1

URL: https://github.com/llvm/llvm-project/commit/decf385c270ed814ac00331410b34fdea4e0b2b1
DIFF: https://github.com/llvm/llvm-project/commit/decf385c270ed814ac00331410b34fdea4e0b2b1.diff

LOG: [RISCV] Teach targetShrinkDemandedConstant to handle OR and XOR.

We were only handling AND before, but SimplifyDemandedBits can
also call it for OR and XOR.

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp
    llvm/test/CodeGen/RISCV/legalize-fneg.ll
    llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 658865703079..382dbb97c728 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -9357,7 +9357,8 @@ bool RISCVTargetLowering::targetShrinkDemandedConstant(
     return false;
 
   // Only handle AND for now.
-  if (Op.getOpcode() != ISD::AND)
+  unsigned Opcode = Op.getOpcode();
+  if (Opcode != ISD::AND && Opcode != ISD::OR && Opcode != ISD::XOR)
     return false;
 
   ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
@@ -9376,12 +9377,13 @@ bool RISCVTargetLowering::targetShrinkDemandedConstant(
   auto IsLegalMask = [ShrunkMask, ExpandedMask](const APInt &Mask) -> bool {
     return ShrunkMask.isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
   };
-  auto UseMask = [Mask, Op, VT, &TLO](const APInt &NewMask) -> bool {
+  auto UseMask = [Mask, Op, &TLO](const APInt &NewMask) -> bool {
     if (NewMask == Mask)
       return true;
     SDLoc DL(Op);
-    SDValue NewC = TLO.DAG.getConstant(NewMask, DL, VT);
-    SDValue NewOp = TLO.DAG.getNode(ISD::AND, DL, VT, Op.getOperand(0), NewC);
+    SDValue NewC = TLO.DAG.getConstant(NewMask, DL, Op.getValueType());
+    SDValue NewOp = TLO.DAG.getNode(Op.getOpcode(), DL, Op.getValueType(),
+                                    Op.getOperand(0), NewC);
     return TLO.CombineTo(Op, NewOp);
   };
 
@@ -9390,18 +9392,21 @@ bool RISCVTargetLowering::targetShrinkDemandedConstant(
   if (ShrunkMask.isSignedIntN(12))
     return false;
 
-  // Preserve (and X, 0xffff) when zext.h is supported.
-  if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbp()) {
-    APInt NewMask = APInt(Mask.getBitWidth(), 0xffff);
-    if (IsLegalMask(NewMask))
-      return UseMask(NewMask);
-  }
+  // And has a few special cases for zext.
+  if (Opcode == ISD::AND) {
+    // Preserve (and X, 0xffff) when zext.h is supported.
+    if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbp()) {
+      APInt NewMask = APInt(Mask.getBitWidth(), 0xffff);
+      if (IsLegalMask(NewMask))
+        return UseMask(NewMask);
+    }
 
-  // Try to preserve (and X, 0xffffffff), the (zext_inreg X, i32) pattern.
-  if (VT == MVT::i64) {
-    APInt NewMask = APInt(64, 0xffffffff);
-    if (IsLegalMask(NewMask))
-      return UseMask(NewMask);
+    // Try to preserve (and X, 0xffffffff), the (zext_inreg X, i32) pattern.
+    if (VT == MVT::i64) {
+      APInt NewMask = APInt(64, 0xffffffff);
+      if (IsLegalMask(NewMask))
+        return UseMask(NewMask);
+    }
   }
 
   // For the remaining optimizations, we need to be able to make a negative
@@ -9414,10 +9419,11 @@ bool RISCVTargetLowering::targetShrinkDemandedConstant(
 
   // Try to make a 12 bit negative immediate. If that fails try to make a 32
   // bit negative immediate unless the shrunk immediate already fits in 32 bits.
+  // If we can't create a simm12, we shouldn't change opaque constants.
   APInt NewMask = ShrunkMask;
   if (MinSignedBits <= 12)
     NewMask.setBitsFrom(11);
-  else if (MinSignedBits <= 32 && !ShrunkMask.isSignedIntN(32))
+  else if (!C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.isSignedIntN(32))
     NewMask.setBitsFrom(31);
   else
     return false;

diff  --git a/llvm/test/CodeGen/RISCV/legalize-fneg.ll b/llvm/test/CodeGen/RISCV/legalize-fneg.ll
index b35884f8f87c..9037a0021c5f 100644
--- a/llvm/test/CodeGen/RISCV/legalize-fneg.ll
+++ b/llvm/test/CodeGen/RISCV/legalize-fneg.ll
@@ -16,8 +16,7 @@ define void @test1(float* %a, float* %b) nounwind {
 ; RV64-LABEL: test1:
 ; RV64:       # %bb.0: # %entry
 ; RV64-NEXT:    lw a1, 0(a1)
-; RV64-NEXT:    li a2, 1
-; RV64-NEXT:    slli a2, a2, 31
+; RV64-NEXT:    lui a2, 524288
 ; RV64-NEXT:    xor a1, a1, a2
 ; RV64-NEXT:    sw a1, 0(a0)
 ; RV64-NEXT:    ret

diff  --git a/llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll b/llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll
index 5bcadf4dce00..ca9f43dd7ad7 100644
--- a/llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll
+++ b/llvm/test/CodeGen/RISCV/rv64i-demanded-bits.ll
@@ -5,7 +5,6 @@
 ; legalization. There are 2 opportunities on the chain feeding the LHS of the
 ; shl. And one opportunity on the shift amount. We previously weren't managing
 ; the DAGCombiner worklist correctly and failed to get the RHS.
-
 define i32 @foo(i32 %x, i32 %y, i32 %z) {
 ; CHECK-LABEL: foo:
 ; CHECK:       # %bb.0:
@@ -37,3 +36,65 @@ define i64 @mul_self_nsw_sign(i64 %x) {
   %b = and i64 %a, 9223372036854775800
   ret i64 %b
 }
+
+; Make sure we sign extend the constant after type legalization to allow the
+; use of ori.
+define void @ori(ptr nocapture noundef %0) {
+; CHECK-LABEL: ori:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a0)
+; CHECK-NEXT:    ori a1, a1, -2
+; CHECK-NEXT:    sw a1, 0(a0)
+; CHECK-NEXT:    ret
+  %2 = load i32, ptr %0, align 4
+  %3 = or i32 %2, -2
+  store i32 %3, ptr %0, align 4
+  ret void
+}
+
+; Make sure we sign extend the constant after type legalization to allow the
+; use of xori.
+define void @xori(ptr nocapture noundef %0) {
+; CHECK-LABEL: xori:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a0)
+; CHECK-NEXT:    xori a1, a1, -5
+; CHECK-NEXT:    sw a1, 0(a0)
+; CHECK-NEXT:    ret
+  %2 = load i32, ptr %0, align 4
+  %3 = xor i32 %2, -5
+  store i32 %3, ptr %0, align 4
+  ret void
+}
+
+; Make sure we sign extend the constant after type legalization to allow the
+; shorter constant materialization.
+define void @or_signbit(ptr nocapture noundef %0) {
+; CHECK-LABEL: or_signbit:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a0)
+; CHECK-NEXT:    lui a2, 524288
+; CHECK-NEXT:    or a1, a1, a2
+; CHECK-NEXT:    sw a1, 0(a0)
+; CHECK-NEXT:    ret
+  %2 = load i32, ptr %0, align 4
+  %3 = or i32 %2, -2147483648
+  store i32 %3, ptr %0, align 4
+  ret void
+}
+
+; Make sure we sign extend the constant after type legalization to allow the
+; shorter constant materialization.
+define void @xor_signbit(ptr nocapture noundef %0) {
+; CHECK-LABEL: xor_signbit:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a0)
+; CHECK-NEXT:    lui a2, 524288
+; CHECK-NEXT:    xor a1, a1, a2
+; CHECK-NEXT:    sw a1, 0(a0)
+; CHECK-NEXT:    ret
+  %2 = load i32, ptr %0, align 4
+  %3 = xor i32 %2, -2147483648
+  store i32 %3, ptr %0, align 4
+  ret void
+}


        


More information about the llvm-commits mailing list