// or X, (select Cond, -1, 0) --> select Cond, -1, X
bool CanFoldNonConst =
(BinOpcode == ISD::AND || BinOpcode == ISD::OR) &&
- (isNullOrNullSplat(CT) || isAllOnesOrAllOnesSplat(CT)) &&
- (isNullOrNullSplat(CF) || isAllOnesOrAllOnesSplat(CF));
+ ((isNullOrNullSplat(CT) && isAllOnesOrAllOnesSplat(CF)) ||
+ (isNullOrNullSplat(CF) && isAllOnesOrAllOnesSplat(CT)));
SDValue CBO = BO->getOperand(SelOpNo ^ 1);
if (!CanFoldNonConst &&
!DAG.isConstantFPBuildVectorOrConstantFP(CBO))
return SDValue();
- // We have a select-of-constants followed by a binary operator with a
- // constant. Eliminate the binop by pulling the constant math into the select.
- // Example: add (select Cond, CT, CF), CBO --> select Cond, CT + CBO, CF + CBO
SDLoc DL(Sel);
- SDValue NewCT = SelOpNo ? DAG.getNode(BinOpcode, DL, VT, CBO, CT)
- : DAG.getNode(BinOpcode, DL, VT, CT, CBO);
- if (!CanFoldNonConst && !NewCT.isUndef() &&
- !isConstantOrConstantVector(NewCT, true) &&
- !DAG.isConstantFPBuildVectorOrConstantFP(NewCT))
- return SDValue();
+ SDValue NewCT, NewCF;
- SDValue NewCF = SelOpNo ? DAG.getNode(BinOpcode, DL, VT, CBO, CF)
- : DAG.getNode(BinOpcode, DL, VT, CF, CBO);
- if (!CanFoldNonConst && !NewCF.isUndef() &&
- !isConstantOrConstantVector(NewCF, true) &&
- !DAG.isConstantFPBuildVectorOrConstantFP(NewCF))
- return SDValue();
+ if (CanFoldNonConst) {
+ // If CBO is an opaque constant, we can't rely on getNode to constant fold.
+ if ((BinOpcode == ISD::AND && isNullOrNullSplat(CT)) ||
+ (BinOpcode == ISD::OR && isAllOnesOrAllOnesSplat(CT)))
+ NewCT = CT;
+ else
+ NewCT = CBO;
+
+ if ((BinOpcode == ISD::AND && isNullOrNullSplat(CF)) ||
+ (BinOpcode == ISD::OR && isAllOnesOrAllOnesSplat(CF)))
+ NewCF = CF;
+ else
+ NewCF = CBO;
+ } else {
+ // We have a select-of-constants followed by a binary operator with a
+ // constant. Eliminate the binop by pulling the constant math into the
+ // select. Example: add (select Cond, CT, CF), CBO --> select Cond, CT +
+ // CBO, CF + CBO
+ NewCT = SelOpNo ? DAG.getNode(BinOpcode, DL, VT, CBO, CT)
+ : DAG.getNode(BinOpcode, DL, VT, CT, CBO);
+ if (!CanFoldNonConst && !NewCT.isUndef() &&
+ !isConstantOrConstantVector(NewCT, true) &&
+ !DAG.isConstantFPBuildVectorOrConstantFP(NewCT))
+ return SDValue();
+
+ NewCF = SelOpNo ? DAG.getNode(BinOpcode, DL, VT, CBO, CF)
+ : DAG.getNode(BinOpcode, DL, VT, CF, CBO);
+ if (!CanFoldNonConst && !NewCF.isUndef() &&
+ !isConstantOrConstantVector(NewCF, true) &&
+ !DAG.isConstantFPBuildVectorOrConstantFP(NewCF))
+ return SDValue();
+ }
SDValue SelectOp = DAG.getSelect(DL, VT, Sel.getOperand(0), NewCT, NewCF);
SelectOp->setFlags(BO->getFlags());
--- /dev/null
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=riscv64 | FileCheck %s
+
+define i32 @f(i1 %0, i32 %1, ptr %2) {
+; CHECK-LABEL: f:
+; CHECK: # %bb.0: # %BB
+; CHECK-NEXT: slliw a3, a1, 11
+; CHECK-NEXT: slliw a1, a1, 12
+; CHECK-NEXT: subw a1, a1, a3
+; CHECK-NEXT: andi a0, a0, 1
+; CHECK-NEXT: neg a0, a0
+; CHECK-NEXT: lui a3, 1
+; CHECK-NEXT: addiw a3, a3, -2048
+; CHECK-NEXT: or a0, a0, a3
+; CHECK-NEXT: sw a1, 0(a2)
+; CHECK-NEXT: ret
+BB:
+ %I = select i1 %0, i32 -1, i32 0
+ %I1 = mul i32 %1, 2048
+ %I2 = or i32 2048, %I
+ store i32 %I1, ptr %2
+ ret i32 %I2
+}
+
+define i32 @g(i1 %0, i32 %1, ptr %2) {
+; CHECK-LABEL: g:
+; CHECK: # %bb.0: # %BB
+; CHECK-NEXT: slliw a3, a1, 11
+; CHECK-NEXT: slliw a1, a1, 12
+; CHECK-NEXT: subw a1, a1, a3
+; CHECK-NEXT: andi a0, a0, 1
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: lui a3, 1
+; CHECK-NEXT: addiw a3, a3, -2048
+; CHECK-NEXT: or a0, a0, a3
+; CHECK-NEXT: sw a1, 0(a2)
+; CHECK-NEXT: ret
+BB:
+ %I = select i1 %0, i32 0, i32 -1
+ %I1 = mul i32 %1, 2048
+ %I2 = or i32 2048, %I
+ store i32 %I1, ptr %2
+ ret i32 %I2
+}
+
+define i32 @h(i1 %0, i32 %1, ptr %2) {
+; CHECK-LABEL: h:
+; CHECK: # %bb.0: # %BB
+; CHECK-NEXT: slliw a3, a1, 11
+; CHECK-NEXT: slliw a1, a1, 12
+; CHECK-NEXT: subw a1, a1, a3
+; CHECK-NEXT: andi a0, a0, 1
+; CHECK-NEXT: slli a0, a0, 11
+; CHECK-NEXT: sw a1, 0(a2)
+; CHECK-NEXT: ret
+BB:
+ %I = select i1 %0, i32 -1, i32 0
+ %I1 = mul i32 %1, 2048
+ %I2 = and i32 2048, %I
+ store i32 %I1, ptr %2
+ ret i32 %I2
+}
+
+define i32 @i(i1 %0, i32 %1, ptr %2) {
+; CHECK-LABEL: i:
+; CHECK: # %bb.0: # %BB
+; CHECK-NEXT: andi a0, a0, 1
+; CHECK-NEXT: slliw a3, a1, 11
+; CHECK-NEXT: slliw a1, a1, 12
+; CHECK-NEXT: subw a1, a1, a3
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: lui a3, 1
+; CHECK-NEXT: addiw a3, a3, -2048
+; CHECK-NEXT: and a0, a0, a3
+; CHECK-NEXT: sw a1, 0(a2)
+; CHECK-NEXT: ret
+BB:
+ %I = select i1 %0, i32 0, i32 -1
+ %I1 = mul i32 %1, 2048
+ %I2 = and i32 2048, %I
+ store i32 %I1, ptr %2
+ ret i32 %I2
+}